1 /* 2 * Copyright (C) 2021 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 #define BTSTACK_FILE__ "device_information_service_client.c" 39 40 #include "btstack_config.h" 41 42 #include <stdint.h> 43 #include <string.h> 44 45 #ifdef ENABLE_TESTING_SUPPORT 46 #include <stdio.h> 47 #endif 48 49 #include "ble/gatt-service/device_information_service_client.h" 50 51 #include "ble/core.h" 52 #include "ble/gatt_client.h" 53 #include "bluetooth_gatt.h" 54 #include "btstack_debug.h" 55 #include "btstack_event.h" 56 #include "gap.h" 57 58 #define DEVICE_INFORMATION_MAX_STRING_LEN 32 59 60 61 typedef enum { 62 DEVICE_INFORMATION_SERVICE_CLIENT_STATE_IDLE, 63 DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE, 64 DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT, 65 #ifdef ENABLE_TESTING_SUPPORT 66 DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_QUERY_CHARACTERISTICS, 67 DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_RESULT, 68 #endif 69 DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_READ_VALUE_OF_CHARACTERISTIC, 70 DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_VALUE 71 } device_information_service_client_state_t; 72 73 typedef struct { 74 hci_con_handle_t con_handle; 75 device_information_service_client_state_t state; 76 btstack_packet_handler_t client_handler; 77 78 // service 79 uint16_t start_handle; 80 uint16_t end_handle; 81 uint8_t num_instances; 82 83 // index of next characteristic to query 84 uint8_t characteristic_index; 85 } device_information_service_client_t; 86 87 88 static btstack_context_callback_registration_t device_information_service_handle_can_send_now; 89 90 static device_information_service_client_t device_information_service_client; 91 92 static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 93 static void device_information_service_emit_string_value(device_information_service_client_t * client, uint8_t subevent, uint8_t att_status, const uint8_t * value, uint16_t value_len); 94 static void device_information_service_emit_system_id(device_information_service_client_t * client, uint8_t subevent, uint8_t att_status, const uint8_t * value, uint16_t value_len); 95 static void device_information_service_emit_certification_data_list(device_information_service_client_t * client, uint8_t subevent, uint8_t att_status, const uint8_t * value, uint16_t value_len); 96 static void device_information_service_emit_pnp_id(device_information_service_client_t * client, uint8_t subevent, uint8_t att_status, const uint8_t * value, uint16_t value_len); 97 static void device_information_service_emit_udi_for_medical_devices(device_information_service_client_t * client, uint8_t subevent, uint8_t att_status, const uint8_t * value, uint16_t value_len); 98 99 // list of uuids and how they are reported as events 100 static const struct device_information_characteristic { 101 uint16_t uuid; 102 uint8_t subevent; 103 void (*handle_value)(device_information_service_client_t * client, uint8_t subevent, uint8_t att_status, const uint8_t * value, uint16_t value_len); 104 } device_information_characteristics[] = { 105 {ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING, GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_MANUFACTURER_NAME, device_information_service_emit_string_value}, 106 {ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING, GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_MODEL_NUMBER, device_information_service_emit_string_value}, 107 {ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING, GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_SERIAL_NUMBER, device_information_service_emit_string_value}, 108 {ORG_BLUETOOTH_CHARACTERISTIC_HARDWARE_REVISION_STRING, GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_HARDWARE_REVISION, device_information_service_emit_string_value}, 109 {ORG_BLUETOOTH_CHARACTERISTIC_FIRMWARE_REVISION_STRING, GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_FIRMWARE_REVISION, device_information_service_emit_string_value}, 110 {ORG_BLUETOOTH_CHARACTERISTIC_SOFTWARE_REVISION_STRING, GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_SOFTWARE_REVISION, device_information_service_emit_string_value}, 111 112 {ORG_BLUETOOTH_CHARACTERISTIC_SYSTEM_ID, GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_SYSTEM_ID, device_information_service_emit_system_id}, 113 {ORG_BLUETOOTH_CHARACTERISTIC_IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST, GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_IEEE_REGULATORY_CERTIFICATION, device_information_service_emit_certification_data_list}, 114 {ORG_BLUETOOTH_CHARACTERISTIC_PNP_ID, GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_PNP_ID, device_information_service_emit_pnp_id}, 115 {ORG_BLUETOOTH_CHARACTERISTIC_UDI_FOR_MEDICAL_DEVICES, GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_UDI_FOR_MEDICAL_DEVICES, device_information_service_emit_udi_for_medical_devices} 116 }; 117 118 static uint8_t device_informatiom_client_request_send_gatt_query(device_information_service_client_t * client){ 119 uint8_t status = gatt_client_request_to_send_gatt_query(&device_information_service_handle_can_send_now, client->con_handle); 120 if (status != ERROR_CODE_SUCCESS){ 121 if (client->state >= DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE){ 122 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_IDLE; 123 } 124 125 } 126 return status; 127 } 128 129 #ifdef ENABLE_TESTING_SUPPORT 130 static struct device_information_characteristic_handles{ 131 uint16_t uuid; 132 uint16_t value_handle; 133 } device_information_characteristic_handles[] = { 134 {ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING, 0}, 135 {ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING, 0}, 136 {ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING, 0}, 137 {ORG_BLUETOOTH_CHARACTERISTIC_HARDWARE_REVISION_STRING, 0}, 138 {ORG_BLUETOOTH_CHARACTERISTIC_FIRMWARE_REVISION_STRING, 0}, 139 {ORG_BLUETOOTH_CHARACTERISTIC_SOFTWARE_REVISION_STRING, 0}, 140 {ORG_BLUETOOTH_CHARACTERISTIC_SYSTEM_ID, 0}, 141 {ORG_BLUETOOTH_CHARACTERISTIC_IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST, 0}, 142 {ORG_BLUETOOTH_CHARACTERISTIC_PNP_ID, 0} 143 }; 144 145 static void device_information_service_update_handle_for_uuid(uint16_t uuid, uint16_t value_handle){ 146 uint8_t i; 147 for (i = 0; i < 9; i++){ 148 if (device_information_characteristic_handles[i].uuid == uuid){ 149 device_information_characteristic_handles[i].value_handle = value_handle; 150 return; 151 } 152 } 153 } 154 #endif 155 156 157 static const uint8_t num_information_fields = sizeof(device_information_characteristics)/sizeof(struct device_information_characteristic); 158 159 #ifdef ENABLE_TESTING_SUPPORT 160 static char * device_information_characteristic_name(uint16_t uuid){ 161 switch (uuid){ 162 case ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING: 163 return "MANUFACTURER_NAME_STRING"; 164 165 case ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING: 166 return "MODEL_NUMBER_STRING"; 167 168 case ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING: 169 return "SERIAL_NUMBER_STRING"; 170 171 case ORG_BLUETOOTH_CHARACTERISTIC_HARDWARE_REVISION_STRING: 172 return "HARDWARE_REVISION_STRING"; 173 174 case ORG_BLUETOOTH_CHARACTERISTIC_FIRMWARE_REVISION_STRING: 175 return "FIRMWARE_REVISION_STRING"; 176 177 case ORG_BLUETOOTH_CHARACTERISTIC_SOFTWARE_REVISION_STRING: 178 return "SOFTWARE_REVISION_STRING"; 179 180 case ORG_BLUETOOTH_CHARACTERISTIC_SYSTEM_ID: 181 return "SYSTEM_ID"; 182 183 case ORG_BLUETOOTH_CHARACTERISTIC_IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST: 184 return "IEEE_11073_20601_REGULATORY_CERTIFICATION_DATA_LIST"; 185 186 case ORG_BLUETOOTH_CHARACTERISTIC_PNP_ID: 187 return "PNP_ID"; 188 189 case ORG_BLUETOOTH_CHARACTERISTIC_UDI_FOR_MEDICAL_DEVICES: 190 return "ORG_BLUETOOTH_CHARACTERISTIC_UDI_FOR_MEDICAL_DEVICES"; 191 192 default: 193 return "UKNOWN"; 194 } 195 } 196 #endif 197 static device_information_service_client_t * device_information_service_client_get_client(void){ 198 return &device_information_service_client; 199 } 200 201 static device_information_service_client_t * device_information_service_get_client_for_con_handle(hci_con_handle_t con_handle){ 202 if (device_information_service_client.con_handle == con_handle){ 203 return &device_information_service_client; 204 } 205 return NULL; 206 } 207 208 static void device_information_service_finalize_client(device_information_service_client_t * client){ 209 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_IDLE; 210 client->con_handle = HCI_CON_HANDLE_INVALID; 211 client->client_handler = NULL; 212 client->num_instances = 0; 213 client->start_handle = 0; 214 client->end_handle = 0; 215 } 216 217 static void device_information_service_emit_query_done_and_finalize_client(device_information_service_client_t * client, uint8_t status){ 218 hci_con_handle_t con_handle = client->con_handle; 219 btstack_packet_handler_t callback = client->client_handler; 220 221 device_information_service_finalize_client(client); 222 223 uint8_t event[6]; 224 int pos = 0; 225 event[pos++] = HCI_EVENT_GATTSERVICE_META; 226 event[pos++] = sizeof(event) - 2; 227 event[pos++] = GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_DONE; 228 little_endian_store_16(event, pos, con_handle); 229 pos += 2; 230 event[pos++] = status; 231 (*callback)(HCI_EVENT_PACKET, 0, event, pos); 232 } 233 234 static void device_information_service_emit_string_value(device_information_service_client_t * client, uint8_t subevent, uint8_t att_status, const uint8_t * value, uint16_t value_len){ 235 uint8_t event[6 + DEVICE_INFORMATION_MAX_STRING_LEN + 1]; 236 int pos = 0; 237 238 event[pos++] = HCI_EVENT_GATTSERVICE_META; 239 pos++; 240 event[pos++] = subevent; 241 little_endian_store_16(event, pos, client->con_handle); 242 pos += 2; 243 event[pos++] = att_status; 244 245 uint16_t bytes_to_copy = btstack_min(value_len, DEVICE_INFORMATION_MAX_STRING_LEN); 246 memcpy((char*)&event[pos], value, bytes_to_copy); 247 pos += bytes_to_copy; 248 event[pos++] = 0; 249 250 event[1] = pos - 2; 251 (*client->client_handler)(HCI_EVENT_PACKET, 0, event, pos); 252 } 253 254 static void device_information_service_emit_system_id(device_information_service_client_t * client, uint8_t subevent, uint8_t att_status, const uint8_t * value, uint16_t value_len){ 255 if (value_len != 8) return; 256 257 uint8_t event[14]; 258 uint16_t pos = 0; 259 event[pos++] = HCI_EVENT_GATTSERVICE_META; 260 event[pos++] = sizeof(event) - 2; 261 event[pos++] = subevent; 262 little_endian_store_16(event, pos, client->con_handle); 263 pos += 2; 264 event[pos++] = att_status; 265 memcpy(event+pos, value, 8); 266 pos += 8; 267 268 (*client->client_handler)(HCI_EVENT_PACKET, 0, event, pos); 269 } 270 271 static void device_information_service_emit_certification_data_list(device_information_service_client_t * client, uint8_t subevent, uint8_t att_status, const uint8_t * value, uint16_t value_len){ 272 if (value_len != 4) return; 273 274 uint8_t event[10]; 275 int pos = 0; 276 event[pos++] = HCI_EVENT_GATTSERVICE_META; 277 event[pos++] = sizeof(event) - 2; 278 event[pos++] = subevent; 279 little_endian_store_16(event, pos, client->con_handle); 280 pos += 2; 281 event[pos++] = att_status; 282 memcpy(event + pos, value, 4); 283 pos += 4; 284 285 (*client->client_handler)(HCI_EVENT_PACKET, 0, event, pos); 286 } 287 288 static void device_information_service_emit_pnp_id(device_information_service_client_t * client, uint8_t subevent, uint8_t att_status, const uint8_t * value, uint16_t value_len){ 289 if (value_len != 7) return; 290 291 uint8_t event[13]; 292 uint16_t pos = 0; 293 event[pos++] = HCI_EVENT_GATTSERVICE_META; 294 event[pos++] = sizeof(event) - 2; 295 event[pos++] = subevent; 296 little_endian_store_16(event, pos, client->con_handle); 297 pos += 2; 298 event[pos++] = att_status; 299 memcpy(event + pos, value, 7); 300 pos += 7; 301 302 (*client->client_handler)(HCI_EVENT_PACKET, 0, event, pos); 303 } 304 305 static void device_information_service_emit_udi_for_medical_devices(device_information_service_client_t * client, uint8_t subevent, uint8_t att_status, const uint8_t * value, uint16_t value_len){ 306 uint16_t max_udi_length = 1 + 4 * DEVICE_INFORMATION_MAX_STRING_LEN; 307 308 if (value_len > max_udi_length) return; 309 310 uint8_t event[6 + 1 + 4 * DEVICE_INFORMATION_MAX_STRING_LEN]; 311 uint16_t pos = 0; 312 event[pos++] = HCI_EVENT_GATTSERVICE_META; 313 event[pos++] = sizeof(event) - 2; 314 event[pos++] = subevent; 315 little_endian_store_16(event, pos, client->con_handle); 316 pos += 2; 317 event[pos++] = att_status; 318 memcpy(event + pos, value, value_len); 319 pos += value_len; 320 321 (*client->client_handler)(HCI_EVENT_PACKET, 0, event, pos); 322 } 323 324 325 static void device_information_service_send_next_query(void * context){ 326 UNUSED(context); 327 device_information_service_client_t * client = device_information_service_client_get_client(); 328 329 if (client == NULL){ 330 return; 331 } 332 333 uint8_t att_status; 334 335 switch (client->state){ 336 case DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE: 337 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT; 338 att_status = gatt_client_discover_primary_services_by_uuid16(handle_gatt_client_event, client->con_handle, ORG_BLUETOOTH_SERVICE_DEVICE_INFORMATION); 339 // TODO handle status 340 UNUSED(att_status); 341 break; 342 #ifdef ENABLE_TESTING_SUPPORT 343 case DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_QUERY_CHARACTERISTICS: 344 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_RESULT; 345 gatt_client_discover_characteristics_for_handle_range_by_uuid16( 346 &handle_gatt_client_event, 347 client->con_handle, client->start_handle, client->end_handle, 348 device_information_characteristics[client->characteristic_index].uuid); 349 break; 350 #endif 351 352 case DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_READ_VALUE_OF_CHARACTERISTIC: 353 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_VALUE; 354 355 #ifdef ENABLE_TESTING_SUPPORT 356 att_status = gatt_client_read_value_of_characteristic_using_value_handle( 357 handle_gatt_client_event, 358 client->con_handle, 359 device_information_characteristic_handles[client->characteristic_index].value_handle); 360 #else 361 att_status = gatt_client_read_value_of_characteristics_by_uuid16( 362 handle_gatt_client_event, 363 client->con_handle, client->start_handle, client->end_handle, 364 device_information_characteristics[client->characteristic_index].uuid); 365 #endif 366 // TODO handle status 367 UNUSED(att_status); 368 break; 369 370 default: 371 break; 372 } 373 } 374 375 static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 376 UNUSED(packet_type); 377 UNUSED(channel); 378 UNUSED(size); 379 380 uint8_t att_status; 381 device_information_service_client_t * client = NULL; 382 gatt_client_service_t service; 383 384 #ifdef ENABLE_TESTING_SUPPORT 385 gatt_client_characteristic_t characteristic; 386 #endif 387 388 switch(hci_event_packet_get_type(packet)){ 389 390 case GATT_EVENT_SERVICE_QUERY_RESULT: 391 client = device_information_service_get_client_for_con_handle(gatt_event_service_query_result_get_handle(packet)); 392 btstack_assert(client != NULL); 393 394 gatt_event_service_query_result_get_service(packet, &service); 395 client->start_handle = service.start_group_handle; 396 client->end_handle = service.end_group_handle; 397 398 client->characteristic_index = 0; 399 if (client->start_handle < client->end_handle){ 400 client->num_instances++; 401 } 402 #ifdef ENABLE_TESTING_SUPPORT 403 printf("Device Information Service: start handle 0x%04X, end handle 0x%04X, num_instances %d\n", client->start_handle, client->end_handle, client->num_instances); 404 #endif 405 break; 406 407 #ifdef ENABLE_TESTING_SUPPORT 408 case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT: 409 client = device_information_service_get_client_for_con_handle(gatt_event_characteristic_query_result_get_handle(packet)); 410 btstack_assert(client != NULL); 411 gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic); 412 413 device_information_service_update_handle_for_uuid(characteristic.uuid16, characteristic.value_handle); 414 printf("Device Information Characteristic %s: \n Attribute Handle 0x%04X, Properties 0x%02X, Handle 0x%04X, UUID 0x%04X\n", 415 device_information_characteristic_name(characteristic.uuid16), 416 characteristic.start_handle, 417 characteristic.properties, 418 characteristic.value_handle, characteristic.uuid16); 419 break; 420 #endif 421 case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT: 422 client = device_information_service_get_client_for_con_handle(gatt_event_characteristic_value_query_result_get_handle(packet)); 423 btstack_assert(client != NULL); 424 425 426 (device_information_characteristics[client->characteristic_index].handle_value( 427 client, device_information_characteristics[client->characteristic_index].subevent, 428 ATT_ERROR_SUCCESS, 429 gatt_event_characteristic_value_query_result_get_value(packet), 430 gatt_event_characteristic_value_query_result_get_value_length(packet))); 431 break; 432 433 case GATT_EVENT_QUERY_COMPLETE: 434 client = device_information_service_get_client_for_con_handle(gatt_event_query_complete_get_handle(packet)); 435 btstack_assert(client != NULL); 436 437 att_status = gatt_event_query_complete_get_att_status(packet); 438 switch (client->state){ 439 case DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT: 440 if (att_status != ATT_ERROR_SUCCESS){ 441 device_information_service_emit_query_done_and_finalize_client(client, att_status); 442 return; 443 } 444 445 if (client->num_instances != 1){ 446 device_information_service_emit_query_done_and_finalize_client(client, ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE); 447 return; 448 } 449 client->characteristic_index = 0; 450 451 #ifdef ENABLE_TESTING_SUPPORT 452 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_QUERY_CHARACTERISTICS; 453 #else 454 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_READ_VALUE_OF_CHARACTERISTIC; 455 #endif 456 break; 457 458 #ifdef ENABLE_TESTING_SUPPORT 459 case DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_RESULT: 460 // check if there is another characteristic to query 461 if ((client->characteristic_index + 1) < num_information_fields){ 462 client->characteristic_index++; 463 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_QUERY_CHARACTERISTICS; 464 break; 465 } 466 client->characteristic_index = 0; 467 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_READ_VALUE_OF_CHARACTERISTIC; 468 break; 469 #endif 470 case DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_VALUE: 471 // check if there is another characteristic to query 472 if ((client->characteristic_index + 1) < num_information_fields){ 473 client->characteristic_index++; 474 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_READ_VALUE_OF_CHARACTERISTIC; 475 break; 476 } 477 // we are done with quering all characteristics 478 device_information_service_emit_query_done_and_finalize_client(client, ERROR_CODE_SUCCESS); 479 return; 480 481 default: 482 break; 483 } 484 break; 485 default: 486 break; 487 } 488 489 if (client && client->state != DEVICE_INFORMATION_SERVICE_CLIENT_STATE_IDLE){ 490 device_informatiom_client_request_send_gatt_query(client); 491 } 492 } 493 494 uint8_t device_information_service_client_query(hci_con_handle_t con_handle, btstack_packet_handler_t packet_handler){ 495 btstack_assert(packet_handler != NULL); 496 device_information_service_client_t * client = device_information_service_get_client_for_con_handle(con_handle); 497 498 if (client != NULL){ 499 return ERROR_CODE_COMMAND_DISALLOWED; 500 } 501 502 client = device_information_service_client_get_client(); 503 504 if (client->con_handle != HCI_CON_HANDLE_INVALID) { 505 return ERROR_CODE_COMMAND_DISALLOWED; 506 } 507 508 client->con_handle = con_handle; 509 client->client_handler = packet_handler; 510 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE; 511 512 device_informatiom_client_request_send_gatt_query(client); 513 return ERROR_CODE_SUCCESS; 514 } 515 516 517 void device_information_service_client_init(void){ 518 device_information_service_client_t * client = device_information_service_client_get_client(); 519 device_information_service_finalize_client(client); 520 device_information_service_handle_can_send_now.callback = &device_information_service_send_next_query; 521 } 522 523 void device_information_service_client_deinit(void){} 524 525 // unit test only 526 #if defined __cplusplus 527 extern "C" 528 #endif 529 void device_information_service_client_set_invalid_state(void); 530 void device_information_service_client_set_invalid_state(void){ 531 device_information_service_client_t * client = device_information_service_client_get_client(); 532 client->state = DEVICE_INFORMATION_SERVICE_CLIENT_STATE_IDLE; 533 } 534