xref: /btstack/src/ble/gatt-service/immediate_alert_service_client.c (revision 1663a09d71ad1d051ac7f5b42bd572d77deb1140)
1*1663a09dSMatthias Ringwald /*
2*1663a09dSMatthias Ringwald  * Copyright (C) 2024 BlueKitchen GmbH
3*1663a09dSMatthias Ringwald  *
4*1663a09dSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*1663a09dSMatthias Ringwald  * modification, are permitted provided that the following conditions
6*1663a09dSMatthias Ringwald  * are met:
7*1663a09dSMatthias Ringwald  *
8*1663a09dSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*1663a09dSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*1663a09dSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*1663a09dSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*1663a09dSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*1663a09dSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*1663a09dSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*1663a09dSMatthias Ringwald  *    from this software without specific prior written permission.
16*1663a09dSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*1663a09dSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*1663a09dSMatthias Ringwald  *    monetary gain.
19*1663a09dSMatthias Ringwald  *
20*1663a09dSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*1663a09dSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*1663a09dSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*1663a09dSMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*1663a09dSMatthias Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*1663a09dSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*1663a09dSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*1663a09dSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*1663a09dSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*1663a09dSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*1663a09dSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*1663a09dSMatthias Ringwald  * SUCH DAMAGE.
32*1663a09dSMatthias Ringwald  *
33*1663a09dSMatthias Ringwald  * Please inquire about commercial licensing options at
34*1663a09dSMatthias Ringwald  * [email protected]
35*1663a09dSMatthias Ringwald  *
36*1663a09dSMatthias Ringwald  */
37*1663a09dSMatthias Ringwald 
38*1663a09dSMatthias Ringwald #define BTSTACK_FILE__ "immediate_alert_service_client.c"
39*1663a09dSMatthias Ringwald 
40*1663a09dSMatthias Ringwald #include "btstack_config.h"
41*1663a09dSMatthias Ringwald 
42*1663a09dSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
43*1663a09dSMatthias Ringwald #include <stdio.h>
44*1663a09dSMatthias Ringwald #include <unistd.h>
45*1663a09dSMatthias Ringwald #endif
46*1663a09dSMatthias Ringwald 
47*1663a09dSMatthias Ringwald #include <stdint.h>
48*1663a09dSMatthias Ringwald #include <string.h>
49*1663a09dSMatthias Ringwald 
50*1663a09dSMatthias Ringwald #include "ble/gatt_service_client.h"
51*1663a09dSMatthias Ringwald #include "ble/gatt-service/immediate_alert_service_client.h"
52*1663a09dSMatthias Ringwald 
53*1663a09dSMatthias Ringwald #include "bluetooth_gatt.h"
54*1663a09dSMatthias Ringwald #include "btstack_debug.h"
55*1663a09dSMatthias Ringwald #include "btstack_event.h"
56*1663a09dSMatthias Ringwald 
57*1663a09dSMatthias Ringwald // IAS Client
58*1663a09dSMatthias Ringwald static gatt_service_client_t ias_client;
59*1663a09dSMatthias Ringwald static btstack_linked_list_t ias_connections;
60*1663a09dSMatthias Ringwald 
61*1663a09dSMatthias Ringwald static btstack_context_callback_registration_t ias_client_handle_can_send_now;
62*1663a09dSMatthias Ringwald 
63*1663a09dSMatthias Ringwald static void ias_client_packet_handler_internal(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
64*1663a09dSMatthias Ringwald static void ias_client_run_for_connection(void * context);
65*1663a09dSMatthias Ringwald 
66*1663a09dSMatthias Ringwald // list of uuids
67*1663a09dSMatthias Ringwald static const uint16_t ias_uuid16s[IMMEDIATE_ALERT_SERVICE_CLIENT_NUM_CHARACTERISTICS] = {
68*1663a09dSMatthias Ringwald     ORG_BLUETOOTH_CHARACTERISTIC_ALERT_LEVEL
69*1663a09dSMatthias Ringwald };
70*1663a09dSMatthias Ringwald 
71*1663a09dSMatthias Ringwald typedef enum {
72*1663a09dSMatthias Ringwald     IAS_CLIENT_CHARACTERISTIC_INDEX_ALERT_LEVEL = 0,
73*1663a09dSMatthias Ringwald     IAS_CLIENT_CHARACTERISTIC_INDEX_RFU
74*1663a09dSMatthias Ringwald } ias_client_characteristic_index_t;
75*1663a09dSMatthias Ringwald 
76*1663a09dSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
77*1663a09dSMatthias Ringwald static char * ias_client_characteristic_name[] = {
78*1663a09dSMatthias Ringwald     "ALERT_LEVEL",
79*1663a09dSMatthias Ringwald     "RFU"
80*1663a09dSMatthias Ringwald };
81*1663a09dSMatthias Ringwald #endif
82*1663a09dSMatthias Ringwald 
ias_client_get_connection_for_cid(uint16_t connection_cid)83*1663a09dSMatthias Ringwald static ias_client_connection_t * ias_client_get_connection_for_cid(uint16_t connection_cid){
84*1663a09dSMatthias Ringwald     btstack_linked_list_iterator_t it;
85*1663a09dSMatthias Ringwald     btstack_linked_list_iterator_init(&it,  &ias_connections);
86*1663a09dSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
87*1663a09dSMatthias Ringwald         ias_client_connection_t * connection = (ias_client_connection_t *)btstack_linked_list_iterator_next(&it);
88*1663a09dSMatthias Ringwald         if (gatt_service_client_get_connection_id(&connection->basic_connection) == connection_cid) {
89*1663a09dSMatthias Ringwald             return connection;
90*1663a09dSMatthias Ringwald         }
91*1663a09dSMatthias Ringwald     }
92*1663a09dSMatthias Ringwald     return NULL;
93*1663a09dSMatthias Ringwald }
94*1663a09dSMatthias Ringwald 
ias_client_add_connection(ias_client_connection_t * connection)95*1663a09dSMatthias Ringwald static void ias_client_add_connection(ias_client_connection_t * connection){
96*1663a09dSMatthias Ringwald     btstack_linked_list_add(&ias_connections, (btstack_linked_item_t*) connection);
97*1663a09dSMatthias Ringwald }
98*1663a09dSMatthias Ringwald 
ias_client_finalize_connection(ias_client_connection_t * connection)99*1663a09dSMatthias Ringwald static void ias_client_finalize_connection(ias_client_connection_t * connection){
100*1663a09dSMatthias Ringwald     btstack_linked_list_remove(&ias_connections, (btstack_linked_item_t*) connection);
101*1663a09dSMatthias Ringwald }
102*1663a09dSMatthias Ringwald 
ias_client_replace_subevent_id_and_emit(btstack_packet_handler_t callback,uint8_t * packet,uint16_t size,uint8_t subevent_id)103*1663a09dSMatthias Ringwald static void ias_client_replace_subevent_id_and_emit(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size, uint8_t subevent_id){
104*1663a09dSMatthias Ringwald     UNUSED(size);
105*1663a09dSMatthias Ringwald     btstack_assert(callback != NULL);
106*1663a09dSMatthias Ringwald     // execute callback
107*1663a09dSMatthias Ringwald     packet[2] = subevent_id;
108*1663a09dSMatthias Ringwald     (*callback)(HCI_EVENT_PACKET, 0, packet, size);
109*1663a09dSMatthias Ringwald }
110*1663a09dSMatthias Ringwald 
ias_client_connected(ias_client_connection_t * connection,uint8_t status,uint8_t * packet,uint16_t size)111*1663a09dSMatthias Ringwald static void ias_client_connected(ias_client_connection_t * connection, uint8_t status, uint8_t * packet, uint16_t size) {
112*1663a09dSMatthias Ringwald     if (status == ERROR_CODE_SUCCESS){
113*1663a09dSMatthias Ringwald         connection->state = IMMEDIATE_ALERT_SERVICE_CLIENT_STATE_READY;
114*1663a09dSMatthias Ringwald     } else {
115*1663a09dSMatthias Ringwald         connection->state = IMMEDIATE_ALERT_SERVICE_CLIENT_STATE_IDLE;
116*1663a09dSMatthias Ringwald     }
117*1663a09dSMatthias Ringwald     ias_client_replace_subevent_id_and_emit(connection->packet_handler, packet, size,
118*1663a09dSMatthias Ringwald                                             GATTSERVICE_SUBEVENT_IAS_CLIENT_CONNECTED);
119*1663a09dSMatthias Ringwald }
120*1663a09dSMatthias Ringwald 
121*1663a09dSMatthias Ringwald 
ias_client_value_handle_for_index(ias_client_connection_t * connection)122*1663a09dSMatthias Ringwald static uint16_t ias_client_value_handle_for_index(ias_client_connection_t * connection){
123*1663a09dSMatthias Ringwald     return connection->basic_connection.characteristics[connection->characteristic_index].value_handle;
124*1663a09dSMatthias Ringwald }
125*1663a09dSMatthias Ringwald 
ias_client_can_query_characteristic(ias_client_connection_t * connection,ias_client_characteristic_index_t characteristic_index)126*1663a09dSMatthias Ringwald static uint8_t ias_client_can_query_characteristic(ias_client_connection_t * connection, ias_client_characteristic_index_t characteristic_index){
127*1663a09dSMatthias Ringwald     uint8_t status = gatt_service_client_can_query_characteristic(&connection->basic_connection,
128*1663a09dSMatthias Ringwald                                                                   (uint8_t) characteristic_index);
129*1663a09dSMatthias Ringwald     if (status != ERROR_CODE_SUCCESS){
130*1663a09dSMatthias Ringwald         return status;
131*1663a09dSMatthias Ringwald     }
132*1663a09dSMatthias Ringwald     return connection->state == IMMEDIATE_ALERT_SERVICE_CLIENT_STATE_READY ? ERROR_CODE_SUCCESS : ERROR_CODE_CONTROLLER_BUSY;
133*1663a09dSMatthias Ringwald }
134*1663a09dSMatthias Ringwald 
ias_client_request_send_gatt_query(ias_client_connection_t * connection,ias_client_characteristic_index_t characteristic_index)135*1663a09dSMatthias Ringwald static uint8_t ias_client_request_send_gatt_query(ias_client_connection_t * connection, ias_client_characteristic_index_t characteristic_index){
136*1663a09dSMatthias Ringwald     connection->characteristic_index = characteristic_index;
137*1663a09dSMatthias Ringwald 
138*1663a09dSMatthias Ringwald     ias_client_handle_can_send_now.context = (void *)(uintptr_t)connection->basic_connection.cid;
139*1663a09dSMatthias Ringwald     uint8_t status = gatt_client_request_to_send_gatt_query(&ias_client_handle_can_send_now, connection->basic_connection.con_handle);
140*1663a09dSMatthias Ringwald     if (status != ERROR_CODE_SUCCESS){
141*1663a09dSMatthias Ringwald         connection->state = IMMEDIATE_ALERT_SERVICE_CLIENT_STATE_READY;
142*1663a09dSMatthias Ringwald     }
143*1663a09dSMatthias Ringwald     return status;
144*1663a09dSMatthias Ringwald }
145*1663a09dSMatthias Ringwald 
ias_client_request_write_without_response_characteristic(ias_client_connection_t * connection,ias_client_characteristic_index_t characteristic_index)146*1663a09dSMatthias Ringwald static uint8_t ias_client_request_write_without_response_characteristic(ias_client_connection_t * connection, ias_client_characteristic_index_t characteristic_index){
147*1663a09dSMatthias Ringwald     connection->state = IMMEDIATE_ALERT_SERVICE_CLIENT_STATE_W2_WRITE_WITHOUT_RESPONSE_CHARACTERISTIC_VALUE;
148*1663a09dSMatthias Ringwald     return ias_client_request_send_gatt_query(connection, characteristic_index);
149*1663a09dSMatthias Ringwald }
150*1663a09dSMatthias Ringwald 
ias_client_packet_handler_internal(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)151*1663a09dSMatthias Ringwald static void ias_client_packet_handler_internal(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
152*1663a09dSMatthias Ringwald     UNUSED(channel);
153*1663a09dSMatthias Ringwald     UNUSED(size);
154*1663a09dSMatthias Ringwald 
155*1663a09dSMatthias Ringwald     if (packet_type != HCI_EVENT_PACKET) return;
156*1663a09dSMatthias Ringwald     ias_client_connection_t * connection;
157*1663a09dSMatthias Ringwald     uint16_t cid;
158*1663a09dSMatthias Ringwald     uint8_t status;
159*1663a09dSMatthias Ringwald 
160*1663a09dSMatthias Ringwald     switch(hci_event_packet_get_type(packet)){
161*1663a09dSMatthias Ringwald         case HCI_EVENT_GATTSERVICE_META:
162*1663a09dSMatthias Ringwald             switch (hci_event_gattservice_meta_get_subevent_code(packet)) {
163*1663a09dSMatthias Ringwald                 case GATTSERVICE_SUBEVENT_CLIENT_CONNECTED:
164*1663a09dSMatthias Ringwald                     cid = gattservice_subevent_client_connected_get_cid(packet);
165*1663a09dSMatthias Ringwald                     connection = ias_client_get_connection_for_cid(cid);
166*1663a09dSMatthias Ringwald                     btstack_assert(connection != NULL);
167*1663a09dSMatthias Ringwald 
168*1663a09dSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
169*1663a09dSMatthias Ringwald                     {
170*1663a09dSMatthias Ringwald                         uint8_t i;
171*1663a09dSMatthias Ringwald                         for (i = IAS_CLIENT_CHARACTERISTIC_INDEX_ALERT_LEVEL;
172*1663a09dSMatthias Ringwald                              i < IAS_CLIENT_CHARACTERISTIC_INDEX_RFU; i++) {
173*1663a09dSMatthias Ringwald                             printf("0x%04X %s\n", connection->basic_connection.characteristics[i].value_handle,
174*1663a09dSMatthias Ringwald                                    ias_client_characteristic_name[i]);
175*1663a09dSMatthias Ringwald                         }
176*1663a09dSMatthias Ringwald                     };
177*1663a09dSMatthias Ringwald #endif
178*1663a09dSMatthias Ringwald                     status = gattservice_subevent_client_connected_get_status(packet);
179*1663a09dSMatthias Ringwald                     ias_client_connected(connection, status, packet, size);
180*1663a09dSMatthias Ringwald                     break;
181*1663a09dSMatthias Ringwald 
182*1663a09dSMatthias Ringwald                 case GATTSERVICE_SUBEVENT_CLIENT_DISCONNECTED:
183*1663a09dSMatthias Ringwald                     cid = gattservice_subevent_client_disconnected_get_cid(packet);
184*1663a09dSMatthias Ringwald                     connection = ias_client_get_connection_for_cid(cid);
185*1663a09dSMatthias Ringwald                     btstack_assert(connection != NULL);
186*1663a09dSMatthias Ringwald                     ias_client_finalize_connection(connection);
187*1663a09dSMatthias Ringwald                     ias_client_replace_subevent_id_and_emit(connection->packet_handler,
188*1663a09dSMatthias Ringwald                                                             packet, size,
189*1663a09dSMatthias Ringwald                                                             GATTSERVICE_SUBEVENT_IAS_CLIENT_DISCONNECTED);
190*1663a09dSMatthias Ringwald                     break;
191*1663a09dSMatthias Ringwald 
192*1663a09dSMatthias Ringwald                 default:
193*1663a09dSMatthias Ringwald                     break;
194*1663a09dSMatthias Ringwald             }
195*1663a09dSMatthias Ringwald             break;
196*1663a09dSMatthias Ringwald 
197*1663a09dSMatthias Ringwald         default:
198*1663a09dSMatthias Ringwald             break;
199*1663a09dSMatthias Ringwald     }
200*1663a09dSMatthias Ringwald }
201*1663a09dSMatthias Ringwald 
ias_client_serialize_characteristic_value_for_write(ias_client_connection_t * connection,uint8_t ** out_value)202*1663a09dSMatthias Ringwald static uint16_t ias_client_serialize_characteristic_value_for_write(ias_client_connection_t * connection, uint8_t ** out_value){
203*1663a09dSMatthias Ringwald     uint16_t characteristic_uuid16 = gatt_service_client_characteristic_uuid16_for_index(&ias_client,
204*1663a09dSMatthias Ringwald                                                                                          connection->characteristic_index);
205*1663a09dSMatthias Ringwald     *out_value = (uint8_t *)connection->write_buffer;
206*1663a09dSMatthias Ringwald 
207*1663a09dSMatthias Ringwald     switch (characteristic_uuid16){
208*1663a09dSMatthias Ringwald         case ORG_BLUETOOTH_CHARACTERISTIC_ALERT_LEVEL:
209*1663a09dSMatthias Ringwald             return 1;
210*1663a09dSMatthias Ringwald         default:
211*1663a09dSMatthias Ringwald             btstack_assert(false);
212*1663a09dSMatthias Ringwald             break;
213*1663a09dSMatthias Ringwald     }
214*1663a09dSMatthias Ringwald     return 0;
215*1663a09dSMatthias Ringwald }
216*1663a09dSMatthias Ringwald 
ias_client_run_for_connection(void * context)217*1663a09dSMatthias Ringwald static void ias_client_run_for_connection(void * context){
218*1663a09dSMatthias Ringwald     uint16_t connection_id = (uint16_t)(uintptr_t)context;
219*1663a09dSMatthias Ringwald     ias_client_connection_t * connection = ias_client_get_connection_for_cid(connection_id);
220*1663a09dSMatthias Ringwald 
221*1663a09dSMatthias Ringwald     btstack_assert(connection != NULL);
222*1663a09dSMatthias Ringwald     uint16_t value_length;
223*1663a09dSMatthias Ringwald     uint8_t * value;
224*1663a09dSMatthias Ringwald 
225*1663a09dSMatthias Ringwald     switch (connection->state){
226*1663a09dSMatthias Ringwald         case IMMEDIATE_ALERT_SERVICE_CLIENT_STATE_W2_WRITE_WITHOUT_RESPONSE_CHARACTERISTIC_VALUE:
227*1663a09dSMatthias Ringwald             connection->state = IMMEDIATE_ALERT_SERVICE_CLIENT_STATE_READY;
228*1663a09dSMatthias Ringwald 
229*1663a09dSMatthias Ringwald             value_length = ias_client_serialize_characteristic_value_for_write(connection, &value);
230*1663a09dSMatthias Ringwald             gatt_client_write_value_of_characteristic_without_response(
231*1663a09dSMatthias Ringwald                     gatt_service_client_get_con_handle(&connection->basic_connection),
232*1663a09dSMatthias Ringwald                     ias_client_value_handle_for_index(connection),
233*1663a09dSMatthias Ringwald                      value_length, value);
234*1663a09dSMatthias Ringwald 
235*1663a09dSMatthias Ringwald             break;
236*1663a09dSMatthias Ringwald 
237*1663a09dSMatthias Ringwald         default:
238*1663a09dSMatthias Ringwald             break;
239*1663a09dSMatthias Ringwald     }
240*1663a09dSMatthias Ringwald }
241*1663a09dSMatthias Ringwald 
immediate_alert_service_client_init(void)242*1663a09dSMatthias Ringwald void immediate_alert_service_client_init(void){
243*1663a09dSMatthias Ringwald     gatt_service_client_register_client(&ias_client, &ias_client_packet_handler_internal, ias_uuid16s,  sizeof(ias_uuid16s)/sizeof(uint16_t));
244*1663a09dSMatthias Ringwald 
245*1663a09dSMatthias Ringwald     ias_client_handle_can_send_now.callback = &ias_client_run_for_connection;
246*1663a09dSMatthias Ringwald }
247*1663a09dSMatthias Ringwald 
immediate_alert_service_client_connect(hci_con_handle_t con_handle,btstack_packet_handler_t packet_handler,ias_client_connection_t * ias_connection,uint16_t * ias_cid)248*1663a09dSMatthias Ringwald uint8_t immediate_alert_service_client_connect(hci_con_handle_t con_handle,
249*1663a09dSMatthias Ringwald     btstack_packet_handler_t packet_handler,
250*1663a09dSMatthias Ringwald     ias_client_connection_t * ias_connection,
251*1663a09dSMatthias Ringwald     uint16_t * ias_cid
252*1663a09dSMatthias Ringwald ){
253*1663a09dSMatthias Ringwald 
254*1663a09dSMatthias Ringwald     btstack_assert(packet_handler != NULL);
255*1663a09dSMatthias Ringwald     btstack_assert(ias_connection != NULL);
256*1663a09dSMatthias Ringwald 
257*1663a09dSMatthias Ringwald     *ias_cid = 0;
258*1663a09dSMatthias Ringwald 
259*1663a09dSMatthias Ringwald     ias_connection->state = IMMEDIATE_ALERT_SERVICE_CLIENT_STATE_W4_CONNECTION;
260*1663a09dSMatthias Ringwald     ias_connection->packet_handler = packet_handler;
261*1663a09dSMatthias Ringwald 
262*1663a09dSMatthias Ringwald     uint8_t status = gatt_service_client_connect_primary_service_with_uuid16(con_handle,
263*1663a09dSMatthias Ringwald                                                                              &ias_client,
264*1663a09dSMatthias Ringwald                                                                              &ias_connection->basic_connection,
265*1663a09dSMatthias Ringwald                                                                              ORG_BLUETOOTH_SERVICE_IMMEDIATE_ALERT, 0,
266*1663a09dSMatthias Ringwald                                                                              ias_connection->characteristics_storage,
267*1663a09dSMatthias Ringwald                                                                              IMMEDIATE_ALERT_SERVICE_CLIENT_NUM_CHARACTERISTICS);
268*1663a09dSMatthias Ringwald 
269*1663a09dSMatthias Ringwald     if (status == ERROR_CODE_SUCCESS){
270*1663a09dSMatthias Ringwald         ias_client_add_connection(ias_connection);
271*1663a09dSMatthias Ringwald         *ias_cid = ias_connection->basic_connection.cid;
272*1663a09dSMatthias Ringwald     }
273*1663a09dSMatthias Ringwald 
274*1663a09dSMatthias Ringwald     return status;
275*1663a09dSMatthias Ringwald }
276*1663a09dSMatthias Ringwald 
immediate_alert_service_client_write_alert_level(uint16_t ias_cid,ias_alert_level_t alert_level)277*1663a09dSMatthias Ringwald uint8_t immediate_alert_service_client_write_alert_level(uint16_t ias_cid, ias_alert_level_t alert_level){
278*1663a09dSMatthias Ringwald     ias_client_connection_t * connection = ias_client_get_connection_for_cid(ias_cid);
279*1663a09dSMatthias Ringwald     if (connection == NULL){
280*1663a09dSMatthias Ringwald         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
281*1663a09dSMatthias Ringwald     }
282*1663a09dSMatthias Ringwald     if (alert_level >= IAS_ALERT_LEVEL_RFU){
283*1663a09dSMatthias Ringwald         return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
284*1663a09dSMatthias Ringwald     }
285*1663a09dSMatthias Ringwald 
286*1663a09dSMatthias Ringwald     ias_client_characteristic_index_t index = IAS_CLIENT_CHARACTERISTIC_INDEX_ALERT_LEVEL;
287*1663a09dSMatthias Ringwald 
288*1663a09dSMatthias Ringwald     uint8_t status = ias_client_can_query_characteristic(connection, index);
289*1663a09dSMatthias Ringwald     if (status != ERROR_CODE_SUCCESS){
290*1663a09dSMatthias Ringwald         return status;
291*1663a09dSMatthias Ringwald     }
292*1663a09dSMatthias Ringwald 
293*1663a09dSMatthias Ringwald     connection->write_buffer[0] = (uint8_t)alert_level;
294*1663a09dSMatthias Ringwald     return ias_client_request_write_without_response_characteristic(connection, index);
295*1663a09dSMatthias Ringwald }
296*1663a09dSMatthias Ringwald 
immediate_alert_service_client_disconnect(uint16_t ias_cid)297*1663a09dSMatthias Ringwald uint8_t immediate_alert_service_client_disconnect(uint16_t ias_cid){
298*1663a09dSMatthias Ringwald     ias_client_connection_t * connection = ias_client_get_connection_for_cid(ias_cid);
299*1663a09dSMatthias Ringwald     if (connection == NULL){
300*1663a09dSMatthias Ringwald         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
301*1663a09dSMatthias Ringwald     }
302*1663a09dSMatthias Ringwald     return gatt_service_client_disconnect(&connection->basic_connection);
303*1663a09dSMatthias Ringwald }
304*1663a09dSMatthias Ringwald 
immediate_alert_service_client_deinit(void)305*1663a09dSMatthias Ringwald void immediate_alert_service_client_deinit(void){
306*1663a09dSMatthias Ringwald     gatt_service_client_unregister_client(&ias_client);
307*1663a09dSMatthias Ringwald }
308*1663a09dSMatthias Ringwald 
309