Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 17 23:23:45 2019 +0000
Revision:
0:5b88d5760320
mbed-os5 only for TYBLE16

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /* mbed Microcontroller Library
kenjiArai 0:5b88d5760320 2 * Copyright (c) 2017-2017 ARM Limited
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * Licensed under the Apache License, Version 2.0 (the "License");
kenjiArai 0:5b88d5760320 5 * you may not use this file except in compliance with the License.
kenjiArai 0:5b88d5760320 6 * You may obtain a copy of the License at
kenjiArai 0:5b88d5760320 7 *
kenjiArai 0:5b88d5760320 8 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 0:5b88d5760320 9 *
kenjiArai 0:5b88d5760320 10 * Unless required by applicable law or agreed to in writing, software
kenjiArai 0:5b88d5760320 11 * distributed under the License is distributed on an "AS IS" BASIS,
kenjiArai 0:5b88d5760320 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 0:5b88d5760320 13 * See the License for the specific language governing permissions and
kenjiArai 0:5b88d5760320 14 * limitations under the License.
kenjiArai 0:5b88d5760320 15 */
kenjiArai 0:5b88d5760320 16
kenjiArai 0:5b88d5760320 17 #include "BLERoles.h"
kenjiArai 0:5b88d5760320 18
kenjiArai 0:5b88d5760320 19 #if BLE_FEATURE_GATT_CLIENT
kenjiArai 0:5b88d5760320 20
kenjiArai 0:5b88d5760320 21 #include <stdio.h>
kenjiArai 0:5b88d5760320 22 #include <stdlib.h>
kenjiArai 0:5b88d5760320 23
kenjiArai 0:5b88d5760320 24 #include "ble/pal/AttServerMessage.h"
kenjiArai 0:5b88d5760320 25 #include "ble/GattClient.h"
kenjiArai 0:5b88d5760320 26 #include <ble/DiscoveredService.h>
kenjiArai 0:5b88d5760320 27 #include <ble/DiscoveredCharacteristic.h>
kenjiArai 0:5b88d5760320 28 #include "ble/generic/GenericGattClient.h"
kenjiArai 0:5b88d5760320 29 #include "ble/blecommon.h"
kenjiArai 0:5b88d5760320 30 #include "ble/BLEInstanceBase.h"
kenjiArai 0:5b88d5760320 31 #include <algorithm>
kenjiArai 0:5b88d5760320 32
kenjiArai 0:5b88d5760320 33 using ble::pal::AttServerMessage;
kenjiArai 0:5b88d5760320 34 using ble::pal::AttReadResponse;
kenjiArai 0:5b88d5760320 35 using ble::pal::AttReadBlobResponse;
kenjiArai 0:5b88d5760320 36 using ble::pal::AttReadByTypeResponse;
kenjiArai 0:5b88d5760320 37 using ble::pal::AttReadByGroupTypeResponse;
kenjiArai 0:5b88d5760320 38 using ble::pal::AttFindByTypeValueResponse;
kenjiArai 0:5b88d5760320 39 using ble::pal::AttErrorResponse;
kenjiArai 0:5b88d5760320 40 using ble::pal::AttributeOpcode;
kenjiArai 0:5b88d5760320 41 using ble::pal::AttWriteResponse;
kenjiArai 0:5b88d5760320 42 using ble::pal::AttPrepareWriteResponse;
kenjiArai 0:5b88d5760320 43 using ble::pal::AttExecuteWriteResponse;
kenjiArai 0:5b88d5760320 44 using ble::pal::AttHandleValueIndication;
kenjiArai 0:5b88d5760320 45 using ble::pal::AttHandleValueNotification;
kenjiArai 0:5b88d5760320 46 using ble::pal::AttFindInformationResponse;
kenjiArai 0:5b88d5760320 47
kenjiArai 0:5b88d5760320 48 #define PREPARE_WRITE_HEADER_LENGTH 5
kenjiArai 0:5b88d5760320 49 #define WRITE_HEADER_LENGTH 3
kenjiArai 0:5b88d5760320 50 #define CMAC_LENGTH 8
kenjiArai 0:5b88d5760320 51 #define MAC_COUNTER_LENGTH 4
kenjiArai 0:5b88d5760320 52
kenjiArai 0:5b88d5760320 53 namespace ble {
kenjiArai 0:5b88d5760320 54 namespace generic {
kenjiArai 0:5b88d5760320 55
kenjiArai 0:5b88d5760320 56 /*
kenjiArai 0:5b88d5760320 57 * Type of procedures which can be launched by the client.
kenjiArai 0:5b88d5760320 58 */
kenjiArai 0:5b88d5760320 59 enum procedure_type_t {
kenjiArai 0:5b88d5760320 60 COMPLETE_DISCOVERY_PROCEDURE,
kenjiArai 0:5b88d5760320 61 READ_PROCEDURE,
kenjiArai 0:5b88d5760320 62 WRITE_PROCEDURE,
kenjiArai 0:5b88d5760320 63 DESCRIPTOR_DISCOVERY_PROCEDURE
kenjiArai 0:5b88d5760320 64 };
kenjiArai 0:5b88d5760320 65
kenjiArai 0:5b88d5760320 66
kenjiArai 0:5b88d5760320 67 /*
kenjiArai 0:5b88d5760320 68 * Base class for a procedure control block
kenjiArai 0:5b88d5760320 69 */
kenjiArai 0:5b88d5760320 70 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 71 struct GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::ProcedureControlBlock {
kenjiArai 0:5b88d5760320 72 /*
kenjiArai 0:5b88d5760320 73 * Base constructor for procedure control block.
kenjiArai 0:5b88d5760320 74 */
kenjiArai 0:5b88d5760320 75 ProcedureControlBlock(procedure_type_t type, connection_handle_t handle) :
kenjiArai 0:5b88d5760320 76 type(type), connection_handle(handle), next(NULL) { }
kenjiArai 0:5b88d5760320 77
kenjiArai 0:5b88d5760320 78 virtual ~ProcedureControlBlock() { }
kenjiArai 0:5b88d5760320 79
kenjiArai 0:5b88d5760320 80 /*
kenjiArai 0:5b88d5760320 81 * Entry point of the control block stack machine.
kenjiArai 0:5b88d5760320 82 */
kenjiArai 0:5b88d5760320 83 virtual void handle(GenericGattClient* client, const AttServerMessage& message) = 0;
kenjiArai 0:5b88d5760320 84
kenjiArai 0:5b88d5760320 85 /*
kenjiArai 0:5b88d5760320 86 * Function call in case of timeout
kenjiArai 0:5b88d5760320 87 */
kenjiArai 0:5b88d5760320 88 virtual void handle_timeout_error(GenericGattClient* client) = 0;
kenjiArai 0:5b88d5760320 89
kenjiArai 0:5b88d5760320 90 /**
kenjiArai 0:5b88d5760320 91 * Function called when the procedure is aborted
kenjiArai 0:5b88d5760320 92 */
kenjiArai 0:5b88d5760320 93 virtual void abort(GenericGattClient *client) = 0;
kenjiArai 0:5b88d5760320 94
kenjiArai 0:5b88d5760320 95 procedure_type_t type;
kenjiArai 0:5b88d5760320 96 connection_handle_t connection_handle;
kenjiArai 0:5b88d5760320 97 ProcedureControlBlock* next;
kenjiArai 0:5b88d5760320 98 };
kenjiArai 0:5b88d5760320 99
kenjiArai 0:5b88d5760320 100
kenjiArai 0:5b88d5760320 101 /*
kenjiArai 0:5b88d5760320 102 * Procedure control block for the discovery process.
kenjiArai 0:5b88d5760320 103 */
kenjiArai 0:5b88d5760320 104 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 105 struct GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::DiscoveryControlBlock : public ProcedureControlBlock {
kenjiArai 0:5b88d5760320 106 using ProcedureControlBlock::connection_handle;
kenjiArai 0:5b88d5760320 107
kenjiArai 0:5b88d5760320 108 DiscoveryControlBlock(
kenjiArai 0:5b88d5760320 109 connection_handle_t handle,
kenjiArai 0:5b88d5760320 110 ServiceDiscovery::ServiceCallback_t service_callback,
kenjiArai 0:5b88d5760320 111 ServiceDiscovery::CharacteristicCallback_t characteristic_callback,
kenjiArai 0:5b88d5760320 112 UUID matching_service_uuid,
kenjiArai 0:5b88d5760320 113 UUID matching_characteristic_uuid
kenjiArai 0:5b88d5760320 114 ) : ProcedureControlBlock(COMPLETE_DISCOVERY_PROCEDURE, handle),
kenjiArai 0:5b88d5760320 115 service_callback(service_callback),
kenjiArai 0:5b88d5760320 116 characteristic_callback(characteristic_callback),
kenjiArai 0:5b88d5760320 117 matching_service_uuid(matching_service_uuid),
kenjiArai 0:5b88d5760320 118 matching_characteristic_uuid(matching_characteristic_uuid),
kenjiArai 0:5b88d5760320 119 services_discovered(NULL),
kenjiArai 0:5b88d5760320 120 done(false) {
kenjiArai 0:5b88d5760320 121 }
kenjiArai 0:5b88d5760320 122
kenjiArai 0:5b88d5760320 123 virtual ~DiscoveryControlBlock() {
kenjiArai 0:5b88d5760320 124 while(services_discovered) {
kenjiArai 0:5b88d5760320 125 service_t* tmp = services_discovered->next;
kenjiArai 0:5b88d5760320 126 delete services_discovered;
kenjiArai 0:5b88d5760320 127 services_discovered = tmp;
kenjiArai 0:5b88d5760320 128 }
kenjiArai 0:5b88d5760320 129 }
kenjiArai 0:5b88d5760320 130
kenjiArai 0:5b88d5760320 131 virtual void handle_timeout_error(GenericGattClient* client) {
kenjiArai 0:5b88d5760320 132 terminate(client);
kenjiArai 0:5b88d5760320 133 }
kenjiArai 0:5b88d5760320 134
kenjiArai 0:5b88d5760320 135 virtual void abort(GenericGattClient *client) {
kenjiArai 0:5b88d5760320 136 terminate(client);
kenjiArai 0:5b88d5760320 137 }
kenjiArai 0:5b88d5760320 138
kenjiArai 0:5b88d5760320 139 virtual void handle(GenericGattClient* client, const AttServerMessage& message) {
kenjiArai 0:5b88d5760320 140 // if end of discovery has been requested, ends it immediately
kenjiArai 0:5b88d5760320 141 if (done) {
kenjiArai 0:5b88d5760320 142 terminate(client);
kenjiArai 0:5b88d5760320 143 return;
kenjiArai 0:5b88d5760320 144 }
kenjiArai 0:5b88d5760320 145
kenjiArai 0:5b88d5760320 146 switch(message.opcode) {
kenjiArai 0:5b88d5760320 147 case AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE:
kenjiArai 0:5b88d5760320 148 handle_service_discovered(
kenjiArai 0:5b88d5760320 149 client, static_cast<const AttReadByGroupTypeResponse&>(message)
kenjiArai 0:5b88d5760320 150 );
kenjiArai 0:5b88d5760320 151 break;
kenjiArai 0:5b88d5760320 152 case AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE:
kenjiArai 0:5b88d5760320 153 handle_service_discovered(
kenjiArai 0:5b88d5760320 154 client, static_cast<const AttFindByTypeValueResponse&>(message)
kenjiArai 0:5b88d5760320 155 );
kenjiArai 0:5b88d5760320 156 break;
kenjiArai 0:5b88d5760320 157 case AttributeOpcode::READ_BY_TYPE_RESPONSE:
kenjiArai 0:5b88d5760320 158 handle_characteristic_discovered(
kenjiArai 0:5b88d5760320 159 client, static_cast<const AttReadByTypeResponse&>(message)
kenjiArai 0:5b88d5760320 160 );
kenjiArai 0:5b88d5760320 161 break;
kenjiArai 0:5b88d5760320 162 case AttributeOpcode::ERROR_RESPONSE: {
kenjiArai 0:5b88d5760320 163 const AttErrorResponse& error = static_cast<const AttErrorResponse&>(message);
kenjiArai 0:5b88d5760320 164 if (error.error_code != AttErrorResponse::ATTRIBUTE_NOT_FOUND) {
kenjiArai 0:5b88d5760320 165 terminate(client);
kenjiArai 0:5b88d5760320 166 return;
kenjiArai 0:5b88d5760320 167 }
kenjiArai 0:5b88d5760320 168
kenjiArai 0:5b88d5760320 169 switch (error.request_opcode) {
kenjiArai 0:5b88d5760320 170 case AttributeOpcode::READ_BY_GROUP_TYPE_REQUEST:
kenjiArai 0:5b88d5760320 171 case AttributeOpcode::FIND_BY_TYPE_VALUE_REQUEST:
kenjiArai 0:5b88d5760320 172 start_characteristic_discovery(client);
kenjiArai 0:5b88d5760320 173 break;
kenjiArai 0:5b88d5760320 174 case AttributeOpcode::READ_BY_TYPE_REQUEST:
kenjiArai 0:5b88d5760320 175 handle_all_characteristics_discovered(client);
kenjiArai 0:5b88d5760320 176 break;
kenjiArai 0:5b88d5760320 177 default:
kenjiArai 0:5b88d5760320 178 // error
kenjiArai 0:5b88d5760320 179 break;
kenjiArai 0:5b88d5760320 180 }
kenjiArai 0:5b88d5760320 181 } break;
kenjiArai 0:5b88d5760320 182 default:
kenjiArai 0:5b88d5760320 183 // error
kenjiArai 0:5b88d5760320 184 break;
kenjiArai 0:5b88d5760320 185 }
kenjiArai 0:5b88d5760320 186 }
kenjiArai 0:5b88d5760320 187
kenjiArai 0:5b88d5760320 188 template<typename Response>
kenjiArai 0:5b88d5760320 189 void handle_service_discovered(GenericGattClient* client, const Response& response) {
kenjiArai 0:5b88d5760320 190 if (!response.size()) {
kenjiArai 0:5b88d5760320 191 terminate(client);
kenjiArai 0:5b88d5760320 192 return;
kenjiArai 0:5b88d5760320 193 }
kenjiArai 0:5b88d5760320 194
kenjiArai 0:5b88d5760320 195 uint16_t end_handle = 0x0000;
kenjiArai 0:5b88d5760320 196 for (size_t i = 0; i < response.size(); ++i) {
kenjiArai 0:5b88d5760320 197 uint16_t start_handle = get_start_handle(response[i]);
kenjiArai 0:5b88d5760320 198 end_handle = get_end_handle(response[i]);
kenjiArai 0:5b88d5760320 199 UUID uuid = get_uuid(response[i]);
kenjiArai 0:5b88d5760320 200
kenjiArai 0:5b88d5760320 201 if (!characteristic_callback) {
kenjiArai 0:5b88d5760320 202 DiscoveredService discovered_service;
kenjiArai 0:5b88d5760320 203 discovered_service.setup(uuid, start_handle, end_handle);
kenjiArai 0:5b88d5760320 204 service_callback(&discovered_service);
kenjiArai 0:5b88d5760320 205 } else {
kenjiArai 0:5b88d5760320 206 service_t* discovered_service = new (std::nothrow) service_t(
kenjiArai 0:5b88d5760320 207 start_handle, end_handle, uuid
kenjiArai 0:5b88d5760320 208 );
kenjiArai 0:5b88d5760320 209
kenjiArai 0:5b88d5760320 210 if (discovered_service == NULL) {
kenjiArai 0:5b88d5760320 211 terminate(client);
kenjiArai 0:5b88d5760320 212 return;
kenjiArai 0:5b88d5760320 213 }
kenjiArai 0:5b88d5760320 214
kenjiArai 0:5b88d5760320 215 insert_service(discovered_service);
kenjiArai 0:5b88d5760320 216 }
kenjiArai 0:5b88d5760320 217 }
kenjiArai 0:5b88d5760320 218
kenjiArai 0:5b88d5760320 219 if (end_handle == 0xFFFF) {
kenjiArai 0:5b88d5760320 220 start_characteristic_discovery(client);
kenjiArai 0:5b88d5760320 221 } else {
kenjiArai 0:5b88d5760320 222 ble_error_t err = client->_pal_client->discover_primary_service(
kenjiArai 0:5b88d5760320 223 connection_handle, end_handle + 1
kenjiArai 0:5b88d5760320 224 );
kenjiArai 0:5b88d5760320 225
kenjiArai 0:5b88d5760320 226 if (err) {
kenjiArai 0:5b88d5760320 227 terminate(client);
kenjiArai 0:5b88d5760320 228 }
kenjiArai 0:5b88d5760320 229 }
kenjiArai 0:5b88d5760320 230 }
kenjiArai 0:5b88d5760320 231
kenjiArai 0:5b88d5760320 232 void start_characteristic_discovery(GenericGattClient* client) {
kenjiArai 0:5b88d5760320 233 if (!services_discovered) {
kenjiArai 0:5b88d5760320 234 terminate(client);
kenjiArai 0:5b88d5760320 235 return;
kenjiArai 0:5b88d5760320 236 }
kenjiArai 0:5b88d5760320 237
kenjiArai 0:5b88d5760320 238 if (!characteristic_callback) {
kenjiArai 0:5b88d5760320 239 terminate(client);
kenjiArai 0:5b88d5760320 240 return;
kenjiArai 0:5b88d5760320 241 }
kenjiArai 0:5b88d5760320 242
kenjiArai 0:5b88d5760320 243 if (service_callback) {
kenjiArai 0:5b88d5760320 244 DiscoveredService discovered_service;
kenjiArai 0:5b88d5760320 245 discovered_service.setup(
kenjiArai 0:5b88d5760320 246 services_discovered->uuid,
kenjiArai 0:5b88d5760320 247 services_discovered->begin,
kenjiArai 0:5b88d5760320 248 services_discovered->end
kenjiArai 0:5b88d5760320 249 );
kenjiArai 0:5b88d5760320 250 service_callback(&discovered_service);
kenjiArai 0:5b88d5760320 251 }
kenjiArai 0:5b88d5760320 252
kenjiArai 0:5b88d5760320 253 last_characteristic = characteristic_t();
kenjiArai 0:5b88d5760320 254 client->_pal_client->discover_characteristics_of_a_service(
kenjiArai 0:5b88d5760320 255 connection_handle,
kenjiArai 0:5b88d5760320 256 attribute_handle_range(
kenjiArai 0:5b88d5760320 257 services_discovered->begin,
kenjiArai 0:5b88d5760320 258 services_discovered->end
kenjiArai 0:5b88d5760320 259 )
kenjiArai 0:5b88d5760320 260 );
kenjiArai 0:5b88d5760320 261 }
kenjiArai 0:5b88d5760320 262
kenjiArai 0:5b88d5760320 263 void handle_characteristic_discovered(GenericGattClient* client, const AttReadByTypeResponse& response) {
kenjiArai 0:5b88d5760320 264 for (size_t i = 0; i < response.size(); ++i) {
kenjiArai 0:5b88d5760320 265 if (last_characteristic.is_valid() == false) {
kenjiArai 0:5b88d5760320 266 last_characteristic.set_last_handle(response[i].handle - 1);
kenjiArai 0:5b88d5760320 267 if (matching_characteristic_uuid == UUID()
kenjiArai 0:5b88d5760320 268 || last_characteristic.getUUID() == matching_characteristic_uuid) {
kenjiArai 0:5b88d5760320 269 characteristic_callback(&last_characteristic);
kenjiArai 0:5b88d5760320 270 }
kenjiArai 0:5b88d5760320 271 }
kenjiArai 0:5b88d5760320 272
kenjiArai 0:5b88d5760320 273 last_characteristic = characteristic_t(
kenjiArai 0:5b88d5760320 274 client, connection_handle, response[i].handle, response[i].value
kenjiArai 0:5b88d5760320 275 );
kenjiArai 0:5b88d5760320 276 }
kenjiArai 0:5b88d5760320 277
kenjiArai 0:5b88d5760320 278 // check if all the characteristics of the service has been discovered
kenjiArai 0:5b88d5760320 279 if (last_characteristic.getValueHandle() == services_discovered->end) {
kenjiArai 0:5b88d5760320 280 handle_all_characteristics_discovered(client);
kenjiArai 0:5b88d5760320 281 } else {
kenjiArai 0:5b88d5760320 282 ble_error_t err = client->_pal_client->discover_characteristics_of_a_service(
kenjiArai 0:5b88d5760320 283 connection_handle,
kenjiArai 0:5b88d5760320 284 attribute_handle_range(
kenjiArai 0:5b88d5760320 285 last_characteristic.getValueHandle() + 1,
kenjiArai 0:5b88d5760320 286 services_discovered->end
kenjiArai 0:5b88d5760320 287 )
kenjiArai 0:5b88d5760320 288 );
kenjiArai 0:5b88d5760320 289
kenjiArai 0:5b88d5760320 290 if (err) {
kenjiArai 0:5b88d5760320 291 terminate(client);
kenjiArai 0:5b88d5760320 292 }
kenjiArai 0:5b88d5760320 293 }
kenjiArai 0:5b88d5760320 294 }
kenjiArai 0:5b88d5760320 295
kenjiArai 0:5b88d5760320 296 void handle_all_characteristics_discovered(GenericGattClient* client) {
kenjiArai 0:5b88d5760320 297 if (last_characteristic.is_valid() == false) {
kenjiArai 0:5b88d5760320 298 if (matching_characteristic_uuid == UUID()
kenjiArai 0:5b88d5760320 299 || matching_characteristic_uuid == last_characteristic.getUUID()) {
kenjiArai 0:5b88d5760320 300 last_characteristic.set_last_handle(services_discovered->end);
kenjiArai 0:5b88d5760320 301 characteristic_callback(&last_characteristic);
kenjiArai 0:5b88d5760320 302 }
kenjiArai 0:5b88d5760320 303 }
kenjiArai 0:5b88d5760320 304
kenjiArai 0:5b88d5760320 305 service_t* old = services_discovered;
kenjiArai 0:5b88d5760320 306 services_discovered = services_discovered->next;
kenjiArai 0:5b88d5760320 307 delete old;
kenjiArai 0:5b88d5760320 308
kenjiArai 0:5b88d5760320 309 if (!services_discovered) {
kenjiArai 0:5b88d5760320 310 terminate(client);
kenjiArai 0:5b88d5760320 311 } else {
kenjiArai 0:5b88d5760320 312 start_characteristic_discovery(client);
kenjiArai 0:5b88d5760320 313 }
kenjiArai 0:5b88d5760320 314 }
kenjiArai 0:5b88d5760320 315
kenjiArai 0:5b88d5760320 316 void terminate(GenericGattClient* client) {
kenjiArai 0:5b88d5760320 317 // unknown error, terminate the procedure immediately
kenjiArai 0:5b88d5760320 318 client->remove_control_block(this);
kenjiArai 0:5b88d5760320 319 connection_handle_t handle = connection_handle;
kenjiArai 0:5b88d5760320 320 delete this;
kenjiArai 0:5b88d5760320 321 client->on_termination(handle);
kenjiArai 0:5b88d5760320 322 }
kenjiArai 0:5b88d5760320 323
kenjiArai 0:5b88d5760320 324 uint16_t get_start_handle(const AttReadByGroupTypeResponse::attribute_data_t& data) {
kenjiArai 0:5b88d5760320 325 return data.group_range.begin;
kenjiArai 0:5b88d5760320 326 }
kenjiArai 0:5b88d5760320 327
kenjiArai 0:5b88d5760320 328 uint16_t get_start_handle(const attribute_handle_range_t& range) {
kenjiArai 0:5b88d5760320 329 return range.begin;
kenjiArai 0:5b88d5760320 330 }
kenjiArai 0:5b88d5760320 331
kenjiArai 0:5b88d5760320 332 uint16_t get_end_handle(const AttReadByGroupTypeResponse::attribute_data_t& data) {
kenjiArai 0:5b88d5760320 333 return data.group_range.end;
kenjiArai 0:5b88d5760320 334 }
kenjiArai 0:5b88d5760320 335
kenjiArai 0:5b88d5760320 336 uint16_t get_end_handle(const attribute_handle_range_t& range) {
kenjiArai 0:5b88d5760320 337 return range.end;
kenjiArai 0:5b88d5760320 338 }
kenjiArai 0:5b88d5760320 339
kenjiArai 0:5b88d5760320 340 UUID get_uuid(const AttReadByGroupTypeResponse::attribute_data_t& data) {
kenjiArai 0:5b88d5760320 341 if (data.value.size() == 2) {
kenjiArai 0:5b88d5760320 342 return UUID(data.value[0] | data.value[1] << 8);
kenjiArai 0:5b88d5760320 343 } else {
kenjiArai 0:5b88d5760320 344 return UUID(data.value.data(), UUID::LSB);
kenjiArai 0:5b88d5760320 345 }
kenjiArai 0:5b88d5760320 346 }
kenjiArai 0:5b88d5760320 347
kenjiArai 0:5b88d5760320 348 UUID get_uuid(const attribute_handle_range_t& range) {
kenjiArai 0:5b88d5760320 349 return matching_service_uuid;
kenjiArai 0:5b88d5760320 350 }
kenjiArai 0:5b88d5760320 351
kenjiArai 0:5b88d5760320 352 struct service_t {
kenjiArai 0:5b88d5760320 353 service_t(uint16_t begin, uint16_t end, const UUID& uuid) :
kenjiArai 0:5b88d5760320 354 begin(begin), end(end), uuid(uuid), next(NULL) { }
kenjiArai 0:5b88d5760320 355 uint16_t begin;
kenjiArai 0:5b88d5760320 356 uint16_t end;
kenjiArai 0:5b88d5760320 357 UUID uuid;
kenjiArai 0:5b88d5760320 358 service_t* next;
kenjiArai 0:5b88d5760320 359 };
kenjiArai 0:5b88d5760320 360
kenjiArai 0:5b88d5760320 361 struct characteristic_t : DiscoveredCharacteristic {
kenjiArai 0:5b88d5760320 362 characteristic_t() : DiscoveredCharacteristic() {
kenjiArai 0:5b88d5760320 363 lastHandle = 0x0001;
kenjiArai 0:5b88d5760320 364 }
kenjiArai 0:5b88d5760320 365
kenjiArai 0:5b88d5760320 366 characteristic_t(
kenjiArai 0:5b88d5760320 367 GattClient* client,
kenjiArai 0:5b88d5760320 368 connection_handle_t connection_handle,
kenjiArai 0:5b88d5760320 369 uint16_t decl_handle,
kenjiArai 0:5b88d5760320 370 const Span<const uint8_t> value
kenjiArai 0:5b88d5760320 371 ) : DiscoveredCharacteristic() {
kenjiArai 0:5b88d5760320 372 gattc = client;
kenjiArai 0:5b88d5760320 373 uuid = get_uuid(value);
kenjiArai 0:5b88d5760320 374 props = get_properties(value);
kenjiArai 0:5b88d5760320 375 declHandle = decl_handle;
kenjiArai 0:5b88d5760320 376 valueHandle = get_value_handle(value);
kenjiArai 0:5b88d5760320 377 lastHandle = 0x0000;
kenjiArai 0:5b88d5760320 378 connHandle = connection_handle;
kenjiArai 0:5b88d5760320 379 }
kenjiArai 0:5b88d5760320 380
kenjiArai 0:5b88d5760320 381 static UUID get_uuid(const Span<const uint8_t>& value) {
kenjiArai 0:5b88d5760320 382 if (value.size() == 5) {
kenjiArai 0:5b88d5760320 383 return UUID(value[3] | (value[4] << 8));
kenjiArai 0:5b88d5760320 384 } else {
kenjiArai 0:5b88d5760320 385 return UUID(value.data() + 3, UUID::LSB);
kenjiArai 0:5b88d5760320 386 }
kenjiArai 0:5b88d5760320 387 }
kenjiArai 0:5b88d5760320 388
kenjiArai 0:5b88d5760320 389 static DiscoveredCharacteristic::Properties_t get_properties(const Span<const uint8_t>& value) {
kenjiArai 0:5b88d5760320 390 uint8_t raw_properties = value[0];
kenjiArai 0:5b88d5760320 391 DiscoveredCharacteristic::Properties_t result;
kenjiArai 0:5b88d5760320 392 result._broadcast = (raw_properties & (1 << 0)) ? true : false;
kenjiArai 0:5b88d5760320 393 result._read = (raw_properties & (1 << 1)) ? true : false;
kenjiArai 0:5b88d5760320 394 result._writeWoResp = (raw_properties & (1 << 2)) ? true : false;
kenjiArai 0:5b88d5760320 395 result._write = (raw_properties & (1 << 3)) ? true : false;
kenjiArai 0:5b88d5760320 396 result._notify = (raw_properties & (1 << 4)) ? true : false;
kenjiArai 0:5b88d5760320 397 result._indicate = (raw_properties & (1 << 5)) ? true : false;
kenjiArai 0:5b88d5760320 398 result._authSignedWrite = (raw_properties & (1 << 6)) ? true : false;
kenjiArai 0:5b88d5760320 399 return result;
kenjiArai 0:5b88d5760320 400 }
kenjiArai 0:5b88d5760320 401
kenjiArai 0:5b88d5760320 402 static uint16_t get_value_handle(const Span<const uint8_t>& value) {
kenjiArai 0:5b88d5760320 403 return value[1] | (value[2] << 8);
kenjiArai 0:5b88d5760320 404 }
kenjiArai 0:5b88d5760320 405
kenjiArai 0:5b88d5760320 406 void set_last_handle(uint16_t last_handle) {
kenjiArai 0:5b88d5760320 407 lastHandle = last_handle;
kenjiArai 0:5b88d5760320 408 }
kenjiArai 0:5b88d5760320 409
kenjiArai 0:5b88d5760320 410 bool is_valid() const {
kenjiArai 0:5b88d5760320 411 return lastHandle != 0x0000;
kenjiArai 0:5b88d5760320 412 }
kenjiArai 0:5b88d5760320 413 };
kenjiArai 0:5b88d5760320 414
kenjiArai 0:5b88d5760320 415 void insert_service(service_t* service) {
kenjiArai 0:5b88d5760320 416 if (services_discovered == NULL) {
kenjiArai 0:5b88d5760320 417 services_discovered = service;
kenjiArai 0:5b88d5760320 418 return;
kenjiArai 0:5b88d5760320 419 }
kenjiArai 0:5b88d5760320 420
kenjiArai 0:5b88d5760320 421 service_t* current = services_discovered;
kenjiArai 0:5b88d5760320 422 while (current->next) {
kenjiArai 0:5b88d5760320 423 current = current->next;
kenjiArai 0:5b88d5760320 424 }
kenjiArai 0:5b88d5760320 425 current->next = service;
kenjiArai 0:5b88d5760320 426 }
kenjiArai 0:5b88d5760320 427
kenjiArai 0:5b88d5760320 428 ServiceDiscovery::ServiceCallback_t service_callback;
kenjiArai 0:5b88d5760320 429 ServiceDiscovery::CharacteristicCallback_t characteristic_callback;
kenjiArai 0:5b88d5760320 430 UUID matching_service_uuid;
kenjiArai 0:5b88d5760320 431 UUID matching_characteristic_uuid;
kenjiArai 0:5b88d5760320 432 service_t* services_discovered;
kenjiArai 0:5b88d5760320 433 characteristic_t last_characteristic;
kenjiArai 0:5b88d5760320 434 bool done;
kenjiArai 0:5b88d5760320 435 };
kenjiArai 0:5b88d5760320 436
kenjiArai 0:5b88d5760320 437
kenjiArai 0:5b88d5760320 438 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 439 struct GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::ReadControlBlock : public ProcedureControlBlock {
kenjiArai 0:5b88d5760320 440 using ProcedureControlBlock::connection_handle;
kenjiArai 0:5b88d5760320 441
kenjiArai 0:5b88d5760320 442 ReadControlBlock(
kenjiArai 0:5b88d5760320 443 connection_handle_t connection_handle, uint16_t attribute_handle, uint16_t offset
kenjiArai 0:5b88d5760320 444 ) : ProcedureControlBlock(READ_PROCEDURE, connection_handle),
kenjiArai 0:5b88d5760320 445 attribute_handle(attribute_handle),
kenjiArai 0:5b88d5760320 446 offset(offset), current_offset(offset), data(NULL) {
kenjiArai 0:5b88d5760320 447 }
kenjiArai 0:5b88d5760320 448
kenjiArai 0:5b88d5760320 449 virtual ~ReadControlBlock() {
kenjiArai 0:5b88d5760320 450 if (data != NULL) {
kenjiArai 0:5b88d5760320 451 free(data);
kenjiArai 0:5b88d5760320 452 }
kenjiArai 0:5b88d5760320 453 }
kenjiArai 0:5b88d5760320 454
kenjiArai 0:5b88d5760320 455 virtual void handle_timeout_error(GenericGattClient* client) {
kenjiArai 0:5b88d5760320 456 GattReadCallbackParams response = {
kenjiArai 0:5b88d5760320 457 connection_handle,
kenjiArai 0:5b88d5760320 458 attribute_handle,
kenjiArai 0:5b88d5760320 459 offset,
kenjiArai 0:5b88d5760320 460 0, // size of 0
kenjiArai 0:5b88d5760320 461 NULL, // no data
kenjiArai 0:5b88d5760320 462 BLE_ERROR_UNSPECIFIED,
kenjiArai 0:5b88d5760320 463
kenjiArai 0:5b88d5760320 464 };
kenjiArai 0:5b88d5760320 465 terminate(client, response);
kenjiArai 0:5b88d5760320 466 }
kenjiArai 0:5b88d5760320 467
kenjiArai 0:5b88d5760320 468 virtual void abort(GenericGattClient *client) {
kenjiArai 0:5b88d5760320 469 GattReadCallbackParams response = {
kenjiArai 0:5b88d5760320 470 connection_handle,
kenjiArai 0:5b88d5760320 471 attribute_handle,
kenjiArai 0:5b88d5760320 472 offset,
kenjiArai 0:5b88d5760320 473 0, // size of 0
kenjiArai 0:5b88d5760320 474 NULL, // no data
kenjiArai 0:5b88d5760320 475 BLE_ERROR_INVALID_STATE,
kenjiArai 0:5b88d5760320 476
kenjiArai 0:5b88d5760320 477 };
kenjiArai 0:5b88d5760320 478 terminate(client, response);
kenjiArai 0:5b88d5760320 479 }
kenjiArai 0:5b88d5760320 480
kenjiArai 0:5b88d5760320 481 void terminate(GenericGattClient* client, const GattReadCallbackParams& response) {
kenjiArai 0:5b88d5760320 482 client->remove_control_block(this);
kenjiArai 0:5b88d5760320 483 client->processReadResponse(&response);
kenjiArai 0:5b88d5760320 484 delete this;
kenjiArai 0:5b88d5760320 485 }
kenjiArai 0:5b88d5760320 486
kenjiArai 0:5b88d5760320 487 virtual void handle(GenericGattClient* client, const AttServerMessage& message) {
kenjiArai 0:5b88d5760320 488 switch(message.opcode) {
kenjiArai 0:5b88d5760320 489 case AttributeOpcode::ERROR_RESPONSE:
kenjiArai 0:5b88d5760320 490 handle_error(client, static_cast<const AttErrorResponse&>(message));
kenjiArai 0:5b88d5760320 491 break;
kenjiArai 0:5b88d5760320 492
kenjiArai 0:5b88d5760320 493 case AttributeOpcode::READ_RESPONSE:
kenjiArai 0:5b88d5760320 494 handle_read_response(client, static_cast<const AttReadResponse&>(message));
kenjiArai 0:5b88d5760320 495 break;
kenjiArai 0:5b88d5760320 496
kenjiArai 0:5b88d5760320 497 case AttributeOpcode::READ_BLOB_RESPONSE:
kenjiArai 0:5b88d5760320 498 handle_read_response(client, static_cast<const AttReadBlobResponse&>(message));
kenjiArai 0:5b88d5760320 499 break;
kenjiArai 0:5b88d5760320 500
kenjiArai 0:5b88d5760320 501 default: {
kenjiArai 0:5b88d5760320 502 // should not happen, terminate the procedure and notify client with an error
kenjiArai 0:5b88d5760320 503 // in such case
kenjiArai 0:5b88d5760320 504 GattReadCallbackParams response = {
kenjiArai 0:5b88d5760320 505 connection_handle,
kenjiArai 0:5b88d5760320 506 attribute_handle,
kenjiArai 0:5b88d5760320 507 AttErrorResponse::UNLIKELY_ERROR,
kenjiArai 0:5b88d5760320 508 0, // size of 0
kenjiArai 0:5b88d5760320 509 NULL, // no data
kenjiArai 0:5b88d5760320 510 BLE_ERROR_UNSPECIFIED,
kenjiArai 0:5b88d5760320 511
kenjiArai 0:5b88d5760320 512 };
kenjiArai 0:5b88d5760320 513 terminate(client, response);
kenjiArai 0:5b88d5760320 514 } break;
kenjiArai 0:5b88d5760320 515 }
kenjiArai 0:5b88d5760320 516 }
kenjiArai 0:5b88d5760320 517
kenjiArai 0:5b88d5760320 518 template<typename ResponseType>
kenjiArai 0:5b88d5760320 519 void handle_read_response(GenericGattClient* client, const ResponseType& read_response) {
kenjiArai 0:5b88d5760320 520 uint16_t mtu_size = client->get_mtu(connection_handle);
kenjiArai 0:5b88d5760320 521
kenjiArai 0:5b88d5760320 522 // end of responses ?
kenjiArai 0:5b88d5760320 523 if ((uint16_t) read_response.size() < (mtu_size - 1)) {
kenjiArai 0:5b88d5760320 524 GattReadCallbackParams response = {
kenjiArai 0:5b88d5760320 525 connection_handle,
kenjiArai 0:5b88d5760320 526 attribute_handle,
kenjiArai 0:5b88d5760320 527 offset,
kenjiArai 0:5b88d5760320 528 0, // size of 0
kenjiArai 0:5b88d5760320 529 NULL, // no data
kenjiArai 0:5b88d5760320 530 BLE_ERROR_NONE,
kenjiArai 0:5b88d5760320 531 };
kenjiArai 0:5b88d5760320 532
kenjiArai 0:5b88d5760320 533 // is it the first response, or is there any other response already
kenjiArai 0:5b88d5760320 534 // in the object ?
kenjiArai 0:5b88d5760320 535 if (data == NULL) {
kenjiArai 0:5b88d5760320 536 response.len = (uint16_t) read_response.size();
kenjiArai 0:5b88d5760320 537 response.data = read_response.data();
kenjiArai 0:5b88d5760320 538 } else {
kenjiArai 0:5b88d5760320 539 // copy the data in the existing buffer
kenjiArai 0:5b88d5760320 540 memcpy(data + (current_offset - offset), read_response.data(), read_response.size());
kenjiArai 0:5b88d5760320 541 response.len = (current_offset + read_response.size()) - offset;
kenjiArai 0:5b88d5760320 542 response.data = data;
kenjiArai 0:5b88d5760320 543 }
kenjiArai 0:5b88d5760320 544 terminate(client, response);
kenjiArai 0:5b88d5760320 545 } else {
kenjiArai 0:5b88d5760320 546 // allocation which will contain the response data plus the next one.
kenjiArai 0:5b88d5760320 547 data = (uint8_t*) realloc(data, (current_offset - offset) + ((mtu_size - 1) * 2));
kenjiArai 0:5b88d5760320 548 if (data == NULL) {
kenjiArai 0:5b88d5760320 549 GattReadCallbackParams response = {
kenjiArai 0:5b88d5760320 550 connection_handle,
kenjiArai 0:5b88d5760320 551 attribute_handle,
kenjiArai 0:5b88d5760320 552 offset,
kenjiArai 0:5b88d5760320 553 AttErrorResponse::INSUFFICIENT_RESOURCES,
kenjiArai 0:5b88d5760320 554 NULL,
kenjiArai 0:5b88d5760320 555 BLE_ERROR_NO_MEM,
kenjiArai 0:5b88d5760320 556 };
kenjiArai 0:5b88d5760320 557 terminate(client, response);
kenjiArai 0:5b88d5760320 558 return;
kenjiArai 0:5b88d5760320 559 }
kenjiArai 0:5b88d5760320 560
kenjiArai 0:5b88d5760320 561 memcpy(data + (current_offset - offset), read_response.data(), read_response.size());
kenjiArai 0:5b88d5760320 562 current_offset = current_offset + read_response.size();
kenjiArai 0:5b88d5760320 563 ble_error_t err = client->_pal_client->read_attribute_blob(
kenjiArai 0:5b88d5760320 564 connection_handle,
kenjiArai 0:5b88d5760320 565 attribute_handle,
kenjiArai 0:5b88d5760320 566 current_offset
kenjiArai 0:5b88d5760320 567 );
kenjiArai 0:5b88d5760320 568
kenjiArai 0:5b88d5760320 569 if (err) {
kenjiArai 0:5b88d5760320 570 GattReadCallbackParams response = {
kenjiArai 0:5b88d5760320 571 connection_handle,
kenjiArai 0:5b88d5760320 572 attribute_handle,
kenjiArai 0:5b88d5760320 573 AttErrorResponse::UNLIKELY_ERROR,
kenjiArai 0:5b88d5760320 574 0, // size of 0
kenjiArai 0:5b88d5760320 575 NULL, // no data
kenjiArai 0:5b88d5760320 576 BLE_ERROR_UNSPECIFIED,
kenjiArai 0:5b88d5760320 577
kenjiArai 0:5b88d5760320 578 };
kenjiArai 0:5b88d5760320 579 terminate(client, response);
kenjiArai 0:5b88d5760320 580 }
kenjiArai 0:5b88d5760320 581 }
kenjiArai 0:5b88d5760320 582 }
kenjiArai 0:5b88d5760320 583
kenjiArai 0:5b88d5760320 584 void handle_error(GenericGattClient* client, const AttErrorResponse& error) {
kenjiArai 0:5b88d5760320 585 ble_error_t status = BLE_ERROR_UNSPECIFIED;
kenjiArai 0:5b88d5760320 586
kenjiArai 0:5b88d5760320 587 switch (error.error_code) {
kenjiArai 0:5b88d5760320 588 case AttErrorResponse::INVALID_HANDLE:
kenjiArai 0:5b88d5760320 589 status = BLE_ERROR_INVALID_PARAM;
kenjiArai 0:5b88d5760320 590 break;
kenjiArai 0:5b88d5760320 591 case AttErrorResponse::INSUFFICIENT_AUTHORIZATION:
kenjiArai 0:5b88d5760320 592 status = BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 593 break;
kenjiArai 0:5b88d5760320 594 case AttErrorResponse::INSUFFICIENT_AUTHENTICATION:
kenjiArai 0:5b88d5760320 595 status = BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 596 break;
kenjiArai 0:5b88d5760320 597 case AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE:
kenjiArai 0:5b88d5760320 598 status = BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 599 break;
kenjiArai 0:5b88d5760320 600 case AttErrorResponse::INSUFFICIENT_ENCRYPTION:
kenjiArai 0:5b88d5760320 601 status = BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 602 break;
kenjiArai 0:5b88d5760320 603 case AttErrorResponse::READ_NOT_PERMITTED:
kenjiArai 0:5b88d5760320 604 status = BLE_ERROR_OPERATION_NOT_PERMITTED;
kenjiArai 0:5b88d5760320 605 break;
kenjiArai 0:5b88d5760320 606 case AttErrorResponse::INVALID_OFFSET:
kenjiArai 0:5b88d5760320 607 status = BLE_ERROR_PARAM_OUT_OF_RANGE;
kenjiArai 0:5b88d5760320 608 break;
kenjiArai 0:5b88d5760320 609 case AttErrorResponse::ATTRIBUTE_NOT_LONG:
kenjiArai 0:5b88d5760320 610 status = BLE_ERROR_PARAM_OUT_OF_RANGE;
kenjiArai 0:5b88d5760320 611 break;
kenjiArai 0:5b88d5760320 612 default:
kenjiArai 0:5b88d5760320 613 status = BLE_ERROR_UNSPECIFIED;
kenjiArai 0:5b88d5760320 614 break;
kenjiArai 0:5b88d5760320 615 }
kenjiArai 0:5b88d5760320 616
kenjiArai 0:5b88d5760320 617 GattReadCallbackParams response = {
kenjiArai 0:5b88d5760320 618 connection_handle,
kenjiArai 0:5b88d5760320 619 attribute_handle,
kenjiArai 0:5b88d5760320 620 offset,
kenjiArai 0:5b88d5760320 621 error.error_code,
kenjiArai 0:5b88d5760320 622 /* data */ NULL,
kenjiArai 0:5b88d5760320 623 status
kenjiArai 0:5b88d5760320 624 };
kenjiArai 0:5b88d5760320 625
kenjiArai 0:5b88d5760320 626 terminate(client, response);
kenjiArai 0:5b88d5760320 627 }
kenjiArai 0:5b88d5760320 628
kenjiArai 0:5b88d5760320 629 uint16_t attribute_handle;
kenjiArai 0:5b88d5760320 630 uint16_t offset;
kenjiArai 0:5b88d5760320 631 uint16_t current_offset;
kenjiArai 0:5b88d5760320 632 uint8_t* data;
kenjiArai 0:5b88d5760320 633 };
kenjiArai 0:5b88d5760320 634
kenjiArai 0:5b88d5760320 635 /*
kenjiArai 0:5b88d5760320 636 * Control block for the write process
kenjiArai 0:5b88d5760320 637 */
kenjiArai 0:5b88d5760320 638 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 639 struct GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::WriteControlBlock : public ProcedureControlBlock {
kenjiArai 0:5b88d5760320 640 using ProcedureControlBlock::connection_handle;
kenjiArai 0:5b88d5760320 641
kenjiArai 0:5b88d5760320 642 WriteControlBlock(
kenjiArai 0:5b88d5760320 643 connection_handle_t connection_handle, uint16_t attribute_handle,
kenjiArai 0:5b88d5760320 644 uint8_t* data, uint16_t len
kenjiArai 0:5b88d5760320 645 ) : ProcedureControlBlock(WRITE_PROCEDURE, connection_handle),
kenjiArai 0:5b88d5760320 646 attribute_handle(attribute_handle), len(len), offset(0), data(data),
kenjiArai 0:5b88d5760320 647 prepare_success(false), status(BLE_ERROR_UNSPECIFIED), error_code(0xFF) {
kenjiArai 0:5b88d5760320 648 }
kenjiArai 0:5b88d5760320 649
kenjiArai 0:5b88d5760320 650 virtual ~WriteControlBlock() {
kenjiArai 0:5b88d5760320 651 free(data);
kenjiArai 0:5b88d5760320 652 }
kenjiArai 0:5b88d5760320 653
kenjiArai 0:5b88d5760320 654 virtual void handle_timeout_error(GenericGattClient* client) {
kenjiArai 0:5b88d5760320 655 GattWriteCallbackParams response = {
kenjiArai 0:5b88d5760320 656 connection_handle,
kenjiArai 0:5b88d5760320 657 attribute_handle,
kenjiArai 0:5b88d5760320 658 GattWriteCallbackParams::OP_WRITE_REQ,
kenjiArai 0:5b88d5760320 659 BLE_ERROR_UNSPECIFIED,
kenjiArai 0:5b88d5760320 660 0x00
kenjiArai 0:5b88d5760320 661 };
kenjiArai 0:5b88d5760320 662 terminate(client, response);
kenjiArai 0:5b88d5760320 663 }
kenjiArai 0:5b88d5760320 664
kenjiArai 0:5b88d5760320 665 virtual void abort(GenericGattClient *client) {
kenjiArai 0:5b88d5760320 666 GattWriteCallbackParams response = {
kenjiArai 0:5b88d5760320 667 connection_handle,
kenjiArai 0:5b88d5760320 668 attribute_handle,
kenjiArai 0:5b88d5760320 669 GattWriteCallbackParams::OP_WRITE_REQ,
kenjiArai 0:5b88d5760320 670 BLE_ERROR_INVALID_STATE,
kenjiArai 0:5b88d5760320 671 0x00
kenjiArai 0:5b88d5760320 672 };
kenjiArai 0:5b88d5760320 673 terminate(client, response);
kenjiArai 0:5b88d5760320 674 }
kenjiArai 0:5b88d5760320 675
kenjiArai 0:5b88d5760320 676 void terminate(GenericGattClient* client, const GattWriteCallbackParams& response) {
kenjiArai 0:5b88d5760320 677 client->remove_control_block(this);
kenjiArai 0:5b88d5760320 678 client->processWriteResponse(&response);
kenjiArai 0:5b88d5760320 679 delete this;
kenjiArai 0:5b88d5760320 680 }
kenjiArai 0:5b88d5760320 681
kenjiArai 0:5b88d5760320 682 virtual void handle(GenericGattClient* client, const AttServerMessage& message) {
kenjiArai 0:5b88d5760320 683 switch(message.opcode) {
kenjiArai 0:5b88d5760320 684 case AttributeOpcode::ERROR_RESPONSE:
kenjiArai 0:5b88d5760320 685 handle_error(client, static_cast<const AttErrorResponse&>(message));
kenjiArai 0:5b88d5760320 686 break;
kenjiArai 0:5b88d5760320 687
kenjiArai 0:5b88d5760320 688 case AttributeOpcode::WRITE_RESPONSE:
kenjiArai 0:5b88d5760320 689 handle_write_response(client, static_cast<const AttWriteResponse&>(message));
kenjiArai 0:5b88d5760320 690 break;
kenjiArai 0:5b88d5760320 691
kenjiArai 0:5b88d5760320 692 case AttributeOpcode::PREPARE_WRITE_RESPONSE:
kenjiArai 0:5b88d5760320 693 handle_prepare_write_response(client, static_cast<const AttPrepareWriteResponse&>(message));
kenjiArai 0:5b88d5760320 694 break;
kenjiArai 0:5b88d5760320 695
kenjiArai 0:5b88d5760320 696 case AttributeOpcode::EXECUTE_WRITE_RESPONSE:
kenjiArai 0:5b88d5760320 697 handle_execute_write_response(client, static_cast<const AttExecuteWriteResponse&>(message));
kenjiArai 0:5b88d5760320 698 break;
kenjiArai 0:5b88d5760320 699
kenjiArai 0:5b88d5760320 700 default: {
kenjiArai 0:5b88d5760320 701 GattWriteCallbackParams response = {
kenjiArai 0:5b88d5760320 702 connection_handle,
kenjiArai 0:5b88d5760320 703 attribute_handle,
kenjiArai 0:5b88d5760320 704 GattWriteCallbackParams::OP_WRITE_REQ,
kenjiArai 0:5b88d5760320 705 BLE_ERROR_UNSPECIFIED,
kenjiArai 0:5b88d5760320 706 AttErrorResponse::UNLIKELY_ERROR
kenjiArai 0:5b88d5760320 707 };
kenjiArai 0:5b88d5760320 708
kenjiArai 0:5b88d5760320 709 terminate(client, response);
kenjiArai 0:5b88d5760320 710 } break;
kenjiArai 0:5b88d5760320 711 }
kenjiArai 0:5b88d5760320 712 }
kenjiArai 0:5b88d5760320 713
kenjiArai 0:5b88d5760320 714 void handle_write_response(GenericGattClient* client, const AttWriteResponse& write_response) {
kenjiArai 0:5b88d5760320 715 GattWriteCallbackParams response = {
kenjiArai 0:5b88d5760320 716 connection_handle, attribute_handle,
kenjiArai 0:5b88d5760320 717 GattWriteCallbackParams::OP_WRITE_REQ,
kenjiArai 0:5b88d5760320 718 BLE_ERROR_NONE, 0x00
kenjiArai 0:5b88d5760320 719 };
kenjiArai 0:5b88d5760320 720
kenjiArai 0:5b88d5760320 721 terminate(client, response);
kenjiArai 0:5b88d5760320 722 }
kenjiArai 0:5b88d5760320 723
kenjiArai 0:5b88d5760320 724 void handle_prepare_write_response(GenericGattClient* client, const AttPrepareWriteResponse& write_response) {
kenjiArai 0:5b88d5760320 725 ble_error_t err = BLE_ERROR_UNSPECIFIED;
kenjiArai 0:5b88d5760320 726
kenjiArai 0:5b88d5760320 727 uint16_t mtu_size = client->get_mtu(connection_handle);
kenjiArai 0:5b88d5760320 728 offset = write_response.offset + write_response.partial_value.size();
kenjiArai 0:5b88d5760320 729 if (offset < len) {
kenjiArai 0:5b88d5760320 730 err = client->_pal_client->queue_prepare_write(
kenjiArai 0:5b88d5760320 731 connection_handle, attribute_handle,
kenjiArai 0:5b88d5760320 732 make_const_Span(
kenjiArai 0:5b88d5760320 733 data + offset,
kenjiArai 0:5b88d5760320 734 std::min((len - offset), (mtu_size - 5))
kenjiArai 0:5b88d5760320 735 ),
kenjiArai 0:5b88d5760320 736 offset
kenjiArai 0:5b88d5760320 737 );
kenjiArai 0:5b88d5760320 738 } else {
kenjiArai 0:5b88d5760320 739 err = client->_pal_client->execute_write_queue(
kenjiArai 0:5b88d5760320 740 connection_handle, true
kenjiArai 0:5b88d5760320 741 );
kenjiArai 0:5b88d5760320 742 }
kenjiArai 0:5b88d5760320 743
kenjiArai 0:5b88d5760320 744 if (err) {
kenjiArai 0:5b88d5760320 745 clear_prepare_queue(client, err, AttErrorResponse::UNLIKELY_ERROR);
kenjiArai 0:5b88d5760320 746 }
kenjiArai 0:5b88d5760320 747 }
kenjiArai 0:5b88d5760320 748
kenjiArai 0:5b88d5760320 749 void handle_execute_write_response(GenericGattClient* client, const AttExecuteWriteResponse& execute_response) {
kenjiArai 0:5b88d5760320 750 if (prepare_success) {
kenjiArai 0:5b88d5760320 751 status = BLE_ERROR_NONE;
kenjiArai 0:5b88d5760320 752 error_code = 0x00;
kenjiArai 0:5b88d5760320 753 }
kenjiArai 0:5b88d5760320 754
kenjiArai 0:5b88d5760320 755 GattWriteCallbackParams response = {
kenjiArai 0:5b88d5760320 756 connection_handle,
kenjiArai 0:5b88d5760320 757 attribute_handle,
kenjiArai 0:5b88d5760320 758 GattWriteCallbackParams::OP_WRITE_REQ,
kenjiArai 0:5b88d5760320 759 status,
kenjiArai 0:5b88d5760320 760 error_code
kenjiArai 0:5b88d5760320 761 };
kenjiArai 0:5b88d5760320 762
kenjiArai 0:5b88d5760320 763 terminate(client, response);
kenjiArai 0:5b88d5760320 764 }
kenjiArai 0:5b88d5760320 765
kenjiArai 0:5b88d5760320 766 void clear_prepare_queue(GenericGattClient* client, ble_error_t s, uint8_t e) {
kenjiArai 0:5b88d5760320 767 prepare_success = false;
kenjiArai 0:5b88d5760320 768 status = s;
kenjiArai 0:5b88d5760320 769 error_code = e;
kenjiArai 0:5b88d5760320 770 ble_error_t err = client->_pal_client->execute_write_queue(
kenjiArai 0:5b88d5760320 771 connection_handle, false
kenjiArai 0:5b88d5760320 772 );
kenjiArai 0:5b88d5760320 773
kenjiArai 0:5b88d5760320 774 if (err) {
kenjiArai 0:5b88d5760320 775 GattWriteCallbackParams response = {
kenjiArai 0:5b88d5760320 776 connection_handle,
kenjiArai 0:5b88d5760320 777 attribute_handle,
kenjiArai 0:5b88d5760320 778 GattWriteCallbackParams::OP_WRITE_REQ,
kenjiArai 0:5b88d5760320 779 err,
kenjiArai 0:5b88d5760320 780 AttErrorResponse::UNLIKELY_ERROR
kenjiArai 0:5b88d5760320 781 };
kenjiArai 0:5b88d5760320 782
kenjiArai 0:5b88d5760320 783 terminate(client, response);
kenjiArai 0:5b88d5760320 784 }
kenjiArai 0:5b88d5760320 785 }
kenjiArai 0:5b88d5760320 786
kenjiArai 0:5b88d5760320 787 void handle_error(GenericGattClient* client, const AttErrorResponse& error) {
kenjiArai 0:5b88d5760320 788 ble_error_t status = BLE_ERROR_UNSPECIFIED;
kenjiArai 0:5b88d5760320 789
kenjiArai 0:5b88d5760320 790 switch (error.error_code) {
kenjiArai 0:5b88d5760320 791 case AttErrorResponse::INVALID_HANDLE:
kenjiArai 0:5b88d5760320 792 status = BLE_ERROR_INVALID_PARAM;
kenjiArai 0:5b88d5760320 793 break;
kenjiArai 0:5b88d5760320 794 case AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH:
kenjiArai 0:5b88d5760320 795 status = BLE_ERROR_INVALID_PARAM;
kenjiArai 0:5b88d5760320 796 break;
kenjiArai 0:5b88d5760320 797 case AttErrorResponse::INSUFFICIENT_AUTHORIZATION:
kenjiArai 0:5b88d5760320 798 status = BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 799 break;
kenjiArai 0:5b88d5760320 800 case AttErrorResponse::INSUFFICIENT_AUTHENTICATION:
kenjiArai 0:5b88d5760320 801 status = BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 802 break;
kenjiArai 0:5b88d5760320 803 case AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE:
kenjiArai 0:5b88d5760320 804 status = BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 805 break;
kenjiArai 0:5b88d5760320 806 case AttErrorResponse::INSUFFICIENT_ENCRYPTION:
kenjiArai 0:5b88d5760320 807 status = BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 808 break;
kenjiArai 0:5b88d5760320 809 case AttErrorResponse::WRITE_NOT_PERMITTED:
kenjiArai 0:5b88d5760320 810 status = BLE_ERROR_OPERATION_NOT_PERMITTED;
kenjiArai 0:5b88d5760320 811 break;
kenjiArai 0:5b88d5760320 812 default:
kenjiArai 0:5b88d5760320 813 status = BLE_ERROR_UNSPECIFIED;
kenjiArai 0:5b88d5760320 814 break;
kenjiArai 0:5b88d5760320 815 }
kenjiArai 0:5b88d5760320 816
kenjiArai 0:5b88d5760320 817 if (error.request_opcode == AttributeOpcode(AttributeOpcode::PREPARE_WRITE_REQUEST)) {
kenjiArai 0:5b88d5760320 818 clear_prepare_queue(client, status, error.error_code);
kenjiArai 0:5b88d5760320 819 } else {
kenjiArai 0:5b88d5760320 820 GattWriteCallbackParams response = {
kenjiArai 0:5b88d5760320 821 connection_handle,
kenjiArai 0:5b88d5760320 822 attribute_handle,
kenjiArai 0:5b88d5760320 823 GattWriteCallbackParams::OP_WRITE_REQ,
kenjiArai 0:5b88d5760320 824 status,
kenjiArai 0:5b88d5760320 825 error.error_code
kenjiArai 0:5b88d5760320 826 };
kenjiArai 0:5b88d5760320 827
kenjiArai 0:5b88d5760320 828 terminate(client, response);
kenjiArai 0:5b88d5760320 829 }
kenjiArai 0:5b88d5760320 830 }
kenjiArai 0:5b88d5760320 831
kenjiArai 0:5b88d5760320 832 uint16_t attribute_handle;
kenjiArai 0:5b88d5760320 833 uint16_t len;
kenjiArai 0:5b88d5760320 834 uint16_t offset;
kenjiArai 0:5b88d5760320 835 uint8_t* data;
kenjiArai 0:5b88d5760320 836 bool prepare_success;
kenjiArai 0:5b88d5760320 837 ble_error_t status;
kenjiArai 0:5b88d5760320 838 uint8_t error_code;
kenjiArai 0:5b88d5760320 839 };
kenjiArai 0:5b88d5760320 840
kenjiArai 0:5b88d5760320 841 /*
kenjiArai 0:5b88d5760320 842 * Control block for the descriptor discovery process
kenjiArai 0:5b88d5760320 843 */
kenjiArai 0:5b88d5760320 844 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 845 struct GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::DescriptorDiscoveryControlBlock : public ProcedureControlBlock {
kenjiArai 0:5b88d5760320 846 using ProcedureControlBlock::connection_handle;
kenjiArai 0:5b88d5760320 847
kenjiArai 0:5b88d5760320 848 DescriptorDiscoveryControlBlock(
kenjiArai 0:5b88d5760320 849 const DiscoveredCharacteristic& characteristic,
kenjiArai 0:5b88d5760320 850 const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
kenjiArai 0:5b88d5760320 851 const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
kenjiArai 0:5b88d5760320 852 ) : ProcedureControlBlock(DESCRIPTOR_DISCOVERY_PROCEDURE, characteristic.getConnectionHandle()),
kenjiArai 0:5b88d5760320 853 characteristic(characteristic),
kenjiArai 0:5b88d5760320 854 discovery_cb(discoveryCallback),
kenjiArai 0:5b88d5760320 855 termination_cb(terminationCallback),
kenjiArai 0:5b88d5760320 856 next_handle(characteristic.getValueHandle() + 1),
kenjiArai 0:5b88d5760320 857 done(false) {
kenjiArai 0:5b88d5760320 858 }
kenjiArai 0:5b88d5760320 859
kenjiArai 0:5b88d5760320 860 virtual ~DescriptorDiscoveryControlBlock() { }
kenjiArai 0:5b88d5760320 861
kenjiArai 0:5b88d5760320 862 ble_error_t start(GenericGattClient* client) {
kenjiArai 0:5b88d5760320 863 return client->_pal_client->discover_characteristics_descriptors(
kenjiArai 0:5b88d5760320 864 connection_handle,
kenjiArai 0:5b88d5760320 865 attribute_handle_range(
kenjiArai 0:5b88d5760320 866 next_handle,
kenjiArai 0:5b88d5760320 867 characteristic.getLastHandle()
kenjiArai 0:5b88d5760320 868 )
kenjiArai 0:5b88d5760320 869 );
kenjiArai 0:5b88d5760320 870 }
kenjiArai 0:5b88d5760320 871
kenjiArai 0:5b88d5760320 872 virtual void handle_timeout_error(GenericGattClient* client) {
kenjiArai 0:5b88d5760320 873 terminate(client, BLE_ERROR_UNSPECIFIED);
kenjiArai 0:5b88d5760320 874 }
kenjiArai 0:5b88d5760320 875
kenjiArai 0:5b88d5760320 876 virtual void abort(GenericGattClient *client) {
kenjiArai 0:5b88d5760320 877 terminate(client, BLE_ERROR_INVALID_STATE);
kenjiArai 0:5b88d5760320 878 }
kenjiArai 0:5b88d5760320 879
kenjiArai 0:5b88d5760320 880 virtual void handle(GenericGattClient* client, const AttServerMessage& message) {
kenjiArai 0:5b88d5760320 881 if (done) {
kenjiArai 0:5b88d5760320 882 terminate(client, BLE_ERROR_NONE);
kenjiArai 0:5b88d5760320 883 return;
kenjiArai 0:5b88d5760320 884 }
kenjiArai 0:5b88d5760320 885
kenjiArai 0:5b88d5760320 886 switch(message.opcode) {
kenjiArai 0:5b88d5760320 887 case AttributeOpcode::ERROR_RESPONSE:
kenjiArai 0:5b88d5760320 888 handle_error(client, static_cast<const AttErrorResponse&>(message));
kenjiArai 0:5b88d5760320 889 return;
kenjiArai 0:5b88d5760320 890
kenjiArai 0:5b88d5760320 891 case AttributeOpcode::FIND_INFORMATION_RESPONSE:
kenjiArai 0:5b88d5760320 892 handle_response(client, static_cast<const AttFindInformationResponse&>(message));
kenjiArai 0:5b88d5760320 893 return;
kenjiArai 0:5b88d5760320 894
kenjiArai 0:5b88d5760320 895 default:
kenjiArai 0:5b88d5760320 896 break;
kenjiArai 0:5b88d5760320 897 }
kenjiArai 0:5b88d5760320 898 }
kenjiArai 0:5b88d5760320 899
kenjiArai 0:5b88d5760320 900 void handle_error(GenericGattClient* client, const AttErrorResponse& error) {
kenjiArai 0:5b88d5760320 901 if (error.error_code == AttErrorResponse::ATTRIBUTE_NOT_FOUND) {
kenjiArai 0:5b88d5760320 902 terminate(client, BLE_ERROR_NONE);
kenjiArai 0:5b88d5760320 903 } else {
kenjiArai 0:5b88d5760320 904 terminate(client, BLE_ERROR_UNSPECIFIED, error.error_code);
kenjiArai 0:5b88d5760320 905 }
kenjiArai 0:5b88d5760320 906 }
kenjiArai 0:5b88d5760320 907
kenjiArai 0:5b88d5760320 908 void handle_response(GenericGattClient* client, const AttFindInformationResponse& response) {
kenjiArai 0:5b88d5760320 909 for (size_t i = 0; i < response.size(); ++i) {
kenjiArai 0:5b88d5760320 910 DiscoveredCharacteristicDescriptor descriptor(
kenjiArai 0:5b88d5760320 911 client, connection_handle, response[i].handle, response[i].uuid
kenjiArai 0:5b88d5760320 912 );
kenjiArai 0:5b88d5760320 913 CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = {
kenjiArai 0:5b88d5760320 914 characteristic,
kenjiArai 0:5b88d5760320 915 descriptor
kenjiArai 0:5b88d5760320 916 };
kenjiArai 0:5b88d5760320 917 discovery_cb(&params);
kenjiArai 0:5b88d5760320 918 if (done) {
kenjiArai 0:5b88d5760320 919 terminate(client, BLE_ERROR_NONE);
kenjiArai 0:5b88d5760320 920 return;
kenjiArai 0:5b88d5760320 921 }
kenjiArai 0:5b88d5760320 922
kenjiArai 0:5b88d5760320 923 if (response[i].handle == characteristic.getLastHandle()) {
kenjiArai 0:5b88d5760320 924 terminate(client, BLE_ERROR_NONE);
kenjiArai 0:5b88d5760320 925 return;
kenjiArai 0:5b88d5760320 926 }
kenjiArai 0:5b88d5760320 927 next_handle = response[i].handle + 1;
kenjiArai 0:5b88d5760320 928 }
kenjiArai 0:5b88d5760320 929
kenjiArai 0:5b88d5760320 930 ble_error_t err = start(client);
kenjiArai 0:5b88d5760320 931 if (err) {
kenjiArai 0:5b88d5760320 932 terminate(client, err, AttErrorResponse::UNLIKELY_ERROR);
kenjiArai 0:5b88d5760320 933 }
kenjiArai 0:5b88d5760320 934 }
kenjiArai 0:5b88d5760320 935
kenjiArai 0:5b88d5760320 936 void terminate(GenericGattClient* client, ble_error_t status, uint8_t error_code = 0x00) {
kenjiArai 0:5b88d5760320 937 client->remove_control_block(this);
kenjiArai 0:5b88d5760320 938 CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
kenjiArai 0:5b88d5760320 939 characteristic,
kenjiArai 0:5b88d5760320 940 status,
kenjiArai 0:5b88d5760320 941 error_code
kenjiArai 0:5b88d5760320 942 };
kenjiArai 0:5b88d5760320 943 termination_cb(&params);
kenjiArai 0:5b88d5760320 944 delete this;
kenjiArai 0:5b88d5760320 945 }
kenjiArai 0:5b88d5760320 946
kenjiArai 0:5b88d5760320 947 DiscoveredCharacteristic characteristic;
kenjiArai 0:5b88d5760320 948 CharacteristicDescriptorDiscovery::DiscoveryCallback_t discovery_cb;
kenjiArai 0:5b88d5760320 949 CharacteristicDescriptorDiscovery::TerminationCallback_t termination_cb;
kenjiArai 0:5b88d5760320 950 uint16_t next_handle;
kenjiArai 0:5b88d5760320 951 bool done;
kenjiArai 0:5b88d5760320 952 };
kenjiArai 0:5b88d5760320 953
kenjiArai 0:5b88d5760320 954 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 955 GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::GenericGattClient(PalGattClient* pal_client) :
kenjiArai 0:5b88d5760320 956 _pal_client(pal_client),
kenjiArai 0:5b88d5760320 957 _termination_callback(),
kenjiArai 0:5b88d5760320 958 #if BLE_FEATURE_SIGNING
kenjiArai 0:5b88d5760320 959 _signing_event_handler(NULL),
kenjiArai 0:5b88d5760320 960 #endif
kenjiArai 0:5b88d5760320 961 control_blocks(NULL),
kenjiArai 0:5b88d5760320 962 _is_reseting(false) {
kenjiArai 0:5b88d5760320 963 _pal_client->when_server_message_received(
kenjiArai 0:5b88d5760320 964 mbed::callback(this, &GenericGattClient::on_server_message_received)
kenjiArai 0:5b88d5760320 965 );
kenjiArai 0:5b88d5760320 966 _pal_client->when_transaction_timeout(
kenjiArai 0:5b88d5760320 967 mbed::callback(this, &GenericGattClient::on_transaction_timeout)
kenjiArai 0:5b88d5760320 968 );
kenjiArai 0:5b88d5760320 969 _pal_client->set_event_handler(this);
kenjiArai 0:5b88d5760320 970 }
kenjiArai 0:5b88d5760320 971
kenjiArai 0:5b88d5760320 972 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 973 ble_error_t GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::launchServiceDiscovery_(
kenjiArai 0:5b88d5760320 974 connection_handle_t connection_handle,
kenjiArai 0:5b88d5760320 975 ServiceDiscovery::ServiceCallback_t service_callback,
kenjiArai 0:5b88d5760320 976 ServiceDiscovery::CharacteristicCallback_t characteristic_callback,
kenjiArai 0:5b88d5760320 977 const UUID& matching_service_uuid,
kenjiArai 0:5b88d5760320 978 const UUID& matching_characteristic_uuid
kenjiArai 0:5b88d5760320 979 ) {
kenjiArai 0:5b88d5760320 980 // verify that there is no other procedures going on this connection
kenjiArai 0:5b88d5760320 981 if (_is_reseting || get_control_block(connection_handle)) {
kenjiArai 0:5b88d5760320 982 return BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 983 }
kenjiArai 0:5b88d5760320 984
kenjiArai 0:5b88d5760320 985 // terminate and return if there is no callback to call
kenjiArai 0:5b88d5760320 986 if (!service_callback && !characteristic_callback) {
kenjiArai 0:5b88d5760320 987 on_termination(connection_handle);
kenjiArai 0:5b88d5760320 988 return BLE_ERROR_NONE;
kenjiArai 0:5b88d5760320 989 }
kenjiArai 0:5b88d5760320 990
kenjiArai 0:5b88d5760320 991 DiscoveryControlBlock* discovery_pcb = new(std::nothrow) DiscoveryControlBlock(
kenjiArai 0:5b88d5760320 992 connection_handle,
kenjiArai 0:5b88d5760320 993 service_callback,
kenjiArai 0:5b88d5760320 994 characteristic_callback,
kenjiArai 0:5b88d5760320 995 matching_service_uuid,
kenjiArai 0:5b88d5760320 996 matching_characteristic_uuid
kenjiArai 0:5b88d5760320 997 );
kenjiArai 0:5b88d5760320 998
kenjiArai 0:5b88d5760320 999 if (discovery_pcb == NULL) {
kenjiArai 0:5b88d5760320 1000 return BLE_ERROR_NO_MEM;
kenjiArai 0:5b88d5760320 1001 }
kenjiArai 0:5b88d5760320 1002
kenjiArai 0:5b88d5760320 1003 // note: control block inserted prior the request because they are part of
kenjiArai 0:5b88d5760320 1004 // of the transaction and the callback can be call synchronously
kenjiArai 0:5b88d5760320 1005 insert_control_block(discovery_pcb);
kenjiArai 0:5b88d5760320 1006
kenjiArai 0:5b88d5760320 1007 // launch the request
kenjiArai 0:5b88d5760320 1008 ble_error_t err = BLE_ERROR_UNSPECIFIED;
kenjiArai 0:5b88d5760320 1009 if (matching_service_uuid == UUID()) {
kenjiArai 0:5b88d5760320 1010 err = _pal_client->discover_primary_service(
kenjiArai 0:5b88d5760320 1011 connection_handle,
kenjiArai 0:5b88d5760320 1012 0x0001
kenjiArai 0:5b88d5760320 1013 );
kenjiArai 0:5b88d5760320 1014 } else {
kenjiArai 0:5b88d5760320 1015 err = _pal_client->discover_primary_service_by_service_uuid(
kenjiArai 0:5b88d5760320 1016 connection_handle,
kenjiArai 0:5b88d5760320 1017 0x0001,
kenjiArai 0:5b88d5760320 1018 matching_service_uuid
kenjiArai 0:5b88d5760320 1019 );
kenjiArai 0:5b88d5760320 1020 }
kenjiArai 0:5b88d5760320 1021
kenjiArai 0:5b88d5760320 1022 if (err) {
kenjiArai 0:5b88d5760320 1023 remove_control_block(discovery_pcb);
kenjiArai 0:5b88d5760320 1024 delete discovery_pcb;
kenjiArai 0:5b88d5760320 1025 }
kenjiArai 0:5b88d5760320 1026
kenjiArai 0:5b88d5760320 1027 return err;
kenjiArai 0:5b88d5760320 1028 }
kenjiArai 0:5b88d5760320 1029
kenjiArai 0:5b88d5760320 1030 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1031 bool GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::isServiceDiscoveryActive_() const {
kenjiArai 0:5b88d5760320 1032 ProcedureControlBlock* pcb = control_blocks;
kenjiArai 0:5b88d5760320 1033
kenjiArai 0:5b88d5760320 1034 while (pcb) {
kenjiArai 0:5b88d5760320 1035 if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) {
kenjiArai 0:5b88d5760320 1036 return true;
kenjiArai 0:5b88d5760320 1037 }
kenjiArai 0:5b88d5760320 1038 pcb = pcb->next;
kenjiArai 0:5b88d5760320 1039 }
kenjiArai 0:5b88d5760320 1040
kenjiArai 0:5b88d5760320 1041 return false;
kenjiArai 0:5b88d5760320 1042 }
kenjiArai 0:5b88d5760320 1043
kenjiArai 0:5b88d5760320 1044 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1045 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::terminateServiceDiscovery_()
kenjiArai 0:5b88d5760320 1046 {
kenjiArai 0:5b88d5760320 1047 ProcedureControlBlock* pcb = control_blocks;
kenjiArai 0:5b88d5760320 1048 while (pcb) {
kenjiArai 0:5b88d5760320 1049 if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) {
kenjiArai 0:5b88d5760320 1050 static_cast<DiscoveryControlBlock*>(pcb)->done = true;
kenjiArai 0:5b88d5760320 1051 }
kenjiArai 0:5b88d5760320 1052 pcb = pcb->next;
kenjiArai 0:5b88d5760320 1053 }
kenjiArai 0:5b88d5760320 1054 }
kenjiArai 0:5b88d5760320 1055
kenjiArai 0:5b88d5760320 1056 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1057 ble_error_t GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::read_(
kenjiArai 0:5b88d5760320 1058 connection_handle_t connection_handle,
kenjiArai 0:5b88d5760320 1059 GattAttribute::Handle_t attribute_handle,
kenjiArai 0:5b88d5760320 1060 uint16_t offset) const
kenjiArai 0:5b88d5760320 1061 {
kenjiArai 0:5b88d5760320 1062 // verify that there is no other procedures going on this connection
kenjiArai 0:5b88d5760320 1063 if (_is_reseting || get_control_block(connection_handle)) {
kenjiArai 0:5b88d5760320 1064 return BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 1065 }
kenjiArai 0:5b88d5760320 1066
kenjiArai 0:5b88d5760320 1067 ReadControlBlock* read_pcb = new(std::nothrow) ReadControlBlock(
kenjiArai 0:5b88d5760320 1068 connection_handle,
kenjiArai 0:5b88d5760320 1069 attribute_handle,
kenjiArai 0:5b88d5760320 1070 offset
kenjiArai 0:5b88d5760320 1071 );
kenjiArai 0:5b88d5760320 1072
kenjiArai 0:5b88d5760320 1073 if (read_pcb == NULL) {
kenjiArai 0:5b88d5760320 1074 return BLE_ERROR_NO_MEM;
kenjiArai 0:5b88d5760320 1075 }
kenjiArai 0:5b88d5760320 1076
kenjiArai 0:5b88d5760320 1077 insert_control_block(read_pcb);
kenjiArai 0:5b88d5760320 1078
kenjiArai 0:5b88d5760320 1079 ble_error_t err = BLE_ERROR_NONE;
kenjiArai 0:5b88d5760320 1080
kenjiArai 0:5b88d5760320 1081 if (offset == 0) {
kenjiArai 0:5b88d5760320 1082 err = _pal_client->read_attribute_value(
kenjiArai 0:5b88d5760320 1083 connection_handle, attribute_handle
kenjiArai 0:5b88d5760320 1084 );
kenjiArai 0:5b88d5760320 1085 } else {
kenjiArai 0:5b88d5760320 1086 err = _pal_client->read_attribute_blob(
kenjiArai 0:5b88d5760320 1087 connection_handle, attribute_handle, offset
kenjiArai 0:5b88d5760320 1088 );
kenjiArai 0:5b88d5760320 1089 }
kenjiArai 0:5b88d5760320 1090
kenjiArai 0:5b88d5760320 1091 if (err) {
kenjiArai 0:5b88d5760320 1092 remove_control_block(read_pcb);
kenjiArai 0:5b88d5760320 1093 delete read_pcb;
kenjiArai 0:5b88d5760320 1094 }
kenjiArai 0:5b88d5760320 1095
kenjiArai 0:5b88d5760320 1096 return err;
kenjiArai 0:5b88d5760320 1097 }
kenjiArai 0:5b88d5760320 1098
kenjiArai 0:5b88d5760320 1099 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1100 ble_error_t GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::write_(
kenjiArai 0:5b88d5760320 1101 WriteOp_t cmd,
kenjiArai 0:5b88d5760320 1102 connection_handle_t connection_handle,
kenjiArai 0:5b88d5760320 1103 GattAttribute::Handle_t attribute_handle,
kenjiArai 0:5b88d5760320 1104 size_t length,
kenjiArai 0:5b88d5760320 1105 const uint8_t* value
kenjiArai 0:5b88d5760320 1106 ) const {
kenjiArai 0:5b88d5760320 1107 // verify that there is no other procedures going on this connection
kenjiArai 0:5b88d5760320 1108 if (_is_reseting || get_control_block(connection_handle)) {
kenjiArai 0:5b88d5760320 1109 return BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 1110 }
kenjiArai 0:5b88d5760320 1111
kenjiArai 0:5b88d5760320 1112 uint16_t mtu = get_mtu(connection_handle);
kenjiArai 0:5b88d5760320 1113
kenjiArai 0:5b88d5760320 1114 #if BLE_FEATURE_SIGNING
kenjiArai 0:5b88d5760320 1115 /* if link is encrypted signed writes should be normal writes */
kenjiArai 0:5b88d5760320 1116 if (cmd == Base::GATT_OP_SIGNED_WRITE_CMD) {
kenjiArai 0:5b88d5760320 1117 ble::link_encryption_t encryption(ble::link_encryption_t::NOT_ENCRYPTED);
kenjiArai 0:5b88d5760320 1118 // FIXME: use security manager or a template if applicable
kenjiArai 0:5b88d5760320 1119 SecurityManager &sm = createBLEInstance()->getSecurityManager();
kenjiArai 0:5b88d5760320 1120 ble_error_t status = sm.getLinkEncryption(connection_handle, &encryption);
kenjiArai 0:5b88d5760320 1121 if (status == BLE_ERROR_NONE &&
kenjiArai 0:5b88d5760320 1122 (encryption == link_encryption_t::ENCRYPTED ||
kenjiArai 0:5b88d5760320 1123 encryption == link_encryption_t::ENCRYPTED_WITH_MITM ||
kenjiArai 0:5b88d5760320 1124 encryption == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM)
kenjiArai 0:5b88d5760320 1125 ) {
kenjiArai 0:5b88d5760320 1126 cmd = Base::GATT_OP_WRITE_CMD;
kenjiArai 0:5b88d5760320 1127 }
kenjiArai 0:5b88d5760320 1128 }
kenjiArai 0:5b88d5760320 1129 #endif // BLE_FEATURE_SIGNING
kenjiArai 0:5b88d5760320 1130
kenjiArai 0:5b88d5760320 1131 if (cmd == Base::GATT_OP_WRITE_CMD) {
kenjiArai 0:5b88d5760320 1132 if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) {
kenjiArai 0:5b88d5760320 1133 return BLE_ERROR_PARAM_OUT_OF_RANGE;
kenjiArai 0:5b88d5760320 1134 }
kenjiArai 0:5b88d5760320 1135 return _pal_client->write_without_response(
kenjiArai 0:5b88d5760320 1136 connection_handle,
kenjiArai 0:5b88d5760320 1137 attribute_handle,
kenjiArai 0:5b88d5760320 1138 make_const_Span(value, length)
kenjiArai 0:5b88d5760320 1139 );
kenjiArai 0:5b88d5760320 1140 #if BLE_FEATURE_SIGNING
kenjiArai 0:5b88d5760320 1141 } else if (cmd == Base::GATT_OP_SIGNED_WRITE_CMD) {
kenjiArai 0:5b88d5760320 1142 if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) {
kenjiArai 0:5b88d5760320 1143 return BLE_ERROR_PARAM_OUT_OF_RANGE;
kenjiArai 0:5b88d5760320 1144 }
kenjiArai 0:5b88d5760320 1145 ble_error_t status = _pal_client->signed_write_without_response(
kenjiArai 0:5b88d5760320 1146 connection_handle,
kenjiArai 0:5b88d5760320 1147 attribute_handle,
kenjiArai 0:5b88d5760320 1148 make_const_Span(value, length)
kenjiArai 0:5b88d5760320 1149 );
kenjiArai 0:5b88d5760320 1150
kenjiArai 0:5b88d5760320 1151 if (_signing_event_handler && (status == BLE_ERROR_NONE)) {
kenjiArai 0:5b88d5760320 1152 _signing_event_handler->on_signed_write();
kenjiArai 0:5b88d5760320 1153 }
kenjiArai 0:5b88d5760320 1154 return status;
kenjiArai 0:5b88d5760320 1155 #endif // BLE_FEATURE_SIGNING
kenjiArai 0:5b88d5760320 1156 } else if (cmd == GattClient::GATT_OP_WRITE_REQ) {
kenjiArai 0:5b88d5760320 1157 uint8_t* data = NULL;
kenjiArai 0:5b88d5760320 1158
kenjiArai 0:5b88d5760320 1159 if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) {
kenjiArai 0:5b88d5760320 1160 data = (uint8_t*) malloc(length);
kenjiArai 0:5b88d5760320 1161 if (data == NULL) {
kenjiArai 0:5b88d5760320 1162 return BLE_ERROR_NO_MEM;
kenjiArai 0:5b88d5760320 1163 }
kenjiArai 0:5b88d5760320 1164 memcpy(data, value, length);
kenjiArai 0:5b88d5760320 1165 }
kenjiArai 0:5b88d5760320 1166
kenjiArai 0:5b88d5760320 1167 WriteControlBlock* write_pcb = new (std::nothrow) WriteControlBlock(
kenjiArai 0:5b88d5760320 1168 connection_handle,
kenjiArai 0:5b88d5760320 1169 attribute_handle,
kenjiArai 0:5b88d5760320 1170 data,
kenjiArai 0:5b88d5760320 1171 length
kenjiArai 0:5b88d5760320 1172 );
kenjiArai 0:5b88d5760320 1173
kenjiArai 0:5b88d5760320 1174 if (write_pcb == NULL) {
kenjiArai 0:5b88d5760320 1175 free(data);
kenjiArai 0:5b88d5760320 1176 return BLE_ERROR_NO_MEM;
kenjiArai 0:5b88d5760320 1177 }
kenjiArai 0:5b88d5760320 1178
kenjiArai 0:5b88d5760320 1179 insert_control_block(write_pcb);
kenjiArai 0:5b88d5760320 1180
kenjiArai 0:5b88d5760320 1181 ble_error_t err = BLE_ERROR_UNSPECIFIED;
kenjiArai 0:5b88d5760320 1182 if (data) {
kenjiArai 0:5b88d5760320 1183 err = _pal_client->queue_prepare_write(
kenjiArai 0:5b88d5760320 1184 connection_handle,
kenjiArai 0:5b88d5760320 1185 attribute_handle,
kenjiArai 0:5b88d5760320 1186 make_const_Span(value, mtu - PREPARE_WRITE_HEADER_LENGTH),
kenjiArai 0:5b88d5760320 1187 /* offset */0
kenjiArai 0:5b88d5760320 1188 );
kenjiArai 0:5b88d5760320 1189 } else {
kenjiArai 0:5b88d5760320 1190 err = _pal_client->write_attribute(
kenjiArai 0:5b88d5760320 1191 connection_handle,
kenjiArai 0:5b88d5760320 1192 attribute_handle,
kenjiArai 0:5b88d5760320 1193 make_const_Span(value, length)
kenjiArai 0:5b88d5760320 1194 );
kenjiArai 0:5b88d5760320 1195 }
kenjiArai 0:5b88d5760320 1196
kenjiArai 0:5b88d5760320 1197 if (err) {
kenjiArai 0:5b88d5760320 1198 remove_control_block(write_pcb);
kenjiArai 0:5b88d5760320 1199 delete write_pcb;
kenjiArai 0:5b88d5760320 1200 }
kenjiArai 0:5b88d5760320 1201
kenjiArai 0:5b88d5760320 1202 return err;
kenjiArai 0:5b88d5760320 1203 }
kenjiArai 0:5b88d5760320 1204
kenjiArai 0:5b88d5760320 1205 return BLE_ERROR_NOT_IMPLEMENTED;
kenjiArai 0:5b88d5760320 1206 }
kenjiArai 0:5b88d5760320 1207
kenjiArai 0:5b88d5760320 1208 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1209 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::onServiceDiscoveryTermination_(
kenjiArai 0:5b88d5760320 1210 ServiceDiscovery::TerminationCallback_t callback
kenjiArai 0:5b88d5760320 1211 ) {
kenjiArai 0:5b88d5760320 1212 _termination_callback = callback;
kenjiArai 0:5b88d5760320 1213 }
kenjiArai 0:5b88d5760320 1214
kenjiArai 0:5b88d5760320 1215 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1216 ble_error_t GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::discoverCharacteristicDescriptors_(
kenjiArai 0:5b88d5760320 1217 const DiscoveredCharacteristic& characteristic,
kenjiArai 0:5b88d5760320 1218 const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
kenjiArai 0:5b88d5760320 1219 const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
kenjiArai 0:5b88d5760320 1220 ) {
kenjiArai 0:5b88d5760320 1221 // verify that there is no other procedures going on this connection
kenjiArai 0:5b88d5760320 1222 if (_is_reseting || get_control_block(characteristic.getConnectionHandle())) {
kenjiArai 0:5b88d5760320 1223 return BLE_ERROR_INVALID_STATE;
kenjiArai 0:5b88d5760320 1224 }
kenjiArai 0:5b88d5760320 1225
kenjiArai 0:5b88d5760320 1226 if (characteristic.getValueHandle() == characteristic.getLastHandle()) {
kenjiArai 0:5b88d5760320 1227 CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
kenjiArai 0:5b88d5760320 1228 characteristic,
kenjiArai 0:5b88d5760320 1229 BLE_ERROR_NONE,
kenjiArai 0:5b88d5760320 1230 /* error code */ 0x00
kenjiArai 0:5b88d5760320 1231 };
kenjiArai 0:5b88d5760320 1232
kenjiArai 0:5b88d5760320 1233 terminationCallback(&params);
kenjiArai 0:5b88d5760320 1234 return BLE_ERROR_NONE;
kenjiArai 0:5b88d5760320 1235 }
kenjiArai 0:5b88d5760320 1236
kenjiArai 0:5b88d5760320 1237 DescriptorDiscoveryControlBlock* discovery_pcb =
kenjiArai 0:5b88d5760320 1238 new(std::nothrow) DescriptorDiscoveryControlBlock(
kenjiArai 0:5b88d5760320 1239 characteristic,
kenjiArai 0:5b88d5760320 1240 discoveryCallback,
kenjiArai 0:5b88d5760320 1241 terminationCallback
kenjiArai 0:5b88d5760320 1242 );
kenjiArai 0:5b88d5760320 1243
kenjiArai 0:5b88d5760320 1244 if (discovery_pcb == NULL) {
kenjiArai 0:5b88d5760320 1245 return BLE_ERROR_NO_MEM;
kenjiArai 0:5b88d5760320 1246 }
kenjiArai 0:5b88d5760320 1247
kenjiArai 0:5b88d5760320 1248 insert_control_block(discovery_pcb);
kenjiArai 0:5b88d5760320 1249
kenjiArai 0:5b88d5760320 1250 ble_error_t err = discovery_pcb->start(this);
kenjiArai 0:5b88d5760320 1251
kenjiArai 0:5b88d5760320 1252 if (err) {
kenjiArai 0:5b88d5760320 1253 remove_control_block(discovery_pcb);
kenjiArai 0:5b88d5760320 1254 delete discovery_pcb;
kenjiArai 0:5b88d5760320 1255 }
kenjiArai 0:5b88d5760320 1256
kenjiArai 0:5b88d5760320 1257 return err;
kenjiArai 0:5b88d5760320 1258 }
kenjiArai 0:5b88d5760320 1259
kenjiArai 0:5b88d5760320 1260 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1261 bool GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::isCharacteristicDescriptorDiscoveryActive_(
kenjiArai 0:5b88d5760320 1262 const DiscoveredCharacteristic& characteristic
kenjiArai 0:5b88d5760320 1263 ) const {
kenjiArai 0:5b88d5760320 1264 ProcedureControlBlock* pcb = control_blocks;
kenjiArai 0:5b88d5760320 1265
kenjiArai 0:5b88d5760320 1266 while (pcb) {
kenjiArai 0:5b88d5760320 1267 if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE &&
kenjiArai 0:5b88d5760320 1268 static_cast<DescriptorDiscoveryControlBlock*>(pcb)->characteristic == characteristic) {
kenjiArai 0:5b88d5760320 1269 return true;
kenjiArai 0:5b88d5760320 1270 }
kenjiArai 0:5b88d5760320 1271 pcb = pcb->next;
kenjiArai 0:5b88d5760320 1272 }
kenjiArai 0:5b88d5760320 1273
kenjiArai 0:5b88d5760320 1274 return false;
kenjiArai 0:5b88d5760320 1275 }
kenjiArai 0:5b88d5760320 1276
kenjiArai 0:5b88d5760320 1277 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1278 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::terminateCharacteristicDescriptorDiscovery_(
kenjiArai 0:5b88d5760320 1279 const DiscoveredCharacteristic& characteristic
kenjiArai 0:5b88d5760320 1280 ) {
kenjiArai 0:5b88d5760320 1281 ProcedureControlBlock* pcb = control_blocks;
kenjiArai 0:5b88d5760320 1282
kenjiArai 0:5b88d5760320 1283 while (pcb) {
kenjiArai 0:5b88d5760320 1284 if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE) {
kenjiArai 0:5b88d5760320 1285 DescriptorDiscoveryControlBlock* dpcb =
kenjiArai 0:5b88d5760320 1286 static_cast<DescriptorDiscoveryControlBlock*>(pcb);
kenjiArai 0:5b88d5760320 1287 if (dpcb->characteristic == characteristic) {
kenjiArai 0:5b88d5760320 1288 dpcb->done = true;
kenjiArai 0:5b88d5760320 1289 return;
kenjiArai 0:5b88d5760320 1290 }
kenjiArai 0:5b88d5760320 1291 }
kenjiArai 0:5b88d5760320 1292
kenjiArai 0:5b88d5760320 1293 pcb = pcb->next;
kenjiArai 0:5b88d5760320 1294 }
kenjiArai 0:5b88d5760320 1295
kenjiArai 0:5b88d5760320 1296 }
kenjiArai 0:5b88d5760320 1297
kenjiArai 0:5b88d5760320 1298 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1299 ble_error_t GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::negotiateAttMtu_(
kenjiArai 0:5b88d5760320 1300 connection_handle_t connection
kenjiArai 0:5b88d5760320 1301 ) {
kenjiArai 0:5b88d5760320 1302 return _pal_client->exchange_mtu(connection);
kenjiArai 0:5b88d5760320 1303 }
kenjiArai 0:5b88d5760320 1304
kenjiArai 0:5b88d5760320 1305 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1306 ble_error_t GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::reset_(void) {
kenjiArai 0:5b88d5760320 1307
kenjiArai 0:5b88d5760320 1308 Base::reset_();
kenjiArai 0:5b88d5760320 1309
kenjiArai 0:5b88d5760320 1310 // _is_reseting prevent executions of new procedure while the instance resets.
kenjiArai 0:5b88d5760320 1311 // otherwise new procedures can be launched from callbacks generated by the
kenjiArai 0:5b88d5760320 1312 // reset.
kenjiArai 0:5b88d5760320 1313 _is_reseting = true;
kenjiArai 0:5b88d5760320 1314 while (control_blocks) {
kenjiArai 0:5b88d5760320 1315 control_blocks->abort(this);
kenjiArai 0:5b88d5760320 1316 }
kenjiArai 0:5b88d5760320 1317 _is_reseting = false;
kenjiArai 0:5b88d5760320 1318
kenjiArai 0:5b88d5760320 1319 return BLE_ERROR_NONE;
kenjiArai 0:5b88d5760320 1320 }
kenjiArai 0:5b88d5760320 1321
kenjiArai 0:5b88d5760320 1322 #if BLE_FEATURE_SIGNING
kenjiArai 0:5b88d5760320 1323 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1324 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::set_signing_event_handler_(
kenjiArai 0:5b88d5760320 1325 SigningMonitorEventHandler *signing_event_handler
kenjiArai 0:5b88d5760320 1326 ) {
kenjiArai 0:5b88d5760320 1327 _signing_event_handler = signing_event_handler;
kenjiArai 0:5b88d5760320 1328 }
kenjiArai 0:5b88d5760320 1329 #endif // BLE_FEATURE_SIGNING
kenjiArai 0:5b88d5760320 1330
kenjiArai 0:5b88d5760320 1331 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1332 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::on_att_mtu_change_(
kenjiArai 0:5b88d5760320 1333 ble::connection_handle_t connection_handle,
kenjiArai 0:5b88d5760320 1334 uint16_t att_mtu_size
kenjiArai 0:5b88d5760320 1335 )
kenjiArai 0:5b88d5760320 1336 {
kenjiArai 0:5b88d5760320 1337 if (eventHandler) {
kenjiArai 0:5b88d5760320 1338 eventHandler->onAttMtuChange(connection_handle, att_mtu_size);
kenjiArai 0:5b88d5760320 1339 }
kenjiArai 0:5b88d5760320 1340 }
kenjiArai 0:5b88d5760320 1341
kenjiArai 0:5b88d5760320 1342 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1343 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::on_write_command_sent_(
kenjiArai 0:5b88d5760320 1344 ble::connection_handle_t connection_handle,
kenjiArai 0:5b88d5760320 1345 ble::attribute_handle_t attribute_handle,
kenjiArai 0:5b88d5760320 1346 uint8_t status
kenjiArai 0:5b88d5760320 1347 ) {
kenjiArai 0:5b88d5760320 1348 GattWriteCallbackParams response = {
kenjiArai 0:5b88d5760320 1349 connection_handle,
kenjiArai 0:5b88d5760320 1350 attribute_handle,
kenjiArai 0:5b88d5760320 1351 GattWriteCallbackParams::OP_WRITE_CMD,
kenjiArai 0:5b88d5760320 1352 BLE_ERROR_NONE,
kenjiArai 0:5b88d5760320 1353 status
kenjiArai 0:5b88d5760320 1354 };
kenjiArai 0:5b88d5760320 1355
kenjiArai 0:5b88d5760320 1356 this->processWriteResponse(&response);
kenjiArai 0:5b88d5760320 1357 }
kenjiArai 0:5b88d5760320 1358
kenjiArai 0:5b88d5760320 1359
kenjiArai 0:5b88d5760320 1360 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1361 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::on_termination(connection_handle_t connection_handle) {
kenjiArai 0:5b88d5760320 1362 if (_termination_callback) {
kenjiArai 0:5b88d5760320 1363 _termination_callback(connection_handle);
kenjiArai 0:5b88d5760320 1364 }
kenjiArai 0:5b88d5760320 1365 }
kenjiArai 0:5b88d5760320 1366
kenjiArai 0:5b88d5760320 1367 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1368 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::on_server_message_received(
kenjiArai 0:5b88d5760320 1369 connection_handle_t connection_handle,
kenjiArai 0:5b88d5760320 1370 const AttServerMessage& message
kenjiArai 0:5b88d5760320 1371 ) {
kenjiArai 0:5b88d5760320 1372 switch(message.opcode) {
kenjiArai 0:5b88d5760320 1373 case AttributeOpcode::ERROR_RESPONSE:
kenjiArai 0:5b88d5760320 1374 case AttributeOpcode::EXCHANGE_MTU_RESPONSE:
kenjiArai 0:5b88d5760320 1375 case AttributeOpcode::FIND_INFORMATION_RESPONSE:
kenjiArai 0:5b88d5760320 1376 case AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE:
kenjiArai 0:5b88d5760320 1377 case AttributeOpcode::READ_BY_TYPE_RESPONSE:
kenjiArai 0:5b88d5760320 1378 case AttributeOpcode::READ_RESPONSE:
kenjiArai 0:5b88d5760320 1379 case AttributeOpcode::READ_BLOB_RESPONSE:
kenjiArai 0:5b88d5760320 1380 case AttributeOpcode::READ_MULTIPLE_RESPONSE:
kenjiArai 0:5b88d5760320 1381 case AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE:
kenjiArai 0:5b88d5760320 1382 case AttributeOpcode::WRITE_RESPONSE:
kenjiArai 0:5b88d5760320 1383 case AttributeOpcode::PREPARE_WRITE_RESPONSE:
kenjiArai 0:5b88d5760320 1384 case AttributeOpcode::EXECUTE_WRITE_RESPONSE: {
kenjiArai 0:5b88d5760320 1385 on_server_response(connection_handle, message);
kenjiArai 0:5b88d5760320 1386 } break;
kenjiArai 0:5b88d5760320 1387
kenjiArai 0:5b88d5760320 1388 case AttributeOpcode::HANDLE_VALUE_INDICATION:
kenjiArai 0:5b88d5760320 1389 case AttributeOpcode::HANDLE_VALUE_NOTIFICATION: {
kenjiArai 0:5b88d5760320 1390 on_server_event(connection_handle, message);
kenjiArai 0:5b88d5760320 1391 } break;
kenjiArai 0:5b88d5760320 1392
kenjiArai 0:5b88d5760320 1393 default:
kenjiArai 0:5b88d5760320 1394 // invalid message receive
kenjiArai 0:5b88d5760320 1395 return;
kenjiArai 0:5b88d5760320 1396 }
kenjiArai 0:5b88d5760320 1397 }
kenjiArai 0:5b88d5760320 1398
kenjiArai 0:5b88d5760320 1399 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1400 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::on_server_response(
kenjiArai 0:5b88d5760320 1401 connection_handle_t connection,
kenjiArai 0:5b88d5760320 1402 const AttServerMessage& message
kenjiArai 0:5b88d5760320 1403 ) {
kenjiArai 0:5b88d5760320 1404 ProcedureControlBlock* pcb = get_control_block(connection);
kenjiArai 0:5b88d5760320 1405 if (pcb == NULL) {
kenjiArai 0:5b88d5760320 1406 return;
kenjiArai 0:5b88d5760320 1407 }
kenjiArai 0:5b88d5760320 1408
kenjiArai 0:5b88d5760320 1409 pcb->handle(this, message);
kenjiArai 0:5b88d5760320 1410 }
kenjiArai 0:5b88d5760320 1411
kenjiArai 0:5b88d5760320 1412 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1413 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::on_server_event(connection_handle_t connection, const AttServerMessage& message) {
kenjiArai 0:5b88d5760320 1414 GattHVXCallbackParams callbacks_params = {
kenjiArai 0:5b88d5760320 1415 (connection_handle_t) connection, 0
kenjiArai 0:5b88d5760320 1416 };
kenjiArai 0:5b88d5760320 1417
kenjiArai 0:5b88d5760320 1418 switch (message.opcode) {
kenjiArai 0:5b88d5760320 1419 case AttributeOpcode::HANDLE_VALUE_NOTIFICATION: {
kenjiArai 0:5b88d5760320 1420 const AttHandleValueNotification& notification =
kenjiArai 0:5b88d5760320 1421 static_cast<const AttHandleValueNotification&>(message);
kenjiArai 0:5b88d5760320 1422 callbacks_params.handle = notification.attribute_handle;
kenjiArai 0:5b88d5760320 1423 callbacks_params.type = BLE_HVX_NOTIFICATION;
kenjiArai 0:5b88d5760320 1424 callbacks_params.len = notification.attribute_value.size();
kenjiArai 0:5b88d5760320 1425 callbacks_params.data = notification.attribute_value.data();
kenjiArai 0:5b88d5760320 1426 } break;
kenjiArai 0:5b88d5760320 1427
kenjiArai 0:5b88d5760320 1428 case AttributeOpcode::HANDLE_VALUE_INDICATION: {
kenjiArai 0:5b88d5760320 1429 const AttHandleValueIndication& indication =
kenjiArai 0:5b88d5760320 1430 static_cast<const AttHandleValueIndication&>(message);
kenjiArai 0:5b88d5760320 1431 callbacks_params.handle = indication.attribute_handle;
kenjiArai 0:5b88d5760320 1432 callbacks_params.type = BLE_HVX_INDICATION;
kenjiArai 0:5b88d5760320 1433 callbacks_params.len = indication.attribute_value.size();
kenjiArai 0:5b88d5760320 1434 callbacks_params.data = indication.attribute_value.data();
kenjiArai 0:5b88d5760320 1435 } break;
kenjiArai 0:5b88d5760320 1436
kenjiArai 0:5b88d5760320 1437 default:
kenjiArai 0:5b88d5760320 1438 return;
kenjiArai 0:5b88d5760320 1439 }
kenjiArai 0:5b88d5760320 1440
kenjiArai 0:5b88d5760320 1441 Base::processHVXEvent(&callbacks_params);
kenjiArai 0:5b88d5760320 1442 }
kenjiArai 0:5b88d5760320 1443
kenjiArai 0:5b88d5760320 1444 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1445 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::on_transaction_timeout(connection_handle_t connection) {
kenjiArai 0:5b88d5760320 1446 ProcedureControlBlock* pcb = get_control_block(connection);
kenjiArai 0:5b88d5760320 1447 if (pcb == NULL) {
kenjiArai 0:5b88d5760320 1448 return;
kenjiArai 0:5b88d5760320 1449 }
kenjiArai 0:5b88d5760320 1450
kenjiArai 0:5b88d5760320 1451 pcb->handle_timeout_error(this);
kenjiArai 0:5b88d5760320 1452 }
kenjiArai 0:5b88d5760320 1453
kenjiArai 0:5b88d5760320 1454 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1455 typename GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::ProcedureControlBlock*
kenjiArai 0:5b88d5760320 1456 GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::get_control_block(connection_handle_t connection) {
kenjiArai 0:5b88d5760320 1457 ProcedureControlBlock* it = control_blocks;
kenjiArai 0:5b88d5760320 1458 while (it && it->connection_handle != connection) {
kenjiArai 0:5b88d5760320 1459 it = it->next;
kenjiArai 0:5b88d5760320 1460 }
kenjiArai 0:5b88d5760320 1461 return it;
kenjiArai 0:5b88d5760320 1462 }
kenjiArai 0:5b88d5760320 1463
kenjiArai 0:5b88d5760320 1464 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1465 const typename GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::ProcedureControlBlock*
kenjiArai 0:5b88d5760320 1466 GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::get_control_block(connection_handle_t connection) const {
kenjiArai 0:5b88d5760320 1467 ProcedureControlBlock* it = control_blocks;
kenjiArai 0:5b88d5760320 1468 while (it && it->connection_handle != connection) {
kenjiArai 0:5b88d5760320 1469 it = it->next;
kenjiArai 0:5b88d5760320 1470 }
kenjiArai 0:5b88d5760320 1471 return it;
kenjiArai 0:5b88d5760320 1472 }
kenjiArai 0:5b88d5760320 1473
kenjiArai 0:5b88d5760320 1474 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1475 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::insert_control_block(ProcedureControlBlock* cb) const {
kenjiArai 0:5b88d5760320 1476 if (control_blocks == NULL) {
kenjiArai 0:5b88d5760320 1477 control_blocks = cb;
kenjiArai 0:5b88d5760320 1478 return;
kenjiArai 0:5b88d5760320 1479 }
kenjiArai 0:5b88d5760320 1480
kenjiArai 0:5b88d5760320 1481 ProcedureControlBlock* current = control_blocks;
kenjiArai 0:5b88d5760320 1482 while (current->next) {
kenjiArai 0:5b88d5760320 1483 current = current->next;
kenjiArai 0:5b88d5760320 1484 }
kenjiArai 0:5b88d5760320 1485 current->next = cb;
kenjiArai 0:5b88d5760320 1486 }
kenjiArai 0:5b88d5760320 1487
kenjiArai 0:5b88d5760320 1488 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1489 void GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::remove_control_block(ProcedureControlBlock* cb) const {
kenjiArai 0:5b88d5760320 1490 if (control_blocks == NULL) {
kenjiArai 0:5b88d5760320 1491 return;
kenjiArai 0:5b88d5760320 1492 }
kenjiArai 0:5b88d5760320 1493
kenjiArai 0:5b88d5760320 1494 if (cb == control_blocks) {
kenjiArai 0:5b88d5760320 1495 control_blocks = control_blocks->next;
kenjiArai 0:5b88d5760320 1496 return;
kenjiArai 0:5b88d5760320 1497 }
kenjiArai 0:5b88d5760320 1498
kenjiArai 0:5b88d5760320 1499 ProcedureControlBlock* current = control_blocks;
kenjiArai 0:5b88d5760320 1500 while (current->next && current->next != cb) {
kenjiArai 0:5b88d5760320 1501 current = current->next;
kenjiArai 0:5b88d5760320 1502 }
kenjiArai 0:5b88d5760320 1503
kenjiArai 0:5b88d5760320 1504 if (current->next == NULL) {
kenjiArai 0:5b88d5760320 1505 return;
kenjiArai 0:5b88d5760320 1506 }
kenjiArai 0:5b88d5760320 1507
kenjiArai 0:5b88d5760320 1508 current->next = cb->next;
kenjiArai 0:5b88d5760320 1509 cb->next = NULL;
kenjiArai 0:5b88d5760320 1510 }
kenjiArai 0:5b88d5760320 1511
kenjiArai 0:5b88d5760320 1512 template<template<class> class TPalGattClient, class SigningMonitorEventHandler>
kenjiArai 0:5b88d5760320 1513 uint16_t GenericGattClient<TPalGattClient, SigningMonitorEventHandler>::get_mtu(connection_handle_t connection) const {
kenjiArai 0:5b88d5760320 1514 uint16_t result = 23;
kenjiArai 0:5b88d5760320 1515 if(_pal_client->get_mtu_size((connection_handle_t) connection, result) != BLE_ERROR_NONE) {
kenjiArai 0:5b88d5760320 1516 result = 23;
kenjiArai 0:5b88d5760320 1517 }
kenjiArai 0:5b88d5760320 1518 return result;
kenjiArai 0:5b88d5760320 1519 }
kenjiArai 0:5b88d5760320 1520
kenjiArai 0:5b88d5760320 1521 } // namespace pal
kenjiArai 0:5b88d5760320 1522 } // namespace ble
kenjiArai 0:5b88d5760320 1523
kenjiArai 0:5b88d5760320 1524 #endif // BLE_FEATURE_GATT_SERVER