gatt_client.c (5611a760af48d1ce1beea59c7908be73bd2393f1) gatt_client.c (f8fbdce0c5067e7e7edd3a29934b1f9b79c8ff2d)
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

--- 226 unchanged lines hidden (view full) ---

235 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 1);
236}
237
238// precondition: can_send_packet_now == TRUE
239static void att_find_information_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle){
240 l2cap_reserve_packet_buffer();
241 uint8_t * request = l2cap_get_outgoing_buffer();
242 request[0] = request_type;
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

--- 226 unchanged lines hidden (view full) ---

235 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 1);
236}
237
238// precondition: can_send_packet_now == TRUE
239static void att_find_information_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle){
240 l2cap_reserve_packet_buffer();
241 uint8_t * request = l2cap_get_outgoing_buffer();
242 request[0] = request_type;
243 bt_store_16(request, 1, start_handle);
244 bt_store_16(request, 3, end_handle);
243 little_endian_store_16(request, 1, start_handle);
244 little_endian_store_16(request, 3, end_handle);
245
246 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5);
247}
248
249// precondition: can_send_packet_now == TRUE
250static void att_find_by_type_value_request(uint16_t request_type, uint16_t attribute_group_type, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle, uint8_t * value, uint16_t value_size){
251 l2cap_reserve_packet_buffer();
252 uint8_t * request = l2cap_get_outgoing_buffer();
253
254 request[0] = request_type;
245
246 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5);
247}
248
249// precondition: can_send_packet_now == TRUE
250static void att_find_by_type_value_request(uint16_t request_type, uint16_t attribute_group_type, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle, uint8_t * value, uint16_t value_size){
251 l2cap_reserve_packet_buffer();
252 uint8_t * request = l2cap_get_outgoing_buffer();
253
254 request[0] = request_type;
255 bt_store_16(request, 1, start_handle);
256 bt_store_16(request, 3, end_handle);
257 bt_store_16(request, 5, attribute_group_type);
255 little_endian_store_16(request, 1, start_handle);
256 little_endian_store_16(request, 3, end_handle);
257 little_endian_store_16(request, 5, attribute_group_type);
258 memcpy(&request[7], value, value_size);
259
260 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 7+value_size);
261}
262
263// precondition: can_send_packet_now == TRUE
264static void att_read_by_type_or_group_request_for_uuid16(uint16_t request_type, uint16_t uuid16, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle){
265 l2cap_reserve_packet_buffer();
266 uint8_t * request = l2cap_get_outgoing_buffer();
267 request[0] = request_type;
258 memcpy(&request[7], value, value_size);
259
260 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 7+value_size);
261}
262
263// precondition: can_send_packet_now == TRUE
264static void att_read_by_type_or_group_request_for_uuid16(uint16_t request_type, uint16_t uuid16, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle){
265 l2cap_reserve_packet_buffer();
266 uint8_t * request = l2cap_get_outgoing_buffer();
267 request[0] = request_type;
268 bt_store_16(request, 1, start_handle);
269 bt_store_16(request, 3, end_handle);
270 bt_store_16(request, 5, uuid16);
268 little_endian_store_16(request, 1, start_handle);
269 little_endian_store_16(request, 3, end_handle);
270 little_endian_store_16(request, 5, uuid16);
271
272 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 7);
273}
274
275// precondition: can_send_packet_now == TRUE
276static void att_read_by_type_or_group_request_for_uuid128(uint16_t request_type, uint8_t * uuid128, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle){
277 l2cap_reserve_packet_buffer();
278 uint8_t * request = l2cap_get_outgoing_buffer();
279 request[0] = request_type;
271
272 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 7);
273}
274
275// precondition: can_send_packet_now == TRUE
276static void att_read_by_type_or_group_request_for_uuid128(uint16_t request_type, uint8_t * uuid128, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle){
277 l2cap_reserve_packet_buffer();
278 uint8_t * request = l2cap_get_outgoing_buffer();
279 request[0] = request_type;
280 bt_store_16(request, 1, start_handle);
281 bt_store_16(request, 3, end_handle);
280 little_endian_store_16(request, 1, start_handle);
281 little_endian_store_16(request, 3, end_handle);
282 swap128(uuid128, &request[5]);
283
284 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 21);
285}
286
287// precondition: can_send_packet_now == TRUE
288static void att_read_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle){
289 l2cap_reserve_packet_buffer();
290 uint8_t * request = l2cap_get_outgoing_buffer();
291 request[0] = request_type;
282 swap128(uuid128, &request[5]);
283
284 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 21);
285}
286
287// precondition: can_send_packet_now == TRUE
288static void att_read_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle){
289 l2cap_reserve_packet_buffer();
290 uint8_t * request = l2cap_get_outgoing_buffer();
291 request[0] = request_type;
292 bt_store_16(request, 1, attribute_handle);
292 little_endian_store_16(request, 1, attribute_handle);
293
294 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3);
295}
296
297// precondition: can_send_packet_now == TRUE
298static void att_read_blob_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_offset){
299 l2cap_reserve_packet_buffer();
300 uint8_t * request = l2cap_get_outgoing_buffer();
301 request[0] = request_type;
293
294 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3);
295}
296
297// precondition: can_send_packet_now == TRUE
298static void att_read_blob_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_offset){
299 l2cap_reserve_packet_buffer();
300 uint8_t * request = l2cap_get_outgoing_buffer();
301 request[0] = request_type;
302 bt_store_16(request, 1, attribute_handle);
303 bt_store_16(request, 3, value_offset);
302 little_endian_store_16(request, 1, attribute_handle);
303 little_endian_store_16(request, 3, value_offset);
304
305 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5);
306}
307
308static void att_read_multiple_request(uint16_t peripheral_handle, uint16_t num_value_handles, uint16_t * value_handles){
309 l2cap_reserve_packet_buffer();
310 uint8_t * request = l2cap_get_outgoing_buffer();
311 request[0] = ATT_READ_MULTIPLE_REQUEST;
312 int i;
313 int offset = 1;
314 for (i=0;i<num_value_handles;i++){
304
305 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5);
306}
307
308static void att_read_multiple_request(uint16_t peripheral_handle, uint16_t num_value_handles, uint16_t * value_handles){
309 l2cap_reserve_packet_buffer();
310 uint8_t * request = l2cap_get_outgoing_buffer();
311 request[0] = ATT_READ_MULTIPLE_REQUEST;
312 int i;
313 int offset = 1;
314 for (i=0;i<num_value_handles;i++){
315 bt_store_16(request, offset, value_handles[i]);
315 little_endian_store_16(request, offset, value_handles[i]);
316 offset += 2;
317 }
318 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, offset);
319}
320
321// precondition: can_send_packet_now == TRUE
322static void att_signed_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_length, uint8_t * value, uint32_t sign_counter, uint8_t sgn[8]){
323 l2cap_reserve_packet_buffer();
324 uint8_t * request = l2cap_get_outgoing_buffer();
325 request[0] = request_type;
316 offset += 2;
317 }
318 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, offset);
319}
320
321// precondition: can_send_packet_now == TRUE
322static void att_signed_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_length, uint8_t * value, uint32_t sign_counter, uint8_t sgn[8]){
323 l2cap_reserve_packet_buffer();
324 uint8_t * request = l2cap_get_outgoing_buffer();
325 request[0] = request_type;
326 bt_store_16(request, 1, attribute_handle);
326 little_endian_store_16(request, 1, attribute_handle);
327 memcpy(&request[3], value, value_length);
327 memcpy(&request[3], value, value_length);
328 bt_store_32(request, 3 + value_length, sign_counter);
328 little_endian_store_32(request, 3 + value_length, sign_counter);
329 swap64(sgn, &request[3 + value_length + 4]);
330 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length + 12);
331}
332
333// precondition: can_send_packet_now == TRUE
334static void att_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_length, uint8_t * value){
335 l2cap_reserve_packet_buffer();
336 uint8_t * request = l2cap_get_outgoing_buffer();
337 request[0] = request_type;
329 swap64(sgn, &request[3 + value_length + 4]);
330 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length + 12);
331}
332
333// precondition: can_send_packet_now == TRUE
334static void att_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_length, uint8_t * value){
335 l2cap_reserve_packet_buffer();
336 uint8_t * request = l2cap_get_outgoing_buffer();
337 request[0] = request_type;
338 bt_store_16(request, 1, attribute_handle);
338 little_endian_store_16(request, 1, attribute_handle);
339 memcpy(&request[3], value, value_length);
340
341 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length);
342}
343
344// precondition: can_send_packet_now == TRUE
345static void att_execute_write_request(uint16_t request_type, uint16_t peripheral_handle, uint8_t execute_write){
346 l2cap_reserve_packet_buffer();
347 uint8_t * request = l2cap_get_outgoing_buffer();
348 request[0] = request_type;
349 request[1] = execute_write;
350 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 2);
351}
352
353// precondition: can_send_packet_now == TRUE
354static void att_prepare_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_offset, uint16_t blob_length, uint8_t * value){
355 l2cap_reserve_packet_buffer();
356 uint8_t * request = l2cap_get_outgoing_buffer();
357 request[0] = request_type;
339 memcpy(&request[3], value, value_length);
340
341 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length);
342}
343
344// precondition: can_send_packet_now == TRUE
345static void att_execute_write_request(uint16_t request_type, uint16_t peripheral_handle, uint8_t execute_write){
346 l2cap_reserve_packet_buffer();
347 uint8_t * request = l2cap_get_outgoing_buffer();
348 request[0] = request_type;
349 request[1] = execute_write;
350 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 2);
351}
352
353// precondition: can_send_packet_now == TRUE
354static void att_prepare_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_offset, uint16_t blob_length, uint8_t * value){
355 l2cap_reserve_packet_buffer();
356 uint8_t * request = l2cap_get_outgoing_buffer();
357 request[0] = request_type;
358 bt_store_16(request, 1, attribute_handle);
359 bt_store_16(request, 3, value_offset);
358 little_endian_store_16(request, 1, attribute_handle);
359 little_endian_store_16(request, 3, value_offset);
360 memcpy(&request[5], &value[value_offset], blob_length);
361
362 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5+blob_length);
363}
364
365static void att_exchange_mtu_request(uint16_t peripheral_handle){
366 uint16_t mtu = l2cap_max_le_mtu();
367 l2cap_reserve_packet_buffer();
368 uint8_t * request = l2cap_get_outgoing_buffer();
369 request[0] = ATT_EXCHANGE_MTU_REQUEST;
360 memcpy(&request[5], &value[value_offset], blob_length);
361
362 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5+blob_length);
363}
364
365static void att_exchange_mtu_request(uint16_t peripheral_handle){
366 uint16_t mtu = l2cap_max_le_mtu();
367 l2cap_reserve_packet_buffer();
368 uint8_t * request = l2cap_get_outgoing_buffer();
369 request[0] = ATT_EXCHANGE_MTU_REQUEST;
370 bt_store_16(request, 1, mtu);
370 little_endian_store_16(request, 1, mtu);
371 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3);
372}
373
374static uint16_t write_blob_length(gatt_client_t * peripheral){
375 uint16_t max_blob_length = peripheral_mtu(peripheral) - 5;
376 if (peripheral->attribute_offset >= peripheral->attribute_length) {
377 return 0;
378 }

--- 6 unchanged lines hidden (view full) ---

385
386static void send_gatt_services_request(gatt_client_t *peripheral){
387 att_read_by_type_or_group_request_for_uuid16(ATT_READ_BY_GROUP_TYPE_REQUEST, GATT_PRIMARY_SERVICE_UUID, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle);
388}
389
390static void send_gatt_by_uuid_request(gatt_client_t *peripheral, uint16_t attribute_group_type){
391 if (peripheral->uuid16){
392 uint8_t uuid16[2];
371 l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3);
372}
373
374static uint16_t write_blob_length(gatt_client_t * peripheral){
375 uint16_t max_blob_length = peripheral_mtu(peripheral) - 5;
376 if (peripheral->attribute_offset >= peripheral->attribute_length) {
377 return 0;
378 }

--- 6 unchanged lines hidden (view full) ---

385
386static void send_gatt_services_request(gatt_client_t *peripheral){
387 att_read_by_type_or_group_request_for_uuid16(ATT_READ_BY_GROUP_TYPE_REQUEST, GATT_PRIMARY_SERVICE_UUID, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle);
388}
389
390static void send_gatt_by_uuid_request(gatt_client_t *peripheral, uint16_t attribute_group_type){
391 if (peripheral->uuid16){
392 uint8_t uuid16[2];
393 bt_store_16(uuid16, 0, peripheral->uuid16);
393 little_endian_store_16(uuid16, 0, peripheral->uuid16);
394 att_find_by_type_value_request(ATT_FIND_BY_TYPE_VALUE_REQUEST, attribute_group_type, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle, uuid16, 2);
395 return;
396 }
397 uint8_t uuid128[16];
398 swap128(peripheral->uuid128, uuid128);
399 att_find_by_type_value_request(ATT_FIND_BY_TYPE_VALUE_REQUEST, attribute_group_type, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle, uuid128, 16);
400}
401

--- 66 unchanged lines hidden (view full) ---

468}
469
470static void send_gatt_signed_write_request(gatt_client_t * peripheral, uint32_t sign_counter){
471 att_signed_write_request(ATT_SIGNED_WRITE_COMMAND, peripheral->handle, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value, sign_counter, peripheral->cmac);
472}
473
474static uint16_t get_last_result_handle_from_service_list(uint8_t * packet, uint16_t size){
475 uint8_t attr_length = packet[1];
394 att_find_by_type_value_request(ATT_FIND_BY_TYPE_VALUE_REQUEST, attribute_group_type, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle, uuid16, 2);
395 return;
396 }
397 uint8_t uuid128[16];
398 swap128(peripheral->uuid128, uuid128);
399 att_find_by_type_value_request(ATT_FIND_BY_TYPE_VALUE_REQUEST, attribute_group_type, peripheral->handle, peripheral->start_group_handle, peripheral->end_group_handle, uuid128, 16);
400}
401

--- 66 unchanged lines hidden (view full) ---

468}
469
470static void send_gatt_signed_write_request(gatt_client_t * peripheral, uint32_t sign_counter){
471 att_signed_write_request(ATT_SIGNED_WRITE_COMMAND, peripheral->handle, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value, sign_counter, peripheral->cmac);
472}
473
474static uint16_t get_last_result_handle_from_service_list(uint8_t * packet, uint16_t size){
475 uint8_t attr_length = packet[1];
476 return READ_BT_16(packet, size - attr_length + 2);
476 return little_endian_read_16(packet, size - attr_length + 2);
477}
478
479static uint16_t get_last_result_handle_from_characteristics_list(uint8_t * packet, uint16_t size){
480 uint8_t attr_length = packet[1];
477}
478
479static uint16_t get_last_result_handle_from_characteristics_list(uint8_t * packet, uint16_t size){
480 uint8_t attr_length = packet[1];
481 return READ_BT_16(packet, size - attr_length + 3);
481 return little_endian_read_16(packet, size - attr_length + 3);
482}
483
484static uint16_t get_last_result_handle_from_included_services_list(uint8_t * packet, uint16_t size){
485 uint8_t attr_length = packet[1];
482}
483
484static uint16_t get_last_result_handle_from_included_services_list(uint8_t * packet, uint16_t size){
485 uint8_t attr_length = packet[1];
486 return READ_BT_16(packet, size - attr_length);
486 return little_endian_read_16(packet, size - attr_length);
487}
488
489static void gatt_client_handle_transaction_complete(gatt_client_t * peripheral){
490 peripheral->gatt_client_state = P_READY;
491 gatt_client_timeout_stop(peripheral);
492}
493
494static void emit_event_new(uint16_t gatt_client_id, uint8_t * packet, uint16_t size){

--- 11 unchanged lines hidden (view full) ---

506 }
507}
508
509static void emit_gatt_complete_event(gatt_client_t * peripheral, uint8_t status){
510 // @format H1
511 uint8_t packet[5];
512 packet[0] = GATT_EVENT_QUERY_COMPLETE;
513 packet[1] = 3;
487}
488
489static void gatt_client_handle_transaction_complete(gatt_client_t * peripheral){
490 peripheral->gatt_client_state = P_READY;
491 gatt_client_timeout_stop(peripheral);
492}
493
494static void emit_event_new(uint16_t gatt_client_id, uint8_t * packet, uint16_t size){

--- 11 unchanged lines hidden (view full) ---

506 }
507}
508
509static void emit_gatt_complete_event(gatt_client_t * peripheral, uint8_t status){
510 // @format H1
511 uint8_t packet[5];
512 packet[0] = GATT_EVENT_QUERY_COMPLETE;
513 packet[1] = 3;
514 bt_store_16(packet, 2, peripheral->handle);
514 little_endian_store_16(packet, 2, peripheral->handle);
515 packet[4] = status;
516 emit_event_new(peripheral->subclient_id, packet, sizeof(packet));
517}
518
519static void emit_gatt_service_query_result_event(gatt_client_t * peripheral, uint16_t start_group_handle, uint16_t end_group_handle, uint8_t * uuid128){
520 // @format HX
521 uint8_t packet[24];
522 packet[0] = GATT_EVENT_SERVICE_QUERY_RESULT;
523 packet[1] = sizeof(packet) - 2;
515 packet[4] = status;
516 emit_event_new(peripheral->subclient_id, packet, sizeof(packet));
517}
518
519static void emit_gatt_service_query_result_event(gatt_client_t * peripheral, uint16_t start_group_handle, uint16_t end_group_handle, uint8_t * uuid128){
520 // @format HX
521 uint8_t packet[24];
522 packet[0] = GATT_EVENT_SERVICE_QUERY_RESULT;
523 packet[1] = sizeof(packet) - 2;
524 bt_store_16(packet, 2, peripheral->handle);
524 little_endian_store_16(packet, 2, peripheral->handle);
525 ///
525 ///
526 bt_store_16(packet, 4, start_group_handle);
527 bt_store_16(packet, 6, end_group_handle);
526 little_endian_store_16(packet, 4, start_group_handle);
527 little_endian_store_16(packet, 6, end_group_handle);
528 swap128(uuid128, &packet[8]);
529 emit_event_new(peripheral->subclient_id, packet, sizeof(packet));
530}
531
532static void emit_gatt_included_service_query_result_event(gatt_client_t * peripheral, uint16_t include_handle, uint16_t start_group_handle, uint16_t end_group_handle, uint8_t * uuid128){
533 // @format HX
534 uint8_t packet[26];
535 packet[0] = GATT_EVENT_INCLUDED_SERVICE_QUERY_RESULT;
536 packet[1] = sizeof(packet) - 2;
528 swap128(uuid128, &packet[8]);
529 emit_event_new(peripheral->subclient_id, packet, sizeof(packet));
530}
531
532static void emit_gatt_included_service_query_result_event(gatt_client_t * peripheral, uint16_t include_handle, uint16_t start_group_handle, uint16_t end_group_handle, uint8_t * uuid128){
533 // @format HX
534 uint8_t packet[26];
535 packet[0] = GATT_EVENT_INCLUDED_SERVICE_QUERY_RESULT;
536 packet[1] = sizeof(packet) - 2;
537 bt_store_16(packet, 2, peripheral->handle);
537 little_endian_store_16(packet, 2, peripheral->handle);
538 ///
538 ///
539 bt_store_16(packet, 4, include_handle);
539 little_endian_store_16(packet, 4, include_handle);
540 //
540 //
541 bt_store_16(packet, 6, start_group_handle);
542 bt_store_16(packet, 8, end_group_handle);
541 little_endian_store_16(packet, 6, start_group_handle);
542 little_endian_store_16(packet, 8, end_group_handle);
543 swap128(uuid128, &packet[10]);
544 emit_event_new(peripheral->subclient_id, packet, sizeof(packet));
545}
546
547static void emit_gatt_characteristic_query_result_event(gatt_client_t * peripheral, uint16_t start_handle, uint16_t value_handle, uint16_t end_handle,
548 uint16_t properties, uint8_t * uuid128){
549 // @format HY
550 uint8_t packet[28];
551 packet[0] = GATT_EVENT_CHARACTERISTIC_QUERY_RESULT;
552 packet[1] = sizeof(packet) - 2;
543 swap128(uuid128, &packet[10]);
544 emit_event_new(peripheral->subclient_id, packet, sizeof(packet));
545}
546
547static void emit_gatt_characteristic_query_result_event(gatt_client_t * peripheral, uint16_t start_handle, uint16_t value_handle, uint16_t end_handle,
548 uint16_t properties, uint8_t * uuid128){
549 // @format HY
550 uint8_t packet[28];
551 packet[0] = GATT_EVENT_CHARACTERISTIC_QUERY_RESULT;
552 packet[1] = sizeof(packet) - 2;
553 bt_store_16(packet, 2, peripheral->handle);
553 little_endian_store_16(packet, 2, peripheral->handle);
554 ///
554 ///
555 bt_store_16(packet, 4, start_handle);
556 bt_store_16(packet, 6, value_handle);
557 bt_store_16(packet, 8, end_handle);
558 bt_store_16(packet, 10, properties);
555 little_endian_store_16(packet, 4, start_handle);
556 little_endian_store_16(packet, 6, value_handle);
557 little_endian_store_16(packet, 8, end_handle);
558 little_endian_store_16(packet, 10, properties);
559 swap128(uuid128, &packet[12]);
560 emit_event_new(peripheral->subclient_id, packet, sizeof(packet));
561}
562
563static void emit_gatt_all_characteristic_descriptors_result_event(
564 gatt_client_t * peripheral, uint16_t descriptor_handle, uint8_t * uuid128){
565 // @format HZ
566 uint8_t packet[22];
567 packet[0] = GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT;
568 packet[1] = sizeof(packet) - 2;
559 swap128(uuid128, &packet[12]);
560 emit_event_new(peripheral->subclient_id, packet, sizeof(packet));
561}
562
563static void emit_gatt_all_characteristic_descriptors_result_event(
564 gatt_client_t * peripheral, uint16_t descriptor_handle, uint8_t * uuid128){
565 // @format HZ
566 uint8_t packet[22];
567 packet[0] = GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT;
568 packet[1] = sizeof(packet) - 2;
569 bt_store_16(packet, 2, peripheral->handle);
569 little_endian_store_16(packet, 2, peripheral->handle);
570 ///
570 ///
571 bt_store_16(packet, 4, descriptor_handle);
571 little_endian_store_16(packet, 4, descriptor_handle);
572 swap128(uuid128, &packet[6]);
573 emit_event_new(peripheral->subclient_id, packet, sizeof(packet));
574}
575///
576
577static void report_gatt_services(gatt_client_t * peripheral, uint8_t * packet, uint16_t size){
578 uint8_t attr_length = packet[1];
579 uint8_t uuid_length = attr_length - 4;
580
581 int i;
582 for (i = 2; i < size; i += attr_length){
572 swap128(uuid128, &packet[6]);
573 emit_event_new(peripheral->subclient_id, packet, sizeof(packet));
574}
575///
576
577static void report_gatt_services(gatt_client_t * peripheral, uint8_t * packet, uint16_t size){
578 uint8_t attr_length = packet[1];
579 uint8_t uuid_length = attr_length - 4;
580
581 int i;
582 for (i = 2; i < size; i += attr_length){
583 uint16_t start_group_handle = READ_BT_16(packet,i);
584 uint16_t end_group_handle = READ_BT_16(packet,i+2);
583 uint16_t start_group_handle = little_endian_read_16(packet,i);
584 uint16_t end_group_handle = little_endian_read_16(packet,i+2);
585 uint8_t uuid128[16];
586 uint16_t uuid16 = 0;
587
588 if (uuid_length == 2){
585 uint8_t uuid128[16];
586 uint16_t uuid16 = 0;
587
588 if (uuid_length == 2){
589 uuid16 = READ_BT_16(packet, i+4);
589 uuid16 = little_endian_read_16(packet, i+4);
590 sdp_normalize_uuid((uint8_t*) &uuid128, uuid16);
591 } else {
592 swap128(&packet[i+4], uuid128);
593 }
594 emit_gatt_service_query_result_event(peripheral, start_group_handle, end_group_handle, uuid128);
595 }
596 // log_info("report_gatt_services for %02X done", peripheral->handle);
597}
598
599// helper
600static void characteristic_start_found(gatt_client_t * peripheral, uint16_t start_handle, uint8_t properties, uint16_t value_handle, uint8_t * uuid, uint16_t uuid_length){
601 uint8_t uuid128[16];
602 uint16_t uuid16 = 0;
603 if (uuid_length == 2){
590 sdp_normalize_uuid((uint8_t*) &uuid128, uuid16);
591 } else {
592 swap128(&packet[i+4], uuid128);
593 }
594 emit_gatt_service_query_result_event(peripheral, start_group_handle, end_group_handle, uuid128);
595 }
596 // log_info("report_gatt_services for %02X done", peripheral->handle);
597}
598
599// helper
600static void characteristic_start_found(gatt_client_t * peripheral, uint16_t start_handle, uint8_t properties, uint16_t value_handle, uint8_t * uuid, uint16_t uuid_length){
601 uint8_t uuid128[16];
602 uint16_t uuid16 = 0;
603 if (uuid_length == 2){
604 uuid16 = READ_BT_16(uuid, 0);
604 uuid16 = little_endian_read_16(uuid, 0);
605 sdp_normalize_uuid((uint8_t*) uuid128, uuid16);
606 } else {
607 swap128(uuid, uuid128);
608 }
609
610 if (peripheral->filter_with_uuid && memcmp(peripheral->uuid128, uuid128, 16) != 0) return;
611
612 peripheral->characteristic_properties = properties;

--- 17 unchanged lines hidden (view full) ---

630 peripheral->characteristic_start_handle = 0;
631}
632
633static void report_gatt_characteristics(gatt_client_t * peripheral, uint8_t * packet, uint16_t size){
634 uint8_t attr_length = packet[1];
635 uint8_t uuid_length = attr_length - 5;
636 int i;
637 for (i = 2; i < size; i += attr_length){
605 sdp_normalize_uuid((uint8_t*) uuid128, uuid16);
606 } else {
607 swap128(uuid, uuid128);
608 }
609
610 if (peripheral->filter_with_uuid && memcmp(peripheral->uuid128, uuid128, 16) != 0) return;
611
612 peripheral->characteristic_properties = properties;

--- 17 unchanged lines hidden (view full) ---

630 peripheral->characteristic_start_handle = 0;
631}
632
633static void report_gatt_characteristics(gatt_client_t * peripheral, uint8_t * packet, uint16_t size){
634 uint8_t attr_length = packet[1];
635 uint8_t uuid_length = attr_length - 5;
636 int i;
637 for (i = 2; i < size; i += attr_length){
638 uint16_t start_handle = READ_BT_16(packet, i);
638 uint16_t start_handle = little_endian_read_16(packet, i);
639 uint8_t properties = packet[i+2];
639 uint8_t properties = packet[i+2];
640 uint16_t value_handle = READ_BT_16(packet, i+3);
640 uint16_t value_handle = little_endian_read_16(packet, i+3);
641 characteristic_end_found(peripheral, start_handle-1);
642 characteristic_start_found(peripheral, start_handle, properties, value_handle, &packet[i+5], uuid_length);
643 }
644}
645
646static void report_gatt_included_service_uuid16(gatt_client_t * peripheral, uint16_t include_handle, uint16_t uuid16){
647 uint8_t normalized_uuid128[16];
648 sdp_normalize_uuid(normalized_uuid128, uuid16);

--- 9 unchanged lines hidden (view full) ---

658// @returns packet pointer
659// @note assume that value is part of an l2cap buffer - overwrite HCI + L2CAP packet headers
660static const int characteristic_value_event_header_size = 8;
661static uint8_t * setup_characteristic_value_packet(uint8_t type, uint16_t con_handle, uint16_t attribute_handle, uint8_t * value, uint16_t length){
662 // before the value inside the ATT PDU
663 uint8_t * packet = value - characteristic_value_event_header_size;
664 packet[0] = type;
665 packet[1] = characteristic_value_event_header_size - 2 + length;
641 characteristic_end_found(peripheral, start_handle-1);
642 characteristic_start_found(peripheral, start_handle, properties, value_handle, &packet[i+5], uuid_length);
643 }
644}
645
646static void report_gatt_included_service_uuid16(gatt_client_t * peripheral, uint16_t include_handle, uint16_t uuid16){
647 uint8_t normalized_uuid128[16];
648 sdp_normalize_uuid(normalized_uuid128, uuid16);

--- 9 unchanged lines hidden (view full) ---

658// @returns packet pointer
659// @note assume that value is part of an l2cap buffer - overwrite HCI + L2CAP packet headers
660static const int characteristic_value_event_header_size = 8;
661static uint8_t * setup_characteristic_value_packet(uint8_t type, uint16_t con_handle, uint16_t attribute_handle, uint8_t * value, uint16_t length){
662 // before the value inside the ATT PDU
663 uint8_t * packet = value - characteristic_value_event_header_size;
664 packet[0] = type;
665 packet[1] = characteristic_value_event_header_size - 2 + length;
666 bt_store_16(packet, 2, con_handle);
667 bt_store_16(packet, 4, attribute_handle);
668 bt_store_16(packet, 6, length);
666 little_endian_store_16(packet, 2, con_handle);
667 little_endian_store_16(packet, 4, attribute_handle);
668 little_endian_store_16(packet, 6, length);
669 return packet;
670}
671
672// @returns packet pointer
673// @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
674static const int long_characteristic_value_event_header_size = 10;
675static uint8_t * setup_long_characteristic_value_packet(uint8_t type, uint16_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * value, uint16_t length){
676#if defined(HCI_INCOMING_PRE_BUFFER_SIZE) && (HCI_INCOMING_PRE_BUFFER_SIZE >= 10 - 8) // L2CAP Header (4) - ACL Header (4)
677 // before the value inside the ATT PDU
678 uint8_t * packet = value - long_characteristic_value_event_header_size;
679 packet[0] = type;
680 packet[1] = long_characteristic_value_event_header_size - 2 + length;
669 return packet;
670}
671
672// @returns packet pointer
673// @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
674static const int long_characteristic_value_event_header_size = 10;
675static uint8_t * setup_long_characteristic_value_packet(uint8_t type, uint16_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * value, uint16_t length){
676#if defined(HCI_INCOMING_PRE_BUFFER_SIZE) && (HCI_INCOMING_PRE_BUFFER_SIZE >= 10 - 8) // L2CAP Header (4) - ACL Header (4)
677 // before the value inside the ATT PDU
678 uint8_t * packet = value - long_characteristic_value_event_header_size;
679 packet[0] = type;
680 packet[1] = long_characteristic_value_event_header_size - 2 + length;
681 bt_store_16(packet, 2, con_handle);
682 bt_store_16(packet, 4, attribute_handle);
683 bt_store_16(packet, 6, offset);
684 bt_store_16(packet, 8, length);
681 little_endian_store_16(packet, 2, con_handle);
682 little_endian_store_16(packet, 4, attribute_handle);
683 little_endian_store_16(packet, 6, offset);
684 little_endian_store_16(packet, 8, length);
685 return packet;
686#else
687 log_error("HCI_INCOMING_PRE_BUFFER_SIZE >= 2 required for long characteristic reads");
688 return NULL;
689#endif
690}
691
692

--- 31 unchanged lines hidden (view full) ---

724 uint8_t * packet = setup_long_characteristic_value_packet(GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT, peripheral->handle, descriptor_handle, value_offset, blob, blob_length);
725 if (!packet) return;
726 emit_event_new(peripheral->subclient_id, packet, blob_length + long_characteristic_value_event_header_size);
727}
728
729static void report_gatt_all_characteristic_descriptors(gatt_client_t * peripheral, uint8_t * packet, uint16_t size, uint16_t pair_size){
730 int i;
731 for (i = 0; i<size; i+=pair_size){
685 return packet;
686#else
687 log_error("HCI_INCOMING_PRE_BUFFER_SIZE >= 2 required for long characteristic reads");
688 return NULL;
689#endif
690}
691
692

--- 31 unchanged lines hidden (view full) ---

724 uint8_t * packet = setup_long_characteristic_value_packet(GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT, peripheral->handle, descriptor_handle, value_offset, blob, blob_length);
725 if (!packet) return;
726 emit_event_new(peripheral->subclient_id, packet, blob_length + long_characteristic_value_event_header_size);
727}
728
729static void report_gatt_all_characteristic_descriptors(gatt_client_t * peripheral, uint8_t * packet, uint16_t size, uint16_t pair_size){
730 int i;
731 for (i = 0; i<size; i+=pair_size){
732 uint16_t descriptor_handle = READ_BT_16(packet,i);
732 uint16_t descriptor_handle = little_endian_read_16(packet,i);
733 uint8_t uuid128[16];
734 uint16_t uuid16 = 0;
735 if (pair_size == 4){
733 uint8_t uuid128[16];
734 uint16_t uuid16 = 0;
735 if (pair_size == 4){
736 uuid16 = READ_BT_16(packet,i+2);
736 uuid16 = little_endian_read_16(packet,i+2);
737 sdp_normalize_uuid(uuid128, uuid16);
738 } else {
739 swap128(&packet[i+2], uuid128);
740 }
741 emit_gatt_all_characteristic_descriptors_result_event(peripheral, descriptor_handle, uuid128);
742 }
743
744}

--- 62 unchanged lines hidden (view full) ---

807 }
808
809 peripheral->attribute_offset += received_blob_length;
810 peripheral->gatt_client_state = next_query_state;
811}
812
813
814static int is_value_valid(gatt_client_t *peripheral, uint8_t *packet, uint16_t size){
737 sdp_normalize_uuid(uuid128, uuid16);
738 } else {
739 swap128(&packet[i+2], uuid128);
740 }
741 emit_gatt_all_characteristic_descriptors_result_event(peripheral, descriptor_handle, uuid128);
742 }
743
744}

--- 62 unchanged lines hidden (view full) ---

807 }
808
809 peripheral->attribute_offset += received_blob_length;
810 peripheral->gatt_client_state = next_query_state;
811}
812
813
814static int is_value_valid(gatt_client_t *peripheral, uint8_t *packet, uint16_t size){
815 uint16_t attribute_handle = READ_BT_16(packet, 1);
816 uint16_t value_offset = READ_BT_16(packet, 3);
815 uint16_t attribute_handle = little_endian_read_16(packet, 1);
816 uint16_t value_offset = little_endian_read_16(packet, 3);
817
818 if (peripheral->attribute_handle != attribute_handle) return 0;
819 if (peripheral->attribute_offset != value_offset) return 0;
820 return memcmp(&peripheral->attribute_value[peripheral->attribute_offset], &packet[5], size-5) == 0;
821}
822
823
824static void gatt_client_run(void){

--- 201 unchanged lines hidden (view full) ---

1026 emit_gatt_complete_event(peripheral, error_code);
1027}
1028
1029static void gatt_client_hci_event_packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
1030 switch (packet[0]) {
1031 case HCI_EVENT_DISCONNECTION_COMPLETE:
1032 {
1033 log_info("GATT Client: HCI_EVENT_DISCONNECTION_COMPLETE");
817
818 if (peripheral->attribute_handle != attribute_handle) return 0;
819 if (peripheral->attribute_offset != value_offset) return 0;
820 return memcmp(&peripheral->attribute_value[peripheral->attribute_offset], &packet[5], size-5) == 0;
821}
822
823
824static void gatt_client_run(void){

--- 201 unchanged lines hidden (view full) ---

1026 emit_gatt_complete_event(peripheral, error_code);
1027}
1028
1029static void gatt_client_hci_event_packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
1030 switch (packet[0]) {
1031 case HCI_EVENT_DISCONNECTION_COMPLETE:
1032 {
1033 log_info("GATT Client: HCI_EVENT_DISCONNECTION_COMPLETE");
1034 uint16_t con_handle = READ_BT_16(packet,3);
1034 uint16_t con_handle = little_endian_read_16(packet,3);
1035 gatt_client_t * peripheral = get_gatt_client_context_for_handle(con_handle);
1036 if (!peripheral) break;
1037 gatt_client_report_error_if_pending(peripheral, ATT_ERROR_HCI_DISCONNECT_RECEIVED);
1038
1039 btstack_linked_list_remove(&gatt_client_connections, (btstack_linked_item_t *) peripheral);
1040 btstack_memory_gatt_client_free(peripheral);
1041 break;
1042 }

--- 14 unchanged lines hidden (view full) ---

1057 }
1058
1059 if (packet_type != ATT_DATA_PACKET) return;
1060
1061 // special cases: notifications don't need a context while indications motivate creating one
1062 gatt_client_t * peripheral;
1063 switch (packet[0]){
1064 case ATT_HANDLE_VALUE_NOTIFICATION:
1035 gatt_client_t * peripheral = get_gatt_client_context_for_handle(con_handle);
1036 if (!peripheral) break;
1037 gatt_client_report_error_if_pending(peripheral, ATT_ERROR_HCI_DISCONNECT_RECEIVED);
1038
1039 btstack_linked_list_remove(&gatt_client_connections, (btstack_linked_item_t *) peripheral);
1040 btstack_memory_gatt_client_free(peripheral);
1041 break;
1042 }

--- 14 unchanged lines hidden (view full) ---

1057 }
1058
1059 if (packet_type != ATT_DATA_PACKET) return;
1060
1061 // special cases: notifications don't need a context while indications motivate creating one
1062 gatt_client_t * peripheral;
1063 switch (packet[0]){
1064 case ATT_HANDLE_VALUE_NOTIFICATION:
1065 report_gatt_notification(handle, READ_BT_16(packet,1), &packet[3], size-3);
1065 report_gatt_notification(handle, little_endian_read_16(packet,1), &packet[3], size-3);
1066 return;
1067 case ATT_HANDLE_VALUE_INDICATION:
1068 peripheral = provide_context_for_conn_handle(handle);
1069 break;
1070 default:
1071 peripheral = get_gatt_client_context_for_handle(handle);
1072 break;
1073 }
1074
1075 if (!peripheral) return;
1076
1077 switch (packet[0]){
1078 case ATT_EXCHANGE_MTU_RESPONSE:
1079 {
1066 return;
1067 case ATT_HANDLE_VALUE_INDICATION:
1068 peripheral = provide_context_for_conn_handle(handle);
1069 break;
1070 default:
1071 peripheral = get_gatt_client_context_for_handle(handle);
1072 break;
1073 }
1074
1075 if (!peripheral) return;
1076
1077 switch (packet[0]){
1078 case ATT_EXCHANGE_MTU_RESPONSE:
1079 {
1080 uint16_t remote_rx_mtu = READ_BT_16(packet, 1);
1080 uint16_t remote_rx_mtu = little_endian_read_16(packet, 1);
1081 uint16_t local_rx_mtu = l2cap_max_le_mtu();
1082 peripheral->mtu = remote_rx_mtu < local_rx_mtu ? remote_rx_mtu : local_rx_mtu;
1083 peripheral->mtu_state = MTU_EXCHANGED;
1084
1085 break;
1086 }
1087 case ATT_READ_BY_GROUP_TYPE_RESPONSE:
1088 switch(peripheral->gatt_client_state){
1089 case P_W4_SERVICE_QUERY_RESULT:
1090 report_gatt_services(peripheral, packet, size);
1091 trigger_next_service_query(peripheral, get_last_result_handle_from_service_list(packet, size));
1092 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1093 break;
1094 default:
1095 break;
1096 }
1097 break;
1098 case ATT_HANDLE_VALUE_INDICATION:
1081 uint16_t local_rx_mtu = l2cap_max_le_mtu();
1082 peripheral->mtu = remote_rx_mtu < local_rx_mtu ? remote_rx_mtu : local_rx_mtu;
1083 peripheral->mtu_state = MTU_EXCHANGED;
1084
1085 break;
1086 }
1087 case ATT_READ_BY_GROUP_TYPE_RESPONSE:
1088 switch(peripheral->gatt_client_state){
1089 case P_W4_SERVICE_QUERY_RESULT:
1090 report_gatt_services(peripheral, packet, size);
1091 trigger_next_service_query(peripheral, get_last_result_handle_from_service_list(packet, size));
1092 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1093 break;
1094 default:
1095 break;
1096 }
1097 break;
1098 case ATT_HANDLE_VALUE_INDICATION:
1099 report_gatt_indication(handle, READ_BT_16(packet,1), &packet[3], size-3);
1099 report_gatt_indication(handle, little_endian_read_16(packet,1), &packet[3], size-3);
1100 peripheral->send_confirmation = 1;
1101 break;
1102
1103 case ATT_READ_BY_TYPE_RESPONSE:
1104 switch (peripheral->gatt_client_state){
1105 case P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT:
1106 report_gatt_characteristics(peripheral, packet, size);
1107 trigger_next_characteristic_query(peripheral, get_last_result_handle_from_characteristics_list(packet, size));

--- 6 unchanged lines hidden (view full) ---

1114 break;
1115 case P_W4_INCLUDED_SERVICE_QUERY_RESULT:
1116 {
1117 uint16_t uuid16 = 0;
1118 uint16_t pair_size = packet[1];
1119
1120 if (pair_size < 7){
1121 // UUIDs not available, query first included service
1100 peripheral->send_confirmation = 1;
1101 break;
1102
1103 case ATT_READ_BY_TYPE_RESPONSE:
1104 switch (peripheral->gatt_client_state){
1105 case P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT:
1106 report_gatt_characteristics(peripheral, packet, size);
1107 trigger_next_characteristic_query(peripheral, get_last_result_handle_from_characteristics_list(packet, size));

--- 6 unchanged lines hidden (view full) ---

1114 break;
1115 case P_W4_INCLUDED_SERVICE_QUERY_RESULT:
1116 {
1117 uint16_t uuid16 = 0;
1118 uint16_t pair_size = packet[1];
1119
1120 if (pair_size < 7){
1121 // UUIDs not available, query first included service
1122 peripheral->start_group_handle = READ_BT_16(packet, 2); // ready for next query
1123 peripheral->query_start_handle = READ_BT_16(packet, 4);
1124 peripheral->query_end_handle = READ_BT_16(packet,6);
1122 peripheral->start_group_handle = little_endian_read_16(packet, 2); // ready for next query
1123 peripheral->query_start_handle = little_endian_read_16(packet, 4);
1124 peripheral->query_end_handle = little_endian_read_16(packet,6);
1125 peripheral->gatt_client_state = P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY;
1126 break;
1127 }
1128
1129 uint16_t offset;
1130 for (offset = 2; offset < size; offset += pair_size){
1125 peripheral->gatt_client_state = P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY;
1126 break;
1127 }
1128
1129 uint16_t offset;
1130 for (offset = 2; offset < size; offset += pair_size){
1131 uint16_t include_handle = READ_BT_16(packet, offset);
1132 peripheral->query_start_handle = READ_BT_16(packet,offset+2);
1133 peripheral->query_end_handle = READ_BT_16(packet,offset+4);
1134 uuid16 = READ_BT_16(packet, offset+6);
1131 uint16_t include_handle = little_endian_read_16(packet, offset);
1132 peripheral->query_start_handle = little_endian_read_16(packet,offset+2);
1133 peripheral->query_end_handle = little_endian_read_16(packet,offset+4);
1134 uuid16 = little_endian_read_16(packet, offset+6);
1135 report_gatt_included_service_uuid16(peripheral, include_handle, uuid16);
1136 }
1137
1138 trigger_next_included_service_query(peripheral, get_last_result_handle_from_included_services_list(packet, size));
1139 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1140 break;
1141 }
1142 case P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT:
1135 report_gatt_included_service_uuid16(peripheral, include_handle, uuid16);
1136 }
1137
1138 trigger_next_included_service_query(peripheral, get_last_result_handle_from_included_services_list(packet, size));
1139 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1140 break;
1141 }
1142 case P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT:
1143 peripheral->client_characteristic_configuration_handle = READ_BT_16(packet, 2);
1143 peripheral->client_characteristic_configuration_handle = little_endian_read_16(packet, 2);
1144 peripheral->gatt_client_state = P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
1145 break;
1146 case P_W4_READ_BY_TYPE_RESPONSE: {
1147 uint16_t pair_size = packet[1];
1148 uint16_t offset;
1149 uint16_t last_result_handle = 0;
1150 for (offset = 2; offset < size ; offset += pair_size){
1144 peripheral->gatt_client_state = P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
1145 break;
1146 case P_W4_READ_BY_TYPE_RESPONSE: {
1147 uint16_t pair_size = packet[1];
1148 uint16_t offset;
1149 uint16_t last_result_handle = 0;
1150 for (offset = 2; offset < size ; offset += pair_size){
1151 uint16_t value_handle = READ_BT_16(packet, offset);
1151 uint16_t value_handle = little_endian_read_16(packet, offset);
1152 report_gatt_characteristic_value(peripheral, value_handle, &packet[offset+2], pair_size-2);
1153 last_result_handle = value_handle;
1154 }
1155 trigger_next_read_by_type_query(peripheral, last_result_handle);
1156 break;
1157 }
1158 default:
1159 break;

--- 28 unchanged lines hidden (view full) ---

1188
1189 case ATT_FIND_BY_TYPE_VALUE_RESPONSE:
1190 {
1191 uint8_t pair_size = 4;
1192 int i;
1193 uint16_t start_group_handle;
1194 uint16_t end_group_handle= 0xffff; // asserts GATT_EVENT_QUERY_COMPLETE is emitted if no results
1195 for (i = 1; i<size; i+=pair_size){
1152 report_gatt_characteristic_value(peripheral, value_handle, &packet[offset+2], pair_size-2);
1153 last_result_handle = value_handle;
1154 }
1155 trigger_next_read_by_type_query(peripheral, last_result_handle);
1156 break;
1157 }
1158 default:
1159 break;

--- 28 unchanged lines hidden (view full) ---

1188
1189 case ATT_FIND_BY_TYPE_VALUE_RESPONSE:
1190 {
1191 uint8_t pair_size = 4;
1192 int i;
1193 uint16_t start_group_handle;
1194 uint16_t end_group_handle= 0xffff; // asserts GATT_EVENT_QUERY_COMPLETE is emitted if no results
1195 for (i = 1; i<size; i+=pair_size){
1196 start_group_handle = READ_BT_16(packet,i);
1197 end_group_handle = READ_BT_16(packet,i+2);
1196 start_group_handle = little_endian_read_16(packet,i);
1197 end_group_handle = little_endian_read_16(packet,i+2);
1198 emit_gatt_service_query_result_event(peripheral, start_group_handle, end_group_handle, peripheral->uuid128);
1199 }
1200 trigger_next_service_by_uuid_query(peripheral, end_group_handle);
1201 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1202 break;
1203 }
1204 case ATT_FIND_INFORMATION_REPLY:
1205 {
1206 uint8_t pair_size = 4;
1207 if (packet[1] == 2){
1208 pair_size = 18;
1209 }
1198 emit_gatt_service_query_result_event(peripheral, start_group_handle, end_group_handle, peripheral->uuid128);
1199 }
1200 trigger_next_service_by_uuid_query(peripheral, end_group_handle);
1201 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1202 break;
1203 }
1204 case ATT_FIND_INFORMATION_REPLY:
1205 {
1206 uint8_t pair_size = 4;
1207 if (packet[1] == 2){
1208 pair_size = 18;
1209 }
1210 uint16_t last_descriptor_handle = READ_BT_16(packet, size - pair_size);
1210 uint16_t last_descriptor_handle = little_endian_read_16(packet, size - pair_size);
1211
1212 report_gatt_all_characteristic_descriptors(peripheral, &packet[2], size-2, pair_size);
1213 trigger_next_characteristic_descriptor_query(peripheral, last_descriptor_handle);
1214 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1215 break;
1216 }
1217
1218 case ATT_WRITE_RESPONSE:

--- 43 unchanged lines hidden (view full) ---

1262 if (is_value_valid(peripheral, packet, size)){
1263 emit_gatt_complete_event(peripheral, 0);
1264 } else {
1265 emit_gatt_complete_event(peripheral, ATT_ERROR_DATA_MISMATCH);
1266 }
1267 break;
1268
1269 case P_W4_PREPARE_WRITE_RESULT:{
1211
1212 report_gatt_all_characteristic_descriptors(peripheral, &packet[2], size-2, pair_size);
1213 trigger_next_characteristic_descriptor_query(peripheral, last_descriptor_handle);
1214 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1215 break;
1216 }
1217
1218 case ATT_WRITE_RESPONSE:

--- 43 unchanged lines hidden (view full) ---

1262 if (is_value_valid(peripheral, packet, size)){
1263 emit_gatt_complete_event(peripheral, 0);
1264 } else {
1265 emit_gatt_complete_event(peripheral, ATT_ERROR_DATA_MISMATCH);
1266 }
1267 break;
1268
1269 case P_W4_PREPARE_WRITE_RESULT:{
1270 peripheral->attribute_offset = READ_BT_16(packet, 3);
1270 peripheral->attribute_offset = little_endian_read_16(packet, 3);
1271 trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_WRITE, P_W2_EXECUTE_PREPARED_WRITE);
1272 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1273 break;
1274 }
1275 case P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:{
1271 trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_WRITE, P_W2_EXECUTE_PREPARED_WRITE);
1272 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1273 break;
1274 }
1275 case P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:{
1276 peripheral->attribute_offset = READ_BT_16(packet, 3);
1276 peripheral->attribute_offset = little_endian_read_16(packet, 3);
1277 trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR, P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR);
1278 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1279 break;
1280 }
1281 case P_W4_PREPARE_RELIABLE_WRITE_RESULT:{
1282 if (is_value_valid(peripheral, packet, size)){
1277 trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR, P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR);
1278 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1279 break;
1280 }
1281 case P_W4_PREPARE_RELIABLE_WRITE_RESULT:{
1282 if (is_value_valid(peripheral, packet, size)){
1283 peripheral->attribute_offset = READ_BT_16(packet, 3);
1283 peripheral->attribute_offset = little_endian_read_16(packet, 3);
1284 trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_RELIABLE_WRITE, P_W2_EXECUTE_PREPARED_WRITE);
1285 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1286 break;
1287 }
1288 peripheral->gatt_client_state = P_W2_CANCEL_PREPARED_WRITE_DATA_MISMATCH;
1289 break;
1290 }
1291 default:

--- 428 unchanged lines hidden (view full) ---

1720 (characteristic->properties & ATT_PROPERTY_INDICATE) == 0){
1721 log_info("le_central_write_client_characteristic_configuration: GATT_CLIENT_CHARACTERISTIC_INDICATION_NOT_SUPPORTED");
1722 return GATT_CLIENT_CHARACTERISTIC_INDICATION_NOT_SUPPORTED;
1723 }
1724
1725 peripheral->subclient_id = gatt_client_id;
1726 peripheral->start_group_handle = characteristic->value_handle;
1727 peripheral->end_group_handle = characteristic->end_handle;
1284 trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_RELIABLE_WRITE, P_W2_EXECUTE_PREPARED_WRITE);
1285 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1286 break;
1287 }
1288 peripheral->gatt_client_state = P_W2_CANCEL_PREPARED_WRITE_DATA_MISMATCH;
1289 break;
1290 }
1291 default:

--- 428 unchanged lines hidden (view full) ---

1720 (characteristic->properties & ATT_PROPERTY_INDICATE) == 0){
1721 log_info("le_central_write_client_characteristic_configuration: GATT_CLIENT_CHARACTERISTIC_INDICATION_NOT_SUPPORTED");
1722 return GATT_CLIENT_CHARACTERISTIC_INDICATION_NOT_SUPPORTED;
1723 }
1724
1725 peripheral->subclient_id = gatt_client_id;
1726 peripheral->start_group_handle = characteristic->value_handle;
1727 peripheral->end_group_handle = characteristic->end_handle;
1728 bt_store_16(peripheral->client_characteristic_configuration_value, 0, configuration);
1728 little_endian_store_16(peripheral->client_characteristic_configuration_value, 0, configuration);
1729
1730 peripheral->gatt_client_state = P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY;
1731 gatt_client_run();
1732 return 0;
1733}
1734
1735uint8_t gatt_client_read_characteristic_descriptor_using_descriptor_handle(uint16_t gatt_client_id, uint16_t con_handle, uint16_t descriptor_handle){
1736 gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);

--- 135 unchanged lines hidden ---
1729
1730 peripheral->gatt_client_state = P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY;
1731 gatt_client_run();
1732 return 0;
1733}
1734
1735uint8_t gatt_client_read_characteristic_descriptor_using_descriptor_handle(uint16_t gatt_client_id, uint16_t con_handle, uint16_t descriptor_handle){
1736 gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);

--- 135 unchanged lines hidden ---