gatt_client.c (9305033e0290a73b79a29900c5b9f35f77d880b1) gatt_client.c (1979f09cf045e87f55a9cd8067e8ef902cc8d78b)
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

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

878 uint16_t value_offset = little_endian_read_16(packet, 3);
879
880 if (gatt_client->attribute_handle != attribute_handle) return 0;
881 if (gatt_client->attribute_offset != value_offset) return 0;
882 return memcmp(&gatt_client->attribute_value[gatt_client->attribute_offset], &packet[5], size - 5u) == 0u;
883}
884
885// returns 1 if packet was sent
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

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

878 uint16_t value_offset = little_endian_read_16(packet, 3);
879
880 if (gatt_client->attribute_handle != attribute_handle) return 0;
881 if (gatt_client->attribute_offset != value_offset) return 0;
882 return memcmp(&gatt_client->attribute_value[gatt_client->attribute_offset], &packet[5], size - 5u) == 0u;
883}
884
885// returns 1 if packet was sent
886static int gatt_client_run_for_gatt_client(gatt_client_t * gatt_client){
886static bool gatt_client_run_for_gatt_client(gatt_client_t * gatt_client){
887
888 // wait until re-encryption is complete
887
888 // wait until re-encryption is complete
889 if (gap_reconnect_security_setup_active(gatt_client->con_handle)) return 0;
889 if (gap_reconnect_security_setup_active(gatt_client->con_handle)) return false;
890
891 // wait until re-encryption is complete
890
891 // wait until re-encryption is complete
892 if (gatt_client->reencryption_active) return 0;
892 if (gatt_client->reencryption_active) return false;
893
894 // wait until pairing complete (either reactive authentication or due to required security level)
893
894 // wait until pairing complete (either reactive authentication or due to required security level)
895 if (gatt_client->wait_for_authentication_complete) return 0;
895 if (gatt_client->wait_for_authentication_complete) return false;
896
897 bool client_request_pending = gatt_client->gatt_client_state != P_READY;
898
899 // verify security level for Mandatory Authentication
900 if (client_request_pending && (gatt_client_required_security_level > gatt_client->security_level)){
901 log_info("Trigger pairing, current security level %u, required %u\n", gatt_client->security_level, gatt_client_required_security_level);
902 gatt_client->wait_for_authentication_complete = 1;
903 // set att error code for pairing failure based on required level
904 switch (gatt_client_required_security_level){
905 case LEVEL_4:
906 case LEVEL_3:
907 gatt_client->pending_error_code = ATT_ERROR_INSUFFICIENT_AUTHENTICATION;
908 break;
909 default:
910 gatt_client->pending_error_code = ATT_ERROR_INSUFFICIENT_ENCRYPTION;
911 break;
912 }
913 sm_request_pairing(gatt_client->con_handle);
914 // sm probably just sent a pdu
896
897 bool client_request_pending = gatt_client->gatt_client_state != P_READY;
898
899 // verify security level for Mandatory Authentication
900 if (client_request_pending && (gatt_client_required_security_level > gatt_client->security_level)){
901 log_info("Trigger pairing, current security level %u, required %u\n", gatt_client->security_level, gatt_client_required_security_level);
902 gatt_client->wait_for_authentication_complete = 1;
903 // set att error code for pairing failure based on required level
904 switch (gatt_client_required_security_level){
905 case LEVEL_4:
906 case LEVEL_3:
907 gatt_client->pending_error_code = ATT_ERROR_INSUFFICIENT_AUTHENTICATION;
908 break;
909 default:
910 gatt_client->pending_error_code = ATT_ERROR_INSUFFICIENT_ENCRYPTION;
911 break;
912 }
913 sm_request_pairing(gatt_client->con_handle);
914 // sm probably just sent a pdu
915 return 1;
915 return true;
916 }
917
918 switch (gatt_client->mtu_state) {
919 case SEND_MTU_EXCHANGE:
920 gatt_client->mtu_state = SENT_MTU_EXCHANGE;
921 att_exchange_mtu_request(gatt_client->con_handle);
916 }
917
918 switch (gatt_client->mtu_state) {
919 case SEND_MTU_EXCHANGE:
920 gatt_client->mtu_state = SENT_MTU_EXCHANGE;
921 att_exchange_mtu_request(gatt_client->con_handle);
922 return 1;
922 return true;
923 case SENT_MTU_EXCHANGE:
923 case SENT_MTU_EXCHANGE:
924 return 0;
924 return false;
925 default:
926 break;
927 }
928
929 if (gatt_client->send_confirmation){
930 gatt_client->send_confirmation = 0;
931 att_confirmation(gatt_client->con_handle);
925 default:
926 break;
927 }
928
929 if (gatt_client->send_confirmation){
930 gatt_client->send_confirmation = 0;
931 att_confirmation(gatt_client->con_handle);
932 return 1;
932 return true;
933 }
934
935 // check MTU for writes
936 switch (gatt_client->gatt_client_state){
937 case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE:
938 case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR:
939 if (gatt_client->attribute_length <= (gatt_client->mtu - 3u)) break;
940 log_error("gatt_client_run: value len %u > MTU %u - 3\n", gatt_client->attribute_length,gatt_client->mtu);
941 gatt_client_handle_transaction_complete(gatt_client);
942 emit_gatt_complete_event(gatt_client, ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH);
933 }
934
935 // check MTU for writes
936 switch (gatt_client->gatt_client_state){
937 case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE:
938 case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR:
939 if (gatt_client->attribute_length <= (gatt_client->mtu - 3u)) break;
940 log_error("gatt_client_run: value len %u > MTU %u - 3\n", gatt_client->attribute_length,gatt_client->mtu);
941 gatt_client_handle_transaction_complete(gatt_client);
942 emit_gatt_complete_event(gatt_client, ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH);
943 return 0;
943 return false;
944 default:
945 break;
946 }
947
948 switch (gatt_client->gatt_client_state){
949 case P_W2_SEND_SERVICE_QUERY:
950 gatt_client->gatt_client_state = P_W4_SERVICE_QUERY_RESULT;
951 send_gatt_services_request(gatt_client);
944 default:
945 break;
946 }
947
948 switch (gatt_client->gatt_client_state){
949 case P_W2_SEND_SERVICE_QUERY:
950 gatt_client->gatt_client_state = P_W4_SERVICE_QUERY_RESULT;
951 send_gatt_services_request(gatt_client);
952 return 1;
952 return true;
953
954 case P_W2_SEND_SERVICE_WITH_UUID_QUERY:
955 gatt_client->gatt_client_state = P_W4_SERVICE_WITH_UUID_RESULT;
956 send_gatt_services_by_uuid_request(gatt_client);
953
954 case P_W2_SEND_SERVICE_WITH_UUID_QUERY:
955 gatt_client->gatt_client_state = P_W4_SERVICE_WITH_UUID_RESULT;
956 send_gatt_services_by_uuid_request(gatt_client);
957 return 1;
957 return true;
958
959 case P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY:
960 gatt_client->gatt_client_state = P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT;
961 send_gatt_characteristic_request(gatt_client);
958
959 case P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY:
960 gatt_client->gatt_client_state = P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT;
961 send_gatt_characteristic_request(gatt_client);
962 return 1;
962 return true;
963
964 case P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY:
965 gatt_client->gatt_client_state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT;
966 send_gatt_characteristic_request(gatt_client);
963
964 case P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY:
965 gatt_client->gatt_client_state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT;
966 send_gatt_characteristic_request(gatt_client);
967 return 1;
967 return true;
968
969 case P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY:
970 gatt_client->gatt_client_state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT;
971 send_gatt_characteristic_descriptor_request(gatt_client);
968
969 case P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY:
970 gatt_client->gatt_client_state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT;
971 send_gatt_characteristic_descriptor_request(gatt_client);
972 return 1;
972 return true;
973
974 case P_W2_SEND_INCLUDED_SERVICE_QUERY:
975 gatt_client->gatt_client_state = P_W4_INCLUDED_SERVICE_QUERY_RESULT;
976 send_gatt_included_service_request(gatt_client);
973
974 case P_W2_SEND_INCLUDED_SERVICE_QUERY:
975 gatt_client->gatt_client_state = P_W4_INCLUDED_SERVICE_QUERY_RESULT;
976 send_gatt_included_service_request(gatt_client);
977 return 1;
977 return true;
978
979 case P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY:
980 gatt_client->gatt_client_state = P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT;
981 send_gatt_included_service_uuid_request(gatt_client);
978
979 case P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY:
980 gatt_client->gatt_client_state = P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT;
981 send_gatt_included_service_uuid_request(gatt_client);
982 return 1;
982 return true;
983
984 case P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY:
985 gatt_client->gatt_client_state = P_W4_READ_CHARACTERISTIC_VALUE_RESULT;
986 send_gatt_read_characteristic_value_request(gatt_client);
983
984 case P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY:
985 gatt_client->gatt_client_state = P_W4_READ_CHARACTERISTIC_VALUE_RESULT;
986 send_gatt_read_characteristic_value_request(gatt_client);
987 return 1;
987 return true;
988
989 case P_W2_SEND_READ_BLOB_QUERY:
990 gatt_client->gatt_client_state = P_W4_READ_BLOB_RESULT;
991 send_gatt_read_blob_request(gatt_client);
988
989 case P_W2_SEND_READ_BLOB_QUERY:
990 gatt_client->gatt_client_state = P_W4_READ_BLOB_RESULT;
991 send_gatt_read_blob_request(gatt_client);
992 return 1;
992 return true;
993
994 case P_W2_SEND_READ_BY_TYPE_REQUEST:
995 gatt_client->gatt_client_state = P_W4_READ_BY_TYPE_RESPONSE;
996 send_gatt_read_by_type_request(gatt_client);
993
994 case P_W2_SEND_READ_BY_TYPE_REQUEST:
995 gatt_client->gatt_client_state = P_W4_READ_BY_TYPE_RESPONSE;
996 send_gatt_read_by_type_request(gatt_client);
997 return 1;
997 return true;
998
999 case P_W2_SEND_READ_MULTIPLE_REQUEST:
1000 gatt_client->gatt_client_state = P_W4_READ_MULTIPLE_RESPONSE;
1001 send_gatt_read_multiple_request(gatt_client);
998
999 case P_W2_SEND_READ_MULTIPLE_REQUEST:
1000 gatt_client->gatt_client_state = P_W4_READ_MULTIPLE_RESPONSE;
1001 send_gatt_read_multiple_request(gatt_client);
1002 return 1;
1002 return true;
1003
1004 case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE:
1005 gatt_client->gatt_client_state = P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT;
1006 send_gatt_write_attribute_value_request(gatt_client);
1003
1004 case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE:
1005 gatt_client->gatt_client_state = P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT;
1006 send_gatt_write_attribute_value_request(gatt_client);
1007 return 1;
1007 return true;
1008
1009 case P_W2_PREPARE_WRITE:
1010 gatt_client->gatt_client_state = P_W4_PREPARE_WRITE_RESULT;
1011 send_gatt_prepare_write_request(gatt_client);
1008
1009 case P_W2_PREPARE_WRITE:
1010 gatt_client->gatt_client_state = P_W4_PREPARE_WRITE_RESULT;
1011 send_gatt_prepare_write_request(gatt_client);
1012 return 1;
1012 return true;
1013
1014 case P_W2_PREPARE_WRITE_SINGLE:
1015 gatt_client->gatt_client_state = P_W4_PREPARE_WRITE_SINGLE_RESULT;
1016 send_gatt_prepare_write_request(gatt_client);
1013
1014 case P_W2_PREPARE_WRITE_SINGLE:
1015 gatt_client->gatt_client_state = P_W4_PREPARE_WRITE_SINGLE_RESULT;
1016 send_gatt_prepare_write_request(gatt_client);
1017 return 1;
1017 return true;
1018
1019 case P_W2_PREPARE_RELIABLE_WRITE:
1020 gatt_client->gatt_client_state = P_W4_PREPARE_RELIABLE_WRITE_RESULT;
1021 send_gatt_prepare_write_request(gatt_client);
1018
1019 case P_W2_PREPARE_RELIABLE_WRITE:
1020 gatt_client->gatt_client_state = P_W4_PREPARE_RELIABLE_WRITE_RESULT;
1021 send_gatt_prepare_write_request(gatt_client);
1022 return 1;
1022 return true;
1023
1024 case P_W2_EXECUTE_PREPARED_WRITE:
1025 gatt_client->gatt_client_state = P_W4_EXECUTE_PREPARED_WRITE_RESULT;
1026 send_gatt_execute_write_request(gatt_client);
1023
1024 case P_W2_EXECUTE_PREPARED_WRITE:
1025 gatt_client->gatt_client_state = P_W4_EXECUTE_PREPARED_WRITE_RESULT;
1026 send_gatt_execute_write_request(gatt_client);
1027 return 1;
1027 return true;
1028
1029 case P_W2_CANCEL_PREPARED_WRITE:
1030 gatt_client->gatt_client_state = P_W4_CANCEL_PREPARED_WRITE_RESULT;
1031 send_gatt_cancel_prepared_write_request(gatt_client);
1028
1029 case P_W2_CANCEL_PREPARED_WRITE:
1030 gatt_client->gatt_client_state = P_W4_CANCEL_PREPARED_WRITE_RESULT;
1031 send_gatt_cancel_prepared_write_request(gatt_client);
1032 return 1;
1032 return true;
1033
1034 case P_W2_CANCEL_PREPARED_WRITE_DATA_MISMATCH:
1035 gatt_client->gatt_client_state = P_W4_CANCEL_PREPARED_WRITE_DATA_MISMATCH_RESULT;
1036 send_gatt_cancel_prepared_write_request(gatt_client);
1033
1034 case P_W2_CANCEL_PREPARED_WRITE_DATA_MISMATCH:
1035 gatt_client->gatt_client_state = P_W4_CANCEL_PREPARED_WRITE_DATA_MISMATCH_RESULT;
1036 send_gatt_cancel_prepared_write_request(gatt_client);
1037 return 1;
1037 return true;
1038
1039#ifdef ENABLE_GATT_FIND_INFORMATION_FOR_CCC_DISCOVERY
1040 case P_W2_SEND_FIND_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY:
1041 // use Find Information
1042 gatt_client->gatt_client_state = P_W4_FIND_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT;
1043 send_gatt_characteristic_descriptor_request(gatt_client);
1044#else
1045 case P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY:
1046 // Use Read By Type
1047 gatt_client->gatt_client_state = P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT;
1048 send_gatt_read_client_characteristic_configuration_request(gatt_client);
1049#endif
1038
1039#ifdef ENABLE_GATT_FIND_INFORMATION_FOR_CCC_DISCOVERY
1040 case P_W2_SEND_FIND_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY:
1041 // use Find Information
1042 gatt_client->gatt_client_state = P_W4_FIND_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT;
1043 send_gatt_characteristic_descriptor_request(gatt_client);
1044#else
1045 case P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY:
1046 // Use Read By Type
1047 gatt_client->gatt_client_state = P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT;
1048 send_gatt_read_client_characteristic_configuration_request(gatt_client);
1049#endif
1050 return 1;
1050 return true;
1051
1052 case P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY:
1053 gatt_client->gatt_client_state = P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT;
1054 send_gatt_read_characteristic_descriptor_request(gatt_client);
1051
1052 case P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY:
1053 gatt_client->gatt_client_state = P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT;
1054 send_gatt_read_characteristic_descriptor_request(gatt_client);
1055 return 1;
1055 return true;
1056
1057 case P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY:
1058 gatt_client->gatt_client_state = P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT;
1059 send_gatt_read_blob_request(gatt_client);
1056
1057 case P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY:
1058 gatt_client->gatt_client_state = P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT;
1059 send_gatt_read_blob_request(gatt_client);
1060 return 1;
1060 return true;
1061
1062 case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR:
1063 gatt_client->gatt_client_state = P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
1064 send_gatt_write_attribute_value_request(gatt_client);
1061
1062 case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR:
1063 gatt_client->gatt_client_state = P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
1064 send_gatt_write_attribute_value_request(gatt_client);
1065 return 1;
1065 return true;
1066
1067 case P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION:
1068 gatt_client->gatt_client_state = P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT;
1069 send_gatt_write_client_characteristic_configuration_request(gatt_client);
1066
1067 case P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION:
1068 gatt_client->gatt_client_state = P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT;
1069 send_gatt_write_client_characteristic_configuration_request(gatt_client);
1070 return 1;
1070 return true;
1071
1072 case P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR:
1073 gatt_client->gatt_client_state = P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
1074 send_gatt_prepare_write_request(gatt_client);
1071
1072 case P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR:
1073 gatt_client->gatt_client_state = P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
1074 send_gatt_prepare_write_request(gatt_client);
1075 return 1;
1075 return true;
1076
1077 case P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR:
1078 gatt_client->gatt_client_state = P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
1079 send_gatt_execute_write_request(gatt_client);
1076
1077 case P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR:
1078 gatt_client->gatt_client_state = P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
1079 send_gatt_execute_write_request(gatt_client);
1080 return 1;
1080 return true;
1081
1082#ifdef ENABLE_LE_SIGNED_WRITE
1083 case P_W4_IDENTITY_RESOLVING:
1084 log_info("P_W4_IDENTITY_RESOLVING - state %x", sm_identity_resolving_state(gatt_client->con_handle));
1085 switch (sm_identity_resolving_state(gatt_client->con_handle)){
1086 case IRK_LOOKUP_SUCCEEDED:
1087 gatt_client->le_device_index = sm_le_device_index(gatt_client->con_handle);
1088 gatt_client->gatt_client_state = P_W4_CMAC_READY;
1089 break;
1090 case IRK_LOOKUP_FAILED:
1091 gatt_client_handle_transaction_complete(gatt_client);
1092 emit_gatt_complete_event(gatt_client, ATT_ERROR_BONDING_INFORMATION_MISSING);
1081
1082#ifdef ENABLE_LE_SIGNED_WRITE
1083 case P_W4_IDENTITY_RESOLVING:
1084 log_info("P_W4_IDENTITY_RESOLVING - state %x", sm_identity_resolving_state(gatt_client->con_handle));
1085 switch (sm_identity_resolving_state(gatt_client->con_handle)){
1086 case IRK_LOOKUP_SUCCEEDED:
1087 gatt_client->le_device_index = sm_le_device_index(gatt_client->con_handle);
1088 gatt_client->gatt_client_state = P_W4_CMAC_READY;
1089 break;
1090 case IRK_LOOKUP_FAILED:
1091 gatt_client_handle_transaction_complete(gatt_client);
1092 emit_gatt_complete_event(gatt_client, ATT_ERROR_BONDING_INFORMATION_MISSING);
1093 return 0;
1093 return false;
1094 default:
1094 default:
1095 return 0;
1095 return false;
1096 }
1097
1098 /* Fall through */
1099
1100 case P_W4_CMAC_READY:
1101 if (sm_cmac_ready()){
1102 sm_key_t csrk;
1103 le_device_db_local_csrk_get(gatt_client->le_device_index, csrk);
1104 uint32_t sign_counter = le_device_db_local_counter_get(gatt_client->le_device_index);
1105 gatt_client->gatt_client_state = P_W4_CMAC_RESULT;
1106 sm_cmac_signed_write_start(csrk, ATT_SIGNED_WRITE_COMMAND, gatt_client->attribute_handle, gatt_client->attribute_length, gatt_client->attribute_value, sign_counter, att_signed_write_handle_cmac_result);
1107 }
1096 }
1097
1098 /* Fall through */
1099
1100 case P_W4_CMAC_READY:
1101 if (sm_cmac_ready()){
1102 sm_key_t csrk;
1103 le_device_db_local_csrk_get(gatt_client->le_device_index, csrk);
1104 uint32_t sign_counter = le_device_db_local_counter_get(gatt_client->le_device_index);
1105 gatt_client->gatt_client_state = P_W4_CMAC_RESULT;
1106 sm_cmac_signed_write_start(csrk, ATT_SIGNED_WRITE_COMMAND, gatt_client->attribute_handle, gatt_client->attribute_length, gatt_client->attribute_value, sign_counter, att_signed_write_handle_cmac_result);
1107 }
1108 return 0;
1108 return false;
1109
1110 case P_W2_SEND_SIGNED_WRITE: {
1111 gatt_client->gatt_client_state = P_W4_SEND_SINGED_WRITE_DONE;
1112 // bump local signing counter
1113 uint32_t sign_counter = le_device_db_local_counter_get(gatt_client->le_device_index);
1114 le_device_db_local_counter_set(gatt_client->le_device_index, sign_counter + 1);
1115 // send signed write command
1116 send_gatt_signed_write_request(gatt_client, sign_counter);
1117 // finally, notifiy client that write is complete
1118 gatt_client_handle_transaction_complete(gatt_client);
1119 emit_gatt_complete_event(gatt_client, ATT_ERROR_SUCCESS);
1109
1110 case P_W2_SEND_SIGNED_WRITE: {
1111 gatt_client->gatt_client_state = P_W4_SEND_SINGED_WRITE_DONE;
1112 // bump local signing counter
1113 uint32_t sign_counter = le_device_db_local_counter_get(gatt_client->le_device_index);
1114 le_device_db_local_counter_set(gatt_client->le_device_index, sign_counter + 1);
1115 // send signed write command
1116 send_gatt_signed_write_request(gatt_client, sign_counter);
1117 // finally, notifiy client that write is complete
1118 gatt_client_handle_transaction_complete(gatt_client);
1119 emit_gatt_complete_event(gatt_client, ATT_ERROR_SUCCESS);
1120 return 1;
1120 return true;
1121 }
1122#endif
1123 default:
1124 break;
1125 }
1126
1127 // requested can send snow?
1128 if (gatt_client->write_without_response_callback){
1129 btstack_packet_handler_t packet_handler = gatt_client->write_without_response_callback;
1130 gatt_client->write_without_response_callback = NULL;
1131 uint8_t event[4];
1132 event[0] = GATT_EVENT_CAN_WRITE_WITHOUT_RESPONSE;
1133 event[1] = sizeof(event) - 2u;
1134 little_endian_store_16(event, 2, gatt_client->con_handle);
1135 packet_handler(HCI_EVENT_PACKET, gatt_client->con_handle, event, sizeof(event));
1121 }
1122#endif
1123 default:
1124 break;
1125 }
1126
1127 // requested can send snow?
1128 if (gatt_client->write_without_response_callback){
1129 btstack_packet_handler_t packet_handler = gatt_client->write_without_response_callback;
1130 gatt_client->write_without_response_callback = NULL;
1131 uint8_t event[4];
1132 event[0] = GATT_EVENT_CAN_WRITE_WITHOUT_RESPONSE;
1133 event[1] = sizeof(event) - 2u;
1134 little_endian_store_16(event, 2, gatt_client->con_handle);
1135 packet_handler(HCI_EVENT_PACKET, gatt_client->con_handle, event, sizeof(event));
1136 return 1; // to trigger requeueing (even if higher layer didn't sent)
1136 return true; // to trigger requeueing (even if higher layer didn't sent)
1137 }
1138
1137 }
1138
1139 return 0;
1139 return false;
1140}
1141
1142static void gatt_client_run(void){
1143 btstack_linked_item_t *it;
1144 for (it = (btstack_linked_item_t *) gatt_client_connections; it != NULL; it = it->next){
1145 gatt_client_t * gatt_client = (gatt_client_t *) it;
1146 if (!att_dispatch_client_can_send_now(gatt_client->con_handle)) {
1147 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle);
1148 return;
1149 }
1140}
1141
1142static void gatt_client_run(void){
1143 btstack_linked_item_t *it;
1144 for (it = (btstack_linked_item_t *) gatt_client_connections; it != NULL; it = it->next){
1145 gatt_client_t * gatt_client = (gatt_client_t *) it;
1146 if (!att_dispatch_client_can_send_now(gatt_client->con_handle)) {
1147 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle);
1148 return;
1149 }
1150 int packet_sent = gatt_client_run_for_gatt_client(gatt_client);
1150 bool packet_sent = gatt_client_run_for_gatt_client(gatt_client);
1151 if (packet_sent){
1152 // request new permission
1153 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle);
1154 // requeue client for fairness and exit
1155 // note: iterator has become invalid
1156 btstack_linked_list_remove(&gatt_client_connections, (btstack_linked_item_t *) gatt_client);
1157 btstack_linked_list_add_tail(&gatt_client_connections, (btstack_linked_item_t *) gatt_client);
1158 return;

--- 1134 unchanged lines hidden ---
1151 if (packet_sent){
1152 // request new permission
1153 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle);
1154 // requeue client for fairness and exit
1155 // note: iterator has become invalid
1156 btstack_linked_list_remove(&gatt_client_connections, (btstack_linked_item_t *) gatt_client);
1157 btstack_linked_list_add_tail(&gatt_client_connections, (btstack_linked_item_t *) gatt_client);
1158 return;

--- 1134 unchanged lines hidden ---