Junichi Katsu / Mbed 2 deprecated BLEControl

Dependencies:   FatFileSystem TB6612FNG2 mbed

Committer:
mbed_Cookbook_SE
Date:
Mon Nov 30 09:32:15 2015 +0000
Revision:
0:de03cbbcd0ff
??

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_Cookbook_SE 0:de03cbbcd0ff 1 /*
mbed_Cookbook_SE 0:de03cbbcd0ff 2 * Copyright (C) 2011-2012 by Matthias Ringwald
mbed_Cookbook_SE 0:de03cbbcd0ff 3 *
mbed_Cookbook_SE 0:de03cbbcd0ff 4 * Redistribution and use in source and binary forms, with or without
mbed_Cookbook_SE 0:de03cbbcd0ff 5 * modification, are permitted provided that the following conditions
mbed_Cookbook_SE 0:de03cbbcd0ff 6 * are met:
mbed_Cookbook_SE 0:de03cbbcd0ff 7 *
mbed_Cookbook_SE 0:de03cbbcd0ff 8 * 1. Redistributions of source code must retain the above copyright
mbed_Cookbook_SE 0:de03cbbcd0ff 9 * notice, this list of conditions and the following disclaimer.
mbed_Cookbook_SE 0:de03cbbcd0ff 10 * 2. Redistributions in binary form must reproduce the above copyright
mbed_Cookbook_SE 0:de03cbbcd0ff 11 * notice, this list of conditions and the following disclaimer in the
mbed_Cookbook_SE 0:de03cbbcd0ff 12 * documentation and/or other materials provided with the distribution.
mbed_Cookbook_SE 0:de03cbbcd0ff 13 * 3. Neither the name of the copyright holders nor the names of
mbed_Cookbook_SE 0:de03cbbcd0ff 14 * contributors may be used to endorse or promote products derived
mbed_Cookbook_SE 0:de03cbbcd0ff 15 * from this software without specific prior written permission.
mbed_Cookbook_SE 0:de03cbbcd0ff 16 * 4. Any redistribution, use, or modification is done solely for
mbed_Cookbook_SE 0:de03cbbcd0ff 17 * personal benefit and not for any commercial purpose or for
mbed_Cookbook_SE 0:de03cbbcd0ff 18 * monetary gain.
mbed_Cookbook_SE 0:de03cbbcd0ff 19 *
mbed_Cookbook_SE 0:de03cbbcd0ff 20 * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
mbed_Cookbook_SE 0:de03cbbcd0ff 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
mbed_Cookbook_SE 0:de03cbbcd0ff 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
mbed_Cookbook_SE 0:de03cbbcd0ff 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
mbed_Cookbook_SE 0:de03cbbcd0ff 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
mbed_Cookbook_SE 0:de03cbbcd0ff 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
mbed_Cookbook_SE 0:de03cbbcd0ff 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
mbed_Cookbook_SE 0:de03cbbcd0ff 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
mbed_Cookbook_SE 0:de03cbbcd0ff 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
mbed_Cookbook_SE 0:de03cbbcd0ff 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
mbed_Cookbook_SE 0:de03cbbcd0ff 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
mbed_Cookbook_SE 0:de03cbbcd0ff 31 * SUCH DAMAGE.
mbed_Cookbook_SE 0:de03cbbcd0ff 32 *
mbed_Cookbook_SE 0:de03cbbcd0ff 33 * Please inquire about commercial licensing options at btstack@ringwald.ch
mbed_Cookbook_SE 0:de03cbbcd0ff 34 *
mbed_Cookbook_SE 0:de03cbbcd0ff 35 */
mbed_Cookbook_SE 0:de03cbbcd0ff 36
mbed_Cookbook_SE 0:de03cbbcd0ff 37 #include <stdio.h>
mbed_Cookbook_SE 0:de03cbbcd0ff 38 #include <string.h>
mbed_Cookbook_SE 0:de03cbbcd0ff 39
mbed_Cookbook_SE 0:de03cbbcd0ff 40 #include "att.h"
mbed_Cookbook_SE 0:de03cbbcd0ff 41 #include "debug.h"
mbed_Cookbook_SE 0:de03cbbcd0ff 42
mbed_Cookbook_SE 0:de03cbbcd0ff 43 // from src/utils.
mbed_Cookbook_SE 0:de03cbbcd0ff 44 #define READ_BT_16( buffer, pos) ( ((uint16_t) buffer[pos]) | (((uint16_t)buffer[pos+1]) << 8))
mbed_Cookbook_SE 0:de03cbbcd0ff 45
mbed_Cookbook_SE 0:de03cbbcd0ff 46 // Buetooth Base UUID 00000000-0000-1000-8000-00805F9B34FB in little endian
mbed_Cookbook_SE 0:de03cbbcd0ff 47 static const uint8_t bluetooth_base_uuid[] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
mbed_Cookbook_SE 0:de03cbbcd0ff 48
mbed_Cookbook_SE 0:de03cbbcd0ff 49 static void bt_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){
mbed_Cookbook_SE 0:de03cbbcd0ff 50 buffer[pos++] = value;
mbed_Cookbook_SE 0:de03cbbcd0ff 51 buffer[pos++] = value >> 8;
mbed_Cookbook_SE 0:de03cbbcd0ff 52 }
mbed_Cookbook_SE 0:de03cbbcd0ff 53
mbed_Cookbook_SE 0:de03cbbcd0ff 54 static void hexdump2(void const *data, int size){
mbed_Cookbook_SE 0:de03cbbcd0ff 55 int i;
mbed_Cookbook_SE 0:de03cbbcd0ff 56 for (i=0; i<size;i++){
mbed_Cookbook_SE 0:de03cbbcd0ff 57 log_info("%02X ", ((uint8_t *)data)[i]);
mbed_Cookbook_SE 0:de03cbbcd0ff 58 }
mbed_Cookbook_SE 0:de03cbbcd0ff 59 log_info("\n");
mbed_Cookbook_SE 0:de03cbbcd0ff 60 }
mbed_Cookbook_SE 0:de03cbbcd0ff 61
mbed_Cookbook_SE 0:de03cbbcd0ff 62 static void printUUID128(const uint8_t * uuid){
mbed_Cookbook_SE 0:de03cbbcd0ff 63 int i;
mbed_Cookbook_SE 0:de03cbbcd0ff 64 for (i=15; i >= 0 ; i--){
mbed_Cookbook_SE 0:de03cbbcd0ff 65 log_info("%02X", uuid[i]);
mbed_Cookbook_SE 0:de03cbbcd0ff 66 switch (i){
mbed_Cookbook_SE 0:de03cbbcd0ff 67 case 4:
mbed_Cookbook_SE 0:de03cbbcd0ff 68 case 6:
mbed_Cookbook_SE 0:de03cbbcd0ff 69 case 8:
mbed_Cookbook_SE 0:de03cbbcd0ff 70 case 10:
mbed_Cookbook_SE 0:de03cbbcd0ff 71 log_info("-");
mbed_Cookbook_SE 0:de03cbbcd0ff 72 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 73 default:
mbed_Cookbook_SE 0:de03cbbcd0ff 74 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 75 }
mbed_Cookbook_SE 0:de03cbbcd0ff 76 }
mbed_Cookbook_SE 0:de03cbbcd0ff 77 }
mbed_Cookbook_SE 0:de03cbbcd0ff 78
mbed_Cookbook_SE 0:de03cbbcd0ff 79 static int is_Bluetooth_Base_UUID(uint8_t const *uuid){
mbed_Cookbook_SE 0:de03cbbcd0ff 80 if (memcmp(&uuid[0], &bluetooth_base_uuid[0], 12)) return 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 81 if (memcmp(&uuid[14], &bluetooth_base_uuid[14], 2)) return 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 82 return 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 83
mbed_Cookbook_SE 0:de03cbbcd0ff 84 }
mbed_Cookbook_SE 0:de03cbbcd0ff 85
mbed_Cookbook_SE 0:de03cbbcd0ff 86 // ATT Database
mbed_Cookbook_SE 0:de03cbbcd0ff 87 static uint8_t const * att_db = NULL;
mbed_Cookbook_SE 0:de03cbbcd0ff 88 static att_read_callback_t att_read_callback = NULL;
mbed_Cookbook_SE 0:de03cbbcd0ff 89 static att_write_callback_t att_write_callback = NULL;
mbed_Cookbook_SE 0:de03cbbcd0ff 90
mbed_Cookbook_SE 0:de03cbbcd0ff 91 // new java-style iterator
mbed_Cookbook_SE 0:de03cbbcd0ff 92 typedef struct att_iterator {
mbed_Cookbook_SE 0:de03cbbcd0ff 93 // private
mbed_Cookbook_SE 0:de03cbbcd0ff 94 uint8_t const * att_ptr;
mbed_Cookbook_SE 0:de03cbbcd0ff 95 // public
mbed_Cookbook_SE 0:de03cbbcd0ff 96 uint16_t size;
mbed_Cookbook_SE 0:de03cbbcd0ff 97 uint16_t flags;
mbed_Cookbook_SE 0:de03cbbcd0ff 98 uint16_t handle;
mbed_Cookbook_SE 0:de03cbbcd0ff 99 uint8_t const * uuid;
mbed_Cookbook_SE 0:de03cbbcd0ff 100 uint16_t value_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 101 uint8_t const * value;
mbed_Cookbook_SE 0:de03cbbcd0ff 102 } att_iterator_t;
mbed_Cookbook_SE 0:de03cbbcd0ff 103
mbed_Cookbook_SE 0:de03cbbcd0ff 104 void att_iterator_init(att_iterator_t *it){
mbed_Cookbook_SE 0:de03cbbcd0ff 105 it->att_ptr = att_db;
mbed_Cookbook_SE 0:de03cbbcd0ff 106 }
mbed_Cookbook_SE 0:de03cbbcd0ff 107
mbed_Cookbook_SE 0:de03cbbcd0ff 108 int att_iterator_has_next(att_iterator_t *it){
mbed_Cookbook_SE 0:de03cbbcd0ff 109 return it->att_ptr != NULL;
mbed_Cookbook_SE 0:de03cbbcd0ff 110 }
mbed_Cookbook_SE 0:de03cbbcd0ff 111
mbed_Cookbook_SE 0:de03cbbcd0ff 112 void att_iterator_fetch_next(att_iterator_t *it){
mbed_Cookbook_SE 0:de03cbbcd0ff 113 it->size = READ_BT_16(it->att_ptr, 0);
mbed_Cookbook_SE 0:de03cbbcd0ff 114 if (it->size == 0){
mbed_Cookbook_SE 0:de03cbbcd0ff 115 it->flags = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 116 it->handle = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 117 it->uuid = NULL;
mbed_Cookbook_SE 0:de03cbbcd0ff 118 it->value_len = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 119 it->value = NULL;
mbed_Cookbook_SE 0:de03cbbcd0ff 120 it->att_ptr = NULL;
mbed_Cookbook_SE 0:de03cbbcd0ff 121 return;
mbed_Cookbook_SE 0:de03cbbcd0ff 122 }
mbed_Cookbook_SE 0:de03cbbcd0ff 123 it->flags = READ_BT_16(it->att_ptr, 2);
mbed_Cookbook_SE 0:de03cbbcd0ff 124 it->handle = READ_BT_16(it->att_ptr, 4);
mbed_Cookbook_SE 0:de03cbbcd0ff 125 it->uuid = &it->att_ptr[6];
mbed_Cookbook_SE 0:de03cbbcd0ff 126 // handle 128 bit UUIDs
mbed_Cookbook_SE 0:de03cbbcd0ff 127 if (it->flags & ATT_PROPERTY_UUID128){
mbed_Cookbook_SE 0:de03cbbcd0ff 128 it->value_len = it->size - 22;
mbed_Cookbook_SE 0:de03cbbcd0ff 129 it->value = &it->att_ptr[22];
mbed_Cookbook_SE 0:de03cbbcd0ff 130 } else {
mbed_Cookbook_SE 0:de03cbbcd0ff 131 it->value_len = it->size - 8;
mbed_Cookbook_SE 0:de03cbbcd0ff 132 it->value = &it->att_ptr[8];
mbed_Cookbook_SE 0:de03cbbcd0ff 133 }
mbed_Cookbook_SE 0:de03cbbcd0ff 134 // advance AFTER setting values
mbed_Cookbook_SE 0:de03cbbcd0ff 135 it->att_ptr += it->size;
mbed_Cookbook_SE 0:de03cbbcd0ff 136 }
mbed_Cookbook_SE 0:de03cbbcd0ff 137
mbed_Cookbook_SE 0:de03cbbcd0ff 138 int att_iterator_match_uuid16(att_iterator_t *it, uint16_t uuid){
mbed_Cookbook_SE 0:de03cbbcd0ff 139 if (it->handle == 0) return 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 140 if (it->flags & ATT_PROPERTY_UUID128){
mbed_Cookbook_SE 0:de03cbbcd0ff 141 if (!is_Bluetooth_Base_UUID(it->uuid)) return 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 142 return READ_BT_16(it->uuid, 12) == uuid;
mbed_Cookbook_SE 0:de03cbbcd0ff 143 }
mbed_Cookbook_SE 0:de03cbbcd0ff 144 return READ_BT_16(it->uuid, 0) == uuid;
mbed_Cookbook_SE 0:de03cbbcd0ff 145 }
mbed_Cookbook_SE 0:de03cbbcd0ff 146
mbed_Cookbook_SE 0:de03cbbcd0ff 147 int att_iterator_match_uuid(att_iterator_t *it, uint8_t *uuid, uint16_t uuid_len){
mbed_Cookbook_SE 0:de03cbbcd0ff 148 if (it->handle == 0) return 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 149 // input: UUID16
mbed_Cookbook_SE 0:de03cbbcd0ff 150 if (uuid_len == 2) {
mbed_Cookbook_SE 0:de03cbbcd0ff 151 return att_iterator_match_uuid16(it, READ_BT_16(uuid, 0));
mbed_Cookbook_SE 0:de03cbbcd0ff 152 }
mbed_Cookbook_SE 0:de03cbbcd0ff 153 // input and db: UUID128
mbed_Cookbook_SE 0:de03cbbcd0ff 154 if (it->flags & ATT_PROPERTY_UUID128){
mbed_Cookbook_SE 0:de03cbbcd0ff 155 return memcmp(it->uuid, uuid, 16) == 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 156 }
mbed_Cookbook_SE 0:de03cbbcd0ff 157 // input: UUID128, db: UUID16
mbed_Cookbook_SE 0:de03cbbcd0ff 158 if (!is_Bluetooth_Base_UUID(uuid)) return 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 159 return READ_BT_16(uuid, 12) == READ_BT_16(it->uuid, 0);
mbed_Cookbook_SE 0:de03cbbcd0ff 160 }
mbed_Cookbook_SE 0:de03cbbcd0ff 161
mbed_Cookbook_SE 0:de03cbbcd0ff 162
mbed_Cookbook_SE 0:de03cbbcd0ff 163 int att_find_handle(att_iterator_t *it, uint16_t handle){
mbed_Cookbook_SE 0:de03cbbcd0ff 164 att_iterator_init(it);
mbed_Cookbook_SE 0:de03cbbcd0ff 165 while (att_iterator_has_next(it)){
mbed_Cookbook_SE 0:de03cbbcd0ff 166 att_iterator_fetch_next(it);
mbed_Cookbook_SE 0:de03cbbcd0ff 167 if (it->handle != handle) continue;
mbed_Cookbook_SE 0:de03cbbcd0ff 168 return 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 169 }
mbed_Cookbook_SE 0:de03cbbcd0ff 170 return 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 171 }
mbed_Cookbook_SE 0:de03cbbcd0ff 172
mbed_Cookbook_SE 0:de03cbbcd0ff 173 static void att_update_value_len(att_iterator_t *it){
mbed_Cookbook_SE 0:de03cbbcd0ff 174 if ((it->flags & ATT_PROPERTY_DYNAMIC) == 0 || !att_read_callback) return;
mbed_Cookbook_SE 0:de03cbbcd0ff 175 it->value_len = (*att_read_callback)(it->handle, 0, NULL, 0);
mbed_Cookbook_SE 0:de03cbbcd0ff 176 return;
mbed_Cookbook_SE 0:de03cbbcd0ff 177 }
mbed_Cookbook_SE 0:de03cbbcd0ff 178
mbed_Cookbook_SE 0:de03cbbcd0ff 179 static int att_copy_value(att_iterator_t *it, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 180
mbed_Cookbook_SE 0:de03cbbcd0ff 181 // DYNAMIC
mbed_Cookbook_SE 0:de03cbbcd0ff 182 if ((it->flags & ATT_PROPERTY_DYNAMIC) && att_read_callback) {
mbed_Cookbook_SE 0:de03cbbcd0ff 183 return (*att_read_callback)(it->handle, offset, buffer, buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 184 }
mbed_Cookbook_SE 0:de03cbbcd0ff 185
mbed_Cookbook_SE 0:de03cbbcd0ff 186 // STATIC
mbed_Cookbook_SE 0:de03cbbcd0ff 187 uint16_t bytes_to_copy = it->value_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 188 if (bytes_to_copy > buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 189 bytes_to_copy = buffer_size;
mbed_Cookbook_SE 0:de03cbbcd0ff 190 }
mbed_Cookbook_SE 0:de03cbbcd0ff 191 memcpy(buffer, it->value, bytes_to_copy);
mbed_Cookbook_SE 0:de03cbbcd0ff 192 return bytes_to_copy;
mbed_Cookbook_SE 0:de03cbbcd0ff 193 }
mbed_Cookbook_SE 0:de03cbbcd0ff 194
mbed_Cookbook_SE 0:de03cbbcd0ff 195 void att_set_db(uint8_t const * db){
mbed_Cookbook_SE 0:de03cbbcd0ff 196 att_db = db;
mbed_Cookbook_SE 0:de03cbbcd0ff 197 }
mbed_Cookbook_SE 0:de03cbbcd0ff 198
mbed_Cookbook_SE 0:de03cbbcd0ff 199 void att_set_read_callback(att_read_callback_t callback){
mbed_Cookbook_SE 0:de03cbbcd0ff 200 att_read_callback = callback;
mbed_Cookbook_SE 0:de03cbbcd0ff 201 }
mbed_Cookbook_SE 0:de03cbbcd0ff 202
mbed_Cookbook_SE 0:de03cbbcd0ff 203 void att_set_write_callback(att_write_callback_t callback){
mbed_Cookbook_SE 0:de03cbbcd0ff 204 att_write_callback = callback;
mbed_Cookbook_SE 0:de03cbbcd0ff 205 }
mbed_Cookbook_SE 0:de03cbbcd0ff 206
mbed_Cookbook_SE 0:de03cbbcd0ff 207 void att_dump_attributes(void){
mbed_Cookbook_SE 0:de03cbbcd0ff 208 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 209 att_iterator_init(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 210 while (att_iterator_has_next(&it)){
mbed_Cookbook_SE 0:de03cbbcd0ff 211 att_iterator_fetch_next(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 212 if (it.handle == 0) {
mbed_Cookbook_SE 0:de03cbbcd0ff 213 log_info("Handle: END\n");
mbed_Cookbook_SE 0:de03cbbcd0ff 214 return;
mbed_Cookbook_SE 0:de03cbbcd0ff 215 }
mbed_Cookbook_SE 0:de03cbbcd0ff 216 log_info("Handle: 0x%04x, flags: 0x%04x, uuid: ", it.handle, it.flags);
mbed_Cookbook_SE 0:de03cbbcd0ff 217 if (it.flags & ATT_PROPERTY_UUID128){
mbed_Cookbook_SE 0:de03cbbcd0ff 218 printUUID128(it.uuid);
mbed_Cookbook_SE 0:de03cbbcd0ff 219 } else {
mbed_Cookbook_SE 0:de03cbbcd0ff 220 log_info("%04x", READ_BT_16(it.uuid, 0));
mbed_Cookbook_SE 0:de03cbbcd0ff 221 }
mbed_Cookbook_SE 0:de03cbbcd0ff 222 log_info(", value_len: %u, value: ", it.value_len);
mbed_Cookbook_SE 0:de03cbbcd0ff 223 hexdump2(it.value, it.value_len);
mbed_Cookbook_SE 0:de03cbbcd0ff 224 }
mbed_Cookbook_SE 0:de03cbbcd0ff 225 }
mbed_Cookbook_SE 0:de03cbbcd0ff 226
mbed_Cookbook_SE 0:de03cbbcd0ff 227 static uint16_t setup_error(uint8_t * response_buffer, uint16_t request, uint16_t handle, uint8_t error_code){
mbed_Cookbook_SE 0:de03cbbcd0ff 228 response_buffer[0] = ATT_ERROR_RESPONSE;
mbed_Cookbook_SE 0:de03cbbcd0ff 229 response_buffer[1] = request;
mbed_Cookbook_SE 0:de03cbbcd0ff 230 bt_store_16(response_buffer, 2, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 231 response_buffer[4] = error_code;
mbed_Cookbook_SE 0:de03cbbcd0ff 232 return 5;
mbed_Cookbook_SE 0:de03cbbcd0ff 233 }
mbed_Cookbook_SE 0:de03cbbcd0ff 234
mbed_Cookbook_SE 0:de03cbbcd0ff 235 static uint16_t setup_error_atribute_not_found(uint8_t * response_buffer, uint16_t request, uint16_t start_handle){
mbed_Cookbook_SE 0:de03cbbcd0ff 236 return setup_error(response_buffer, request, start_handle, ATT_ERROR_ATTRIBUTE_NOT_FOUND);
mbed_Cookbook_SE 0:de03cbbcd0ff 237 }
mbed_Cookbook_SE 0:de03cbbcd0ff 238
mbed_Cookbook_SE 0:de03cbbcd0ff 239 static uint16_t setup_error_invalid_handle(uint8_t * response_buffer, uint16_t request, uint16_t handle){
mbed_Cookbook_SE 0:de03cbbcd0ff 240 return setup_error(response_buffer, request, handle, ATT_ERROR_ATTRIBUTE_INVALID);
mbed_Cookbook_SE 0:de03cbbcd0ff 241 }
mbed_Cookbook_SE 0:de03cbbcd0ff 242
mbed_Cookbook_SE 0:de03cbbcd0ff 243 static uint16_t setup_error_invalid_offset(uint8_t * response_buffer, uint16_t request, uint16_t handle){
mbed_Cookbook_SE 0:de03cbbcd0ff 244 return setup_error(response_buffer, request, handle, ATT_ERROR_INVALID_OFFSET);
mbed_Cookbook_SE 0:de03cbbcd0ff 245 }
mbed_Cookbook_SE 0:de03cbbcd0ff 246
mbed_Cookbook_SE 0:de03cbbcd0ff 247 //
mbed_Cookbook_SE 0:de03cbbcd0ff 248 // MARK: ATT_EXCHANGE_MTU_REQUEST
mbed_Cookbook_SE 0:de03cbbcd0ff 249 //
mbed_Cookbook_SE 0:de03cbbcd0ff 250 static uint16_t handle_exchange_mtu_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 251 uint8_t * response_buffer){
mbed_Cookbook_SE 0:de03cbbcd0ff 252
mbed_Cookbook_SE 0:de03cbbcd0ff 253 uint16_t client_rx_mtu = READ_BT_16(request_buffer, 1);
mbed_Cookbook_SE 0:de03cbbcd0ff 254 if (client_rx_mtu < att_connection->mtu){
mbed_Cookbook_SE 0:de03cbbcd0ff 255 att_connection->mtu = client_rx_mtu;
mbed_Cookbook_SE 0:de03cbbcd0ff 256 }
mbed_Cookbook_SE 0:de03cbbcd0ff 257
mbed_Cookbook_SE 0:de03cbbcd0ff 258 response_buffer[0] = ATT_EXCHANGE_MTU_RESPONSE;
mbed_Cookbook_SE 0:de03cbbcd0ff 259 bt_store_16(response_buffer, 1, att_connection->mtu);
mbed_Cookbook_SE 0:de03cbbcd0ff 260 return 3;
mbed_Cookbook_SE 0:de03cbbcd0ff 261 }
mbed_Cookbook_SE 0:de03cbbcd0ff 262
mbed_Cookbook_SE 0:de03cbbcd0ff 263
mbed_Cookbook_SE 0:de03cbbcd0ff 264 //
mbed_Cookbook_SE 0:de03cbbcd0ff 265 // MARK: ATT_FIND_INFORMATION_REQUEST
mbed_Cookbook_SE 0:de03cbbcd0ff 266 //
mbed_Cookbook_SE 0:de03cbbcd0ff 267 // TODO: handle other types then GATT_PRIMARY_SERVICE_UUID and GATT_SECONDARY_SERVICE_UUID
mbed_Cookbook_SE 0:de03cbbcd0ff 268 //
mbed_Cookbook_SE 0:de03cbbcd0ff 269 static uint16_t handle_find_information_request2(uint8_t * response_buffer, uint16_t response_buffer_size,
mbed_Cookbook_SE 0:de03cbbcd0ff 270 uint16_t start_handle, uint16_t end_handle){
mbed_Cookbook_SE 0:de03cbbcd0ff 271
mbed_Cookbook_SE 0:de03cbbcd0ff 272 log_info("ATT_FIND_INFORMATION_REQUEST: from %04X to %04X\n", start_handle, end_handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 273
mbed_Cookbook_SE 0:de03cbbcd0ff 274 uint16_t offset = 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 275 uint16_t pair_len = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 276
mbed_Cookbook_SE 0:de03cbbcd0ff 277 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 278 att_iterator_init(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 279 while (att_iterator_has_next(&it)){
mbed_Cookbook_SE 0:de03cbbcd0ff 280 att_iterator_fetch_next(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 281 if (!it.handle) break;
mbed_Cookbook_SE 0:de03cbbcd0ff 282 if (it.handle > end_handle) break;
mbed_Cookbook_SE 0:de03cbbcd0ff 283 if (it.handle < start_handle) continue;
mbed_Cookbook_SE 0:de03cbbcd0ff 284
mbed_Cookbook_SE 0:de03cbbcd0ff 285 att_update_value_len(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 286
mbed_Cookbook_SE 0:de03cbbcd0ff 287 // log_debug("Handle 0x%04x\n", it.handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 288
mbed_Cookbook_SE 0:de03cbbcd0ff 289 // check if value has same len as last one
mbed_Cookbook_SE 0:de03cbbcd0ff 290 uint16_t this_pair_len = 2 + it.value_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 291 if (offset > 1){
mbed_Cookbook_SE 0:de03cbbcd0ff 292 if (pair_len != this_pair_len) {
mbed_Cookbook_SE 0:de03cbbcd0ff 293 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 294 }
mbed_Cookbook_SE 0:de03cbbcd0ff 295 }
mbed_Cookbook_SE 0:de03cbbcd0ff 296
mbed_Cookbook_SE 0:de03cbbcd0ff 297 // first
mbed_Cookbook_SE 0:de03cbbcd0ff 298 if (offset == 1) {
mbed_Cookbook_SE 0:de03cbbcd0ff 299 pair_len = this_pair_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 300 if (it.value_len == 2) {
mbed_Cookbook_SE 0:de03cbbcd0ff 301 response_buffer[offset] = 0x01; // format
mbed_Cookbook_SE 0:de03cbbcd0ff 302 } else {
mbed_Cookbook_SE 0:de03cbbcd0ff 303 response_buffer[offset] = 0x02;
mbed_Cookbook_SE 0:de03cbbcd0ff 304 }
mbed_Cookbook_SE 0:de03cbbcd0ff 305 offset++;
mbed_Cookbook_SE 0:de03cbbcd0ff 306 }
mbed_Cookbook_SE 0:de03cbbcd0ff 307
mbed_Cookbook_SE 0:de03cbbcd0ff 308 // space?
mbed_Cookbook_SE 0:de03cbbcd0ff 309 if (offset + pair_len > response_buffer_size) {
mbed_Cookbook_SE 0:de03cbbcd0ff 310 if (offset > 2) break;
mbed_Cookbook_SE 0:de03cbbcd0ff 311 it.value_len = response_buffer_size - 4;
mbed_Cookbook_SE 0:de03cbbcd0ff 312 }
mbed_Cookbook_SE 0:de03cbbcd0ff 313
mbed_Cookbook_SE 0:de03cbbcd0ff 314 // store
mbed_Cookbook_SE 0:de03cbbcd0ff 315 bt_store_16(response_buffer, offset, it.handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 316 offset += 2;
mbed_Cookbook_SE 0:de03cbbcd0ff 317 uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len);
mbed_Cookbook_SE 0:de03cbbcd0ff 318 offset += bytes_copied;
mbed_Cookbook_SE 0:de03cbbcd0ff 319 }
mbed_Cookbook_SE 0:de03cbbcd0ff 320
mbed_Cookbook_SE 0:de03cbbcd0ff 321 if (offset == 1){
mbed_Cookbook_SE 0:de03cbbcd0ff 322 return setup_error_atribute_not_found(response_buffer, ATT_FIND_INFORMATION_REQUEST, start_handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 323 }
mbed_Cookbook_SE 0:de03cbbcd0ff 324
mbed_Cookbook_SE 0:de03cbbcd0ff 325 response_buffer[0] = ATT_FIND_INFORMATION_REPLY;
mbed_Cookbook_SE 0:de03cbbcd0ff 326 return offset;
mbed_Cookbook_SE 0:de03cbbcd0ff 327 }
mbed_Cookbook_SE 0:de03cbbcd0ff 328
mbed_Cookbook_SE 0:de03cbbcd0ff 329 static uint16_t handle_find_information_request(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 330 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 331 return handle_find_information_request2(response_buffer, response_buffer_size, READ_BT_16(request_buffer, 1), READ_BT_16(request_buffer, 3));
mbed_Cookbook_SE 0:de03cbbcd0ff 332 }
mbed_Cookbook_SE 0:de03cbbcd0ff 333
mbed_Cookbook_SE 0:de03cbbcd0ff 334 //
mbed_Cookbook_SE 0:de03cbbcd0ff 335 // MARK: ATT_FIND_BY_TYPE_VALUE
mbed_Cookbook_SE 0:de03cbbcd0ff 336 //
mbed_Cookbook_SE 0:de03cbbcd0ff 337 // "Only attributes with attribute handles between and including the Starting Handle parameter
mbed_Cookbook_SE 0:de03cbbcd0ff 338 // and the Ending Handle parameter that match the requested attri- bute type and the attribute
mbed_Cookbook_SE 0:de03cbbcd0ff 339 // value that have sufficient permissions to allow reading will be returned" -> (1)
mbed_Cookbook_SE 0:de03cbbcd0ff 340 //
mbed_Cookbook_SE 0:de03cbbcd0ff 341 // TODO: handle other types then GATT_PRIMARY_SERVICE_UUID and GATT_SECONDARY_SERVICE_UUID
mbed_Cookbook_SE 0:de03cbbcd0ff 342 //
mbed_Cookbook_SE 0:de03cbbcd0ff 343 // NOTE: doesn't handle DYNAMIC values
mbed_Cookbook_SE 0:de03cbbcd0ff 344 // NOTE: only supports 16 bit UUIDs
mbed_Cookbook_SE 0:de03cbbcd0ff 345 //
mbed_Cookbook_SE 0:de03cbbcd0ff 346 static uint16_t handle_find_by_type_value_request2(uint8_t * response_buffer, uint16_t response_buffer_size,
mbed_Cookbook_SE 0:de03cbbcd0ff 347 uint16_t start_handle, uint16_t end_handle,
mbed_Cookbook_SE 0:de03cbbcd0ff 348 uint16_t attribute_type, uint16_t attribute_len, uint8_t* attribute_value){
mbed_Cookbook_SE 0:de03cbbcd0ff 349
mbed_Cookbook_SE 0:de03cbbcd0ff 350 log_info("ATT_FIND_BY_TYPE_VALUE_REQUEST: from %04X to %04X, type %04X, value: ", start_handle, end_handle, attribute_type);
mbed_Cookbook_SE 0:de03cbbcd0ff 351 hexdump2(attribute_value, attribute_len);
mbed_Cookbook_SE 0:de03cbbcd0ff 352
mbed_Cookbook_SE 0:de03cbbcd0ff 353 uint16_t offset = 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 354 uint16_t in_group = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 355 uint16_t prev_handle = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 356
mbed_Cookbook_SE 0:de03cbbcd0ff 357 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 358 att_iterator_init(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 359 while (att_iterator_has_next(&it)){
mbed_Cookbook_SE 0:de03cbbcd0ff 360 att_iterator_fetch_next(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 361
mbed_Cookbook_SE 0:de03cbbcd0ff 362 if (it.handle && it.handle < start_handle) continue;
mbed_Cookbook_SE 0:de03cbbcd0ff 363 if (it.handle > end_handle) break; // (1)
mbed_Cookbook_SE 0:de03cbbcd0ff 364
mbed_Cookbook_SE 0:de03cbbcd0ff 365 // close current tag, if within a group and a new service definition starts or we reach end of att db
mbed_Cookbook_SE 0:de03cbbcd0ff 366 if (in_group &&
mbed_Cookbook_SE 0:de03cbbcd0ff 367 (it.handle == 0 || att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID))){
mbed_Cookbook_SE 0:de03cbbcd0ff 368
mbed_Cookbook_SE 0:de03cbbcd0ff 369 log_info("End of group, handle 0x%04x\n", prev_handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 370 bt_store_16(response_buffer, offset, prev_handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 371 offset += 2;
mbed_Cookbook_SE 0:de03cbbcd0ff 372 in_group = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 373
mbed_Cookbook_SE 0:de03cbbcd0ff 374 // check if space for another handle pair available
mbed_Cookbook_SE 0:de03cbbcd0ff 375 if (offset + 4 > response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 376 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 377 }
mbed_Cookbook_SE 0:de03cbbcd0ff 378 }
mbed_Cookbook_SE 0:de03cbbcd0ff 379
mbed_Cookbook_SE 0:de03cbbcd0ff 380 // keep track of previous handle
mbed_Cookbook_SE 0:de03cbbcd0ff 381 prev_handle = it.handle;
mbed_Cookbook_SE 0:de03cbbcd0ff 382
mbed_Cookbook_SE 0:de03cbbcd0ff 383 // does current attribute match
mbed_Cookbook_SE 0:de03cbbcd0ff 384 if (it.handle && att_iterator_match_uuid16(&it, attribute_type) && attribute_len == it.value_len && memcmp(attribute_value, it.value, it.value_len) == 0){
mbed_Cookbook_SE 0:de03cbbcd0ff 385 log_info("Begin of group, handle 0x%04x\n", it.handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 386 bt_store_16(response_buffer, offset, it.handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 387 offset += 2;
mbed_Cookbook_SE 0:de03cbbcd0ff 388 in_group = 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 389 }
mbed_Cookbook_SE 0:de03cbbcd0ff 390 }
mbed_Cookbook_SE 0:de03cbbcd0ff 391
mbed_Cookbook_SE 0:de03cbbcd0ff 392 if (offset == 1){
mbed_Cookbook_SE 0:de03cbbcd0ff 393 return setup_error_atribute_not_found(response_buffer, ATT_FIND_BY_TYPE_VALUE_REQUEST, start_handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 394 }
mbed_Cookbook_SE 0:de03cbbcd0ff 395
mbed_Cookbook_SE 0:de03cbbcd0ff 396 response_buffer[0] = ATT_FIND_BY_TYPE_VALUE_RESPONSE;
mbed_Cookbook_SE 0:de03cbbcd0ff 397 return offset;
mbed_Cookbook_SE 0:de03cbbcd0ff 398 }
mbed_Cookbook_SE 0:de03cbbcd0ff 399
mbed_Cookbook_SE 0:de03cbbcd0ff 400 static uint16_t handle_find_by_type_value_request(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 401 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 402 int attribute_len = request_len - 7;
mbed_Cookbook_SE 0:de03cbbcd0ff 403 return handle_find_by_type_value_request2(response_buffer, response_buffer_size, READ_BT_16(request_buffer, 1),
mbed_Cookbook_SE 0:de03cbbcd0ff 404 READ_BT_16(request_buffer, 3), READ_BT_16(request_buffer, 5), attribute_len, &request_buffer[7]);
mbed_Cookbook_SE 0:de03cbbcd0ff 405 }
mbed_Cookbook_SE 0:de03cbbcd0ff 406
mbed_Cookbook_SE 0:de03cbbcd0ff 407 //
mbed_Cookbook_SE 0:de03cbbcd0ff 408 // MARK: ATT_READ_BY_TYPE_REQUEST
mbed_Cookbook_SE 0:de03cbbcd0ff 409 //
mbed_Cookbook_SE 0:de03cbbcd0ff 410 static uint16_t handle_read_by_type_request2(uint8_t * response_buffer, uint16_t response_buffer_size,
mbed_Cookbook_SE 0:de03cbbcd0ff 411 uint16_t start_handle, uint16_t end_handle,
mbed_Cookbook_SE 0:de03cbbcd0ff 412 uint16_t attribute_type_len, uint8_t * attribute_type){
mbed_Cookbook_SE 0:de03cbbcd0ff 413
mbed_Cookbook_SE 0:de03cbbcd0ff 414 log_info("ATT_READ_BY_TYPE_REQUEST: from %04X to %04X, type: ", start_handle, end_handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 415 hexdump2(attribute_type, attribute_type_len);
mbed_Cookbook_SE 0:de03cbbcd0ff 416
mbed_Cookbook_SE 0:de03cbbcd0ff 417 uint16_t offset = 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 418 uint16_t pair_len = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 419
mbed_Cookbook_SE 0:de03cbbcd0ff 420 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 421 att_iterator_init(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 422 while (att_iterator_has_next(&it)){
mbed_Cookbook_SE 0:de03cbbcd0ff 423 att_iterator_fetch_next(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 424
mbed_Cookbook_SE 0:de03cbbcd0ff 425 if (!it.handle) break;
mbed_Cookbook_SE 0:de03cbbcd0ff 426 if (it.handle < start_handle) continue;
mbed_Cookbook_SE 0:de03cbbcd0ff 427 if (it.handle > end_handle) break; // (1)
mbed_Cookbook_SE 0:de03cbbcd0ff 428
mbed_Cookbook_SE 0:de03cbbcd0ff 429 // does current attribute match
mbed_Cookbook_SE 0:de03cbbcd0ff 430 if (!att_iterator_match_uuid(&it, attribute_type, attribute_type_len)) continue;
mbed_Cookbook_SE 0:de03cbbcd0ff 431
mbed_Cookbook_SE 0:de03cbbcd0ff 432 att_update_value_len(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 433
mbed_Cookbook_SE 0:de03cbbcd0ff 434 // check if value has same len as last one
mbed_Cookbook_SE 0:de03cbbcd0ff 435 uint16_t this_pair_len = 2 + it.value_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 436 if (offset > 1){
mbed_Cookbook_SE 0:de03cbbcd0ff 437 if (pair_len != this_pair_len) {
mbed_Cookbook_SE 0:de03cbbcd0ff 438 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 439 }
mbed_Cookbook_SE 0:de03cbbcd0ff 440 }
mbed_Cookbook_SE 0:de03cbbcd0ff 441
mbed_Cookbook_SE 0:de03cbbcd0ff 442 // first
mbed_Cookbook_SE 0:de03cbbcd0ff 443 if (offset == 1) {
mbed_Cookbook_SE 0:de03cbbcd0ff 444 pair_len = this_pair_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 445 response_buffer[offset] = pair_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 446 offset++;
mbed_Cookbook_SE 0:de03cbbcd0ff 447 }
mbed_Cookbook_SE 0:de03cbbcd0ff 448
mbed_Cookbook_SE 0:de03cbbcd0ff 449 // space?
mbed_Cookbook_SE 0:de03cbbcd0ff 450 if (offset + pair_len > response_buffer_size) {
mbed_Cookbook_SE 0:de03cbbcd0ff 451 if (offset > 2) break;
mbed_Cookbook_SE 0:de03cbbcd0ff 452 it.value_len = response_buffer_size - 4;
mbed_Cookbook_SE 0:de03cbbcd0ff 453 }
mbed_Cookbook_SE 0:de03cbbcd0ff 454
mbed_Cookbook_SE 0:de03cbbcd0ff 455 // store
mbed_Cookbook_SE 0:de03cbbcd0ff 456 bt_store_16(response_buffer, offset, it.handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 457 offset += 2;
mbed_Cookbook_SE 0:de03cbbcd0ff 458 uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len);
mbed_Cookbook_SE 0:de03cbbcd0ff 459 offset += bytes_copied;
mbed_Cookbook_SE 0:de03cbbcd0ff 460 }
mbed_Cookbook_SE 0:de03cbbcd0ff 461
mbed_Cookbook_SE 0:de03cbbcd0ff 462 if (offset == 1){
mbed_Cookbook_SE 0:de03cbbcd0ff 463 return setup_error_atribute_not_found(response_buffer, ATT_READ_BY_TYPE_REQUEST, start_handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 464 }
mbed_Cookbook_SE 0:de03cbbcd0ff 465
mbed_Cookbook_SE 0:de03cbbcd0ff 466 response_buffer[0] = ATT_READ_BY_TYPE_RESPONSE;
mbed_Cookbook_SE 0:de03cbbcd0ff 467 return offset;
mbed_Cookbook_SE 0:de03cbbcd0ff 468 }
mbed_Cookbook_SE 0:de03cbbcd0ff 469
mbed_Cookbook_SE 0:de03cbbcd0ff 470 static uint16_t handle_read_by_type_request(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 471 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 472 int attribute_type_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 473 if (request_len <= 7){
mbed_Cookbook_SE 0:de03cbbcd0ff 474 attribute_type_len = 2;
mbed_Cookbook_SE 0:de03cbbcd0ff 475 } else {
mbed_Cookbook_SE 0:de03cbbcd0ff 476 attribute_type_len = 16;
mbed_Cookbook_SE 0:de03cbbcd0ff 477 }
mbed_Cookbook_SE 0:de03cbbcd0ff 478 return handle_read_by_type_request2(response_buffer, response_buffer_size, READ_BT_16(request_buffer, 1), READ_BT_16(request_buffer, 3), attribute_type_len, &request_buffer[5]);
mbed_Cookbook_SE 0:de03cbbcd0ff 479 }
mbed_Cookbook_SE 0:de03cbbcd0ff 480
mbed_Cookbook_SE 0:de03cbbcd0ff 481 //
mbed_Cookbook_SE 0:de03cbbcd0ff 482 // MARK: ATT_READ_BY_TYPE_REQUEST
mbed_Cookbook_SE 0:de03cbbcd0ff 483 //
mbed_Cookbook_SE 0:de03cbbcd0ff 484 static uint16_t handle_read_request2(uint8_t * response_buffer, uint16_t response_buffer_size, uint16_t handle){
mbed_Cookbook_SE 0:de03cbbcd0ff 485
mbed_Cookbook_SE 0:de03cbbcd0ff 486 log_info("ATT_READ_REQUEST: handle %04x\n", handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 487
mbed_Cookbook_SE 0:de03cbbcd0ff 488 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 489 int ok = att_find_handle(&it, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 490 if (!ok){
mbed_Cookbook_SE 0:de03cbbcd0ff 491 return setup_error_atribute_not_found(response_buffer, ATT_READ_REQUEST, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 492 }
mbed_Cookbook_SE 0:de03cbbcd0ff 493
mbed_Cookbook_SE 0:de03cbbcd0ff 494 att_update_value_len(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 495
mbed_Cookbook_SE 0:de03cbbcd0ff 496 uint16_t offset = 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 497 // limit data
mbed_Cookbook_SE 0:de03cbbcd0ff 498 if (offset + it.value_len > response_buffer_size) {
mbed_Cookbook_SE 0:de03cbbcd0ff 499 it.value_len = response_buffer_size - 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 500 }
mbed_Cookbook_SE 0:de03cbbcd0ff 501
mbed_Cookbook_SE 0:de03cbbcd0ff 502 // store
mbed_Cookbook_SE 0:de03cbbcd0ff 503 uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len);
mbed_Cookbook_SE 0:de03cbbcd0ff 504 offset += bytes_copied;
mbed_Cookbook_SE 0:de03cbbcd0ff 505
mbed_Cookbook_SE 0:de03cbbcd0ff 506 response_buffer[0] = ATT_READ_RESPONSE;
mbed_Cookbook_SE 0:de03cbbcd0ff 507 return offset;
mbed_Cookbook_SE 0:de03cbbcd0ff 508 }
mbed_Cookbook_SE 0:de03cbbcd0ff 509
mbed_Cookbook_SE 0:de03cbbcd0ff 510 static uint16_t handle_read_request(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 511 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 512 return handle_read_request2(response_buffer, response_buffer_size, READ_BT_16(request_buffer, 1));
mbed_Cookbook_SE 0:de03cbbcd0ff 513 }
mbed_Cookbook_SE 0:de03cbbcd0ff 514
mbed_Cookbook_SE 0:de03cbbcd0ff 515 //
mbed_Cookbook_SE 0:de03cbbcd0ff 516 // MARK: ATT_READ_BLOB_REQUEST 0x0c
mbed_Cookbook_SE 0:de03cbbcd0ff 517 //
mbed_Cookbook_SE 0:de03cbbcd0ff 518 static uint16_t handle_read_blob_request2(uint8_t * response_buffer, uint16_t response_buffer_size, uint16_t handle, uint16_t value_offset){
mbed_Cookbook_SE 0:de03cbbcd0ff 519 log_info("ATT_READ_BLOB_REQUEST: handle %04x, offset %u\n", handle, value_offset);
mbed_Cookbook_SE 0:de03cbbcd0ff 520
mbed_Cookbook_SE 0:de03cbbcd0ff 521 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 522 int ok = att_find_handle(&it, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 523 if (!ok){
mbed_Cookbook_SE 0:de03cbbcd0ff 524 return setup_error_atribute_not_found(response_buffer, ATT_READ_BLOB_REQUEST, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 525 }
mbed_Cookbook_SE 0:de03cbbcd0ff 526
mbed_Cookbook_SE 0:de03cbbcd0ff 527 att_update_value_len(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 528
mbed_Cookbook_SE 0:de03cbbcd0ff 529 if (value_offset >= it.value_len){
mbed_Cookbook_SE 0:de03cbbcd0ff 530 return setup_error_invalid_offset(response_buffer, ATT_READ_BLOB_REQUEST, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 531 }
mbed_Cookbook_SE 0:de03cbbcd0ff 532
mbed_Cookbook_SE 0:de03cbbcd0ff 533 // limit data
mbed_Cookbook_SE 0:de03cbbcd0ff 534 uint16_t offset = 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 535 if (offset + it.value_len - value_offset > response_buffer_size) {
mbed_Cookbook_SE 0:de03cbbcd0ff 536 it.value_len = response_buffer_size - 1 + value_offset;
mbed_Cookbook_SE 0:de03cbbcd0ff 537 }
mbed_Cookbook_SE 0:de03cbbcd0ff 538
mbed_Cookbook_SE 0:de03cbbcd0ff 539 // store
mbed_Cookbook_SE 0:de03cbbcd0ff 540 uint16_t bytes_copied = att_copy_value(&it, value_offset, response_buffer + offset, it.value_len - value_offset);
mbed_Cookbook_SE 0:de03cbbcd0ff 541 offset += bytes_copied;
mbed_Cookbook_SE 0:de03cbbcd0ff 542
mbed_Cookbook_SE 0:de03cbbcd0ff 543 response_buffer[0] = ATT_READ_BLOB_RESPONSE;
mbed_Cookbook_SE 0:de03cbbcd0ff 544 return offset;
mbed_Cookbook_SE 0:de03cbbcd0ff 545 }
mbed_Cookbook_SE 0:de03cbbcd0ff 546
mbed_Cookbook_SE 0:de03cbbcd0ff 547 uint16_t handle_read_blob_request(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 548 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 549 return handle_read_blob_request2(response_buffer, response_buffer_size, READ_BT_16(request_buffer, 1), READ_BT_16(request_buffer, 3));
mbed_Cookbook_SE 0:de03cbbcd0ff 550 }
mbed_Cookbook_SE 0:de03cbbcd0ff 551
mbed_Cookbook_SE 0:de03cbbcd0ff 552 //
mbed_Cookbook_SE 0:de03cbbcd0ff 553 // MARK: ATT_READ_MULTIPLE_REQUEST 0x0e
mbed_Cookbook_SE 0:de03cbbcd0ff 554 //
mbed_Cookbook_SE 0:de03cbbcd0ff 555 static uint16_t handle_read_multiple_request2(uint8_t * response_buffer, uint16_t response_buffer_size, uint16_t num_handles, uint16_t * handles){
mbed_Cookbook_SE 0:de03cbbcd0ff 556 log_info("ATT_READ_MULTIPLE_REQUEST: num handles %u\n", num_handles);
mbed_Cookbook_SE 0:de03cbbcd0ff 557
mbed_Cookbook_SE 0:de03cbbcd0ff 558 uint16_t offset = 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 559
mbed_Cookbook_SE 0:de03cbbcd0ff 560 int i;
mbed_Cookbook_SE 0:de03cbbcd0ff 561 for (i=0;i<num_handles;i++){
mbed_Cookbook_SE 0:de03cbbcd0ff 562 uint16_t handle = handles[i];
mbed_Cookbook_SE 0:de03cbbcd0ff 563
mbed_Cookbook_SE 0:de03cbbcd0ff 564 if (handle == 0){
mbed_Cookbook_SE 0:de03cbbcd0ff 565 return setup_error_invalid_handle(response_buffer, ATT_READ_MULTIPLE_REQUEST, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 566 }
mbed_Cookbook_SE 0:de03cbbcd0ff 567
mbed_Cookbook_SE 0:de03cbbcd0ff 568 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 569
mbed_Cookbook_SE 0:de03cbbcd0ff 570 int ok = att_find_handle(&it, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 571 if (!ok){
mbed_Cookbook_SE 0:de03cbbcd0ff 572 return setup_error_invalid_handle(response_buffer, ATT_READ_MULTIPLE_REQUEST, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 573 }
mbed_Cookbook_SE 0:de03cbbcd0ff 574
mbed_Cookbook_SE 0:de03cbbcd0ff 575 att_update_value_len(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 576
mbed_Cookbook_SE 0:de03cbbcd0ff 577 // limit data
mbed_Cookbook_SE 0:de03cbbcd0ff 578 if (offset + it.value_len > response_buffer_size) {
mbed_Cookbook_SE 0:de03cbbcd0ff 579 it.value_len = response_buffer_size - 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 580 }
mbed_Cookbook_SE 0:de03cbbcd0ff 581
mbed_Cookbook_SE 0:de03cbbcd0ff 582 // store
mbed_Cookbook_SE 0:de03cbbcd0ff 583 uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len);
mbed_Cookbook_SE 0:de03cbbcd0ff 584 offset += bytes_copied;
mbed_Cookbook_SE 0:de03cbbcd0ff 585 }
mbed_Cookbook_SE 0:de03cbbcd0ff 586
mbed_Cookbook_SE 0:de03cbbcd0ff 587 response_buffer[0] = ATT_READ_MULTIPLE_RESPONSE;
mbed_Cookbook_SE 0:de03cbbcd0ff 588 return offset;
mbed_Cookbook_SE 0:de03cbbcd0ff 589 }
mbed_Cookbook_SE 0:de03cbbcd0ff 590 uint16_t handle_read_multiple_request(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 591 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 592 int num_handles = (request_len - 1) >> 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 593 return handle_read_multiple_request2(response_buffer, response_buffer_size, num_handles, (uint16_t*) &request_buffer[1]);
mbed_Cookbook_SE 0:de03cbbcd0ff 594 }
mbed_Cookbook_SE 0:de03cbbcd0ff 595
mbed_Cookbook_SE 0:de03cbbcd0ff 596 //
mbed_Cookbook_SE 0:de03cbbcd0ff 597 // MARK: ATT_READ_BY_GROUP_TYPE_REQUEST 0x10
mbed_Cookbook_SE 0:de03cbbcd0ff 598 //
mbed_Cookbook_SE 0:de03cbbcd0ff 599 // TODO: handle other types then GATT_PRIMARY_SERVICE_UUID and GATT_SECONDARY_SERVICE_UUID
mbed_Cookbook_SE 0:de03cbbcd0ff 600 //
mbed_Cookbook_SE 0:de03cbbcd0ff 601 // NOTE: doesn't handle DYNAMIC values
mbed_Cookbook_SE 0:de03cbbcd0ff 602 //
mbed_Cookbook_SE 0:de03cbbcd0ff 603 static uint16_t handle_read_by_group_type_request2(uint8_t * response_buffer, uint16_t response_buffer_size,
mbed_Cookbook_SE 0:de03cbbcd0ff 604 uint16_t start_handle, uint16_t end_handle,
mbed_Cookbook_SE 0:de03cbbcd0ff 605 uint16_t attribute_type_len, uint8_t * attribute_type){
mbed_Cookbook_SE 0:de03cbbcd0ff 606
mbed_Cookbook_SE 0:de03cbbcd0ff 607 log_info("ATT_READ_BY_GROUP_TYPE_REQUEST: from %04X to %04X, buffer size %u, type: ", start_handle, end_handle, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 608 hexdump2(attribute_type, attribute_type_len);
mbed_Cookbook_SE 0:de03cbbcd0ff 609
mbed_Cookbook_SE 0:de03cbbcd0ff 610 uint16_t offset = 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 611 uint16_t pair_len = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 612 uint16_t in_group = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 613 uint16_t group_start_handle = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 614 uint8_t const * group_start_value = NULL;
mbed_Cookbook_SE 0:de03cbbcd0ff 615 uint16_t prev_handle = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 616
mbed_Cookbook_SE 0:de03cbbcd0ff 617 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 618 att_iterator_init(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 619 while (att_iterator_has_next(&it)){
mbed_Cookbook_SE 0:de03cbbcd0ff 620 att_iterator_fetch_next(&it);
mbed_Cookbook_SE 0:de03cbbcd0ff 621
mbed_Cookbook_SE 0:de03cbbcd0ff 622 if (it.handle && it.handle < start_handle) continue;
mbed_Cookbook_SE 0:de03cbbcd0ff 623 if (it.handle > end_handle) break; // (1)
mbed_Cookbook_SE 0:de03cbbcd0ff 624
mbed_Cookbook_SE 0:de03cbbcd0ff 625 // close current tag, if within a group and a new service definition starts or we reach end of att db
mbed_Cookbook_SE 0:de03cbbcd0ff 626 if (in_group &&
mbed_Cookbook_SE 0:de03cbbcd0ff 627 (it.handle == 0 || att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID))){
mbed_Cookbook_SE 0:de03cbbcd0ff 628 // TODO: check if handle is included in start/end range
mbed_Cookbook_SE 0:de03cbbcd0ff 629 // log_debug("End of group, handle 0x%04x, val_len: %u\n", prev_handle, pair_len - 4);
mbed_Cookbook_SE 0:de03cbbcd0ff 630
mbed_Cookbook_SE 0:de03cbbcd0ff 631 bt_store_16(response_buffer, offset, group_start_handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 632 offset += 2;
mbed_Cookbook_SE 0:de03cbbcd0ff 633 bt_store_16(response_buffer, offset, prev_handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 634 offset += 2;
mbed_Cookbook_SE 0:de03cbbcd0ff 635 memcpy(response_buffer + offset, group_start_value, pair_len - 4);
mbed_Cookbook_SE 0:de03cbbcd0ff 636 offset += pair_len - 4;
mbed_Cookbook_SE 0:de03cbbcd0ff 637 in_group = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 638
mbed_Cookbook_SE 0:de03cbbcd0ff 639 // check if space for another handle pair available
mbed_Cookbook_SE 0:de03cbbcd0ff 640 if (offset + pair_len > response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 641 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 642 }
mbed_Cookbook_SE 0:de03cbbcd0ff 643 }
mbed_Cookbook_SE 0:de03cbbcd0ff 644
mbed_Cookbook_SE 0:de03cbbcd0ff 645 // keep track of previous handle
mbed_Cookbook_SE 0:de03cbbcd0ff 646 prev_handle = it.handle;
mbed_Cookbook_SE 0:de03cbbcd0ff 647
mbed_Cookbook_SE 0:de03cbbcd0ff 648 // does current attribute match
mbed_Cookbook_SE 0:de03cbbcd0ff 649 // log_debug("compare: %04x == %04x\n", *(uint16_t*) context->attribute_type, *(uint16_t*) uuid);
mbed_Cookbook_SE 0:de03cbbcd0ff 650 if (it.handle && att_iterator_match_uuid(&it, attribute_type, attribute_type_len)) {
mbed_Cookbook_SE 0:de03cbbcd0ff 651
mbed_Cookbook_SE 0:de03cbbcd0ff 652 // check if value has same len as last one
mbed_Cookbook_SE 0:de03cbbcd0ff 653 uint16_t this_pair_len = 4 + it.value_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 654 if (offset > 1){
mbed_Cookbook_SE 0:de03cbbcd0ff 655 if (this_pair_len != pair_len) {
mbed_Cookbook_SE 0:de03cbbcd0ff 656 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 657 }
mbed_Cookbook_SE 0:de03cbbcd0ff 658 }
mbed_Cookbook_SE 0:de03cbbcd0ff 659
mbed_Cookbook_SE 0:de03cbbcd0ff 660 // log_debug("Begin of group, handle 0x%04x\n", it.handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 661
mbed_Cookbook_SE 0:de03cbbcd0ff 662 // first
mbed_Cookbook_SE 0:de03cbbcd0ff 663 if (offset == 1) {
mbed_Cookbook_SE 0:de03cbbcd0ff 664 pair_len = this_pair_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 665 response_buffer[offset] = this_pair_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 666 offset++;
mbed_Cookbook_SE 0:de03cbbcd0ff 667 }
mbed_Cookbook_SE 0:de03cbbcd0ff 668
mbed_Cookbook_SE 0:de03cbbcd0ff 669 group_start_handle = it.handle;
mbed_Cookbook_SE 0:de03cbbcd0ff 670 group_start_value = it.value;
mbed_Cookbook_SE 0:de03cbbcd0ff 671 in_group = 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 672 }
mbed_Cookbook_SE 0:de03cbbcd0ff 673 }
mbed_Cookbook_SE 0:de03cbbcd0ff 674
mbed_Cookbook_SE 0:de03cbbcd0ff 675 if (offset == 1){
mbed_Cookbook_SE 0:de03cbbcd0ff 676 return setup_error_atribute_not_found(response_buffer, ATT_READ_BY_GROUP_TYPE_REQUEST, start_handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 677 }
mbed_Cookbook_SE 0:de03cbbcd0ff 678
mbed_Cookbook_SE 0:de03cbbcd0ff 679 response_buffer[0] = ATT_READ_BY_GROUP_TYPE_RESPONSE;
mbed_Cookbook_SE 0:de03cbbcd0ff 680 return offset;
mbed_Cookbook_SE 0:de03cbbcd0ff 681 }
mbed_Cookbook_SE 0:de03cbbcd0ff 682 uint16_t handle_read_by_group_type_request(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 683 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 684 int attribute_type_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 685 if (request_len <= 7){
mbed_Cookbook_SE 0:de03cbbcd0ff 686 attribute_type_len = 2;
mbed_Cookbook_SE 0:de03cbbcd0ff 687 } else {
mbed_Cookbook_SE 0:de03cbbcd0ff 688 attribute_type_len = 16;
mbed_Cookbook_SE 0:de03cbbcd0ff 689 }
mbed_Cookbook_SE 0:de03cbbcd0ff 690 return handle_read_by_group_type_request2(response_buffer, response_buffer_size, READ_BT_16(request_buffer, 1), READ_BT_16(request_buffer, 3), attribute_type_len, &request_buffer[5]);
mbed_Cookbook_SE 0:de03cbbcd0ff 691 }
mbed_Cookbook_SE 0:de03cbbcd0ff 692
mbed_Cookbook_SE 0:de03cbbcd0ff 693 //
mbed_Cookbook_SE 0:de03cbbcd0ff 694 // MARK: ATT_WRITE_REQUEST 0x12
mbed_Cookbook_SE 0:de03cbbcd0ff 695 static uint16_t handle_write_request(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 696 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 697 uint16_t handle = READ_BT_16(request_buffer, 1);
mbed_Cookbook_SE 0:de03cbbcd0ff 698 if (!att_write_callback) {
mbed_Cookbook_SE 0:de03cbbcd0ff 699 // TODO: Use "Write Not Permitted"
mbed_Cookbook_SE 0:de03cbbcd0ff 700 return setup_error_atribute_not_found(response_buffer, ATT_WRITE_REQUEST, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 701 }
mbed_Cookbook_SE 0:de03cbbcd0ff 702 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 703 int ok = att_find_handle(&it, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 704 if (!ok) {
mbed_Cookbook_SE 0:de03cbbcd0ff 705 return setup_error_atribute_not_found(response_buffer, ATT_WRITE_REQUEST, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 706 }
mbed_Cookbook_SE 0:de03cbbcd0ff 707 if ((it.flags & ATT_PROPERTY_DYNAMIC) == 0) {
mbed_Cookbook_SE 0:de03cbbcd0ff 708 // TODO: Use "Write Not Permitted"
mbed_Cookbook_SE 0:de03cbbcd0ff 709 return setup_error_atribute_not_found(response_buffer, ATT_WRITE_REQUEST, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 710 }
mbed_Cookbook_SE 0:de03cbbcd0ff 711 (*att_write_callback)(handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3, NULL);
mbed_Cookbook_SE 0:de03cbbcd0ff 712 response_buffer[0] = ATT_WRITE_RESPONSE;
mbed_Cookbook_SE 0:de03cbbcd0ff 713 return 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 714 }
mbed_Cookbook_SE 0:de03cbbcd0ff 715
mbed_Cookbook_SE 0:de03cbbcd0ff 716 //
mbed_Cookbook_SE 0:de03cbbcd0ff 717 // MARK: ATT_PREPARE_WRITE_REQUEST 0x16
mbed_Cookbook_SE 0:de03cbbcd0ff 718 static uint16_t handle_prepare_write_request(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 719 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 720 uint16_t handle = READ_BT_16(request_buffer, 1);
mbed_Cookbook_SE 0:de03cbbcd0ff 721 if (!att_write_callback) {
mbed_Cookbook_SE 0:de03cbbcd0ff 722 // TODO: Use "Write Not Permitted"
mbed_Cookbook_SE 0:de03cbbcd0ff 723 return setup_error_atribute_not_found(response_buffer, ATT_PREPARE_WRITE_REQUEST, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 724 }
mbed_Cookbook_SE 0:de03cbbcd0ff 725 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 726 int ok = att_find_handle(&it, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 727 if (!ok) {
mbed_Cookbook_SE 0:de03cbbcd0ff 728 return setup_error_atribute_not_found(response_buffer, ATT_WRITE_REQUEST, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 729 }
mbed_Cookbook_SE 0:de03cbbcd0ff 730 if ((it.flags & ATT_PROPERTY_DYNAMIC) == 0) {
mbed_Cookbook_SE 0:de03cbbcd0ff 731 // TODO: Use "Write Not Permitted"
mbed_Cookbook_SE 0:de03cbbcd0ff 732 return setup_error_atribute_not_found(response_buffer, ATT_WRITE_REQUEST, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 733 }
mbed_Cookbook_SE 0:de03cbbcd0ff 734 (*att_write_callback)(handle, ATT_TRANSACTION_MODE_ACTIVE, 0, request_buffer + 3, request_len - 3, NULL);
mbed_Cookbook_SE 0:de03cbbcd0ff 735
mbed_Cookbook_SE 0:de03cbbcd0ff 736 // response: echo request
mbed_Cookbook_SE 0:de03cbbcd0ff 737 memcpy(response_buffer, request_buffer, request_len);
mbed_Cookbook_SE 0:de03cbbcd0ff 738 response_buffer[0] = ATT_PREPARE_WRITE_RESPONSE;
mbed_Cookbook_SE 0:de03cbbcd0ff 739 return request_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 740 }
mbed_Cookbook_SE 0:de03cbbcd0ff 741
mbed_Cookbook_SE 0:de03cbbcd0ff 742 // MARK: ATT_EXECUTE_WRITE_REQUEST 0x18
mbed_Cookbook_SE 0:de03cbbcd0ff 743 static uint16_t handle_execute_write_request(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 744 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 745 if (!att_write_callback) {
mbed_Cookbook_SE 0:de03cbbcd0ff 746 // TODO: Use "Write Not Permitted"
mbed_Cookbook_SE 0:de03cbbcd0ff 747 return setup_error_atribute_not_found(response_buffer, ATT_EXECUTE_WRITE_REQUEST, 0);
mbed_Cookbook_SE 0:de03cbbcd0ff 748 }
mbed_Cookbook_SE 0:de03cbbcd0ff 749 if (request_buffer[1]) {
mbed_Cookbook_SE 0:de03cbbcd0ff 750 (*att_write_callback)(0, ATT_TRANSACTION_MODE_EXECUTE, 0, request_buffer + 3, request_len - 3, NULL);
mbed_Cookbook_SE 0:de03cbbcd0ff 751 } else {
mbed_Cookbook_SE 0:de03cbbcd0ff 752 (*att_write_callback)(0, ATT_TRANSACTION_MODE_CANCEL, 0, request_buffer + 3, request_len - 3, NULL);
mbed_Cookbook_SE 0:de03cbbcd0ff 753 }
mbed_Cookbook_SE 0:de03cbbcd0ff 754 response_buffer[0] = ATT_EXECUTE_WRITE_RESPONSE;
mbed_Cookbook_SE 0:de03cbbcd0ff 755 return 1;
mbed_Cookbook_SE 0:de03cbbcd0ff 756 }
mbed_Cookbook_SE 0:de03cbbcd0ff 757
mbed_Cookbook_SE 0:de03cbbcd0ff 758 // MARK: ATT_WRITE_COMMAND 0x52
mbed_Cookbook_SE 0:de03cbbcd0ff 759 static void handle_write_command(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 760 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 761 if (!att_write_callback) return;
mbed_Cookbook_SE 0:de03cbbcd0ff 762 uint16_t handle = READ_BT_16(request_buffer, 1);
mbed_Cookbook_SE 0:de03cbbcd0ff 763 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 764 int ok = att_find_handle(&it, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 765 if (!ok) return;
mbed_Cookbook_SE 0:de03cbbcd0ff 766 if ((it.flags & ATT_PROPERTY_DYNAMIC) == 0) return;
mbed_Cookbook_SE 0:de03cbbcd0ff 767 (*att_write_callback)(handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3, NULL);
mbed_Cookbook_SE 0:de03cbbcd0ff 768 }
mbed_Cookbook_SE 0:de03cbbcd0ff 769
mbed_Cookbook_SE 0:de03cbbcd0ff 770 // MARK: ATT_SIGNED_WRITE_COMAND 0xD2
mbed_Cookbook_SE 0:de03cbbcd0ff 771 static void handle_signed_write_command(uint8_t * request_buffer, uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 772 uint8_t * response_buffer, uint16_t response_buffer_size){
mbed_Cookbook_SE 0:de03cbbcd0ff 773
mbed_Cookbook_SE 0:de03cbbcd0ff 774 if (request_len < 15) return;
mbed_Cookbook_SE 0:de03cbbcd0ff 775 if (!att_write_callback) return;
mbed_Cookbook_SE 0:de03cbbcd0ff 776 uint16_t handle = READ_BT_16(request_buffer, 1);
mbed_Cookbook_SE 0:de03cbbcd0ff 777 att_iterator_t it;
mbed_Cookbook_SE 0:de03cbbcd0ff 778 int ok = att_find_handle(&it, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 779 if (!ok) return;
mbed_Cookbook_SE 0:de03cbbcd0ff 780 if ((it.flags & ATT_PROPERTY_DYNAMIC) == 0) return;
mbed_Cookbook_SE 0:de03cbbcd0ff 781 (*att_write_callback)(handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3 - 12, (signature_t *) request_buffer + request_len - 12);
mbed_Cookbook_SE 0:de03cbbcd0ff 782 }
mbed_Cookbook_SE 0:de03cbbcd0ff 783
mbed_Cookbook_SE 0:de03cbbcd0ff 784 // MARK: helper for ATT_HANDLE_VALUE_NOTIFICATION and ATT_HANDLE_VALUE_INDICATION
mbed_Cookbook_SE 0:de03cbbcd0ff 785 static uint16_t prepare_handle_value(att_connection_t * att_connection,
mbed_Cookbook_SE 0:de03cbbcd0ff 786 uint16_t handle,
mbed_Cookbook_SE 0:de03cbbcd0ff 787 uint8_t *value,
mbed_Cookbook_SE 0:de03cbbcd0ff 788 uint16_t value_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 789 uint8_t * response_buffer){
mbed_Cookbook_SE 0:de03cbbcd0ff 790 bt_store_16(response_buffer, 1, handle);
mbed_Cookbook_SE 0:de03cbbcd0ff 791 if (value_len > att_connection->mtu - 3){
mbed_Cookbook_SE 0:de03cbbcd0ff 792 value_len = att_connection->mtu - 3;
mbed_Cookbook_SE 0:de03cbbcd0ff 793 }
mbed_Cookbook_SE 0:de03cbbcd0ff 794 memcpy(&response_buffer[3], value, value_len);
mbed_Cookbook_SE 0:de03cbbcd0ff 795 return value_len + 3;
mbed_Cookbook_SE 0:de03cbbcd0ff 796 }
mbed_Cookbook_SE 0:de03cbbcd0ff 797
mbed_Cookbook_SE 0:de03cbbcd0ff 798 // MARK: ATT_HANDLE_VALUE_NOTIFICATION 0x1b
mbed_Cookbook_SE 0:de03cbbcd0ff 799 uint16_t att_prepare_handle_value_notification(att_connection_t * att_connection,
mbed_Cookbook_SE 0:de03cbbcd0ff 800 uint16_t handle,
mbed_Cookbook_SE 0:de03cbbcd0ff 801 uint8_t *value,
mbed_Cookbook_SE 0:de03cbbcd0ff 802 uint16_t value_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 803 uint8_t * response_buffer){
mbed_Cookbook_SE 0:de03cbbcd0ff 804
mbed_Cookbook_SE 0:de03cbbcd0ff 805 response_buffer[0] = ATT_HANDLE_VALUE_NOTIFICATION;
mbed_Cookbook_SE 0:de03cbbcd0ff 806 return prepare_handle_value(att_connection, handle, value, value_len, response_buffer);
mbed_Cookbook_SE 0:de03cbbcd0ff 807 }
mbed_Cookbook_SE 0:de03cbbcd0ff 808
mbed_Cookbook_SE 0:de03cbbcd0ff 809 // MARK: ATT_HANDLE_VALUE_INDICATION 0x1d
mbed_Cookbook_SE 0:de03cbbcd0ff 810 uint16_t att_prepare_handle_value_indication(att_connection_t * att_connection,
mbed_Cookbook_SE 0:de03cbbcd0ff 811 uint16_t handle,
mbed_Cookbook_SE 0:de03cbbcd0ff 812 uint8_t *value,
mbed_Cookbook_SE 0:de03cbbcd0ff 813 uint16_t value_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 814 uint8_t * response_buffer){
mbed_Cookbook_SE 0:de03cbbcd0ff 815
mbed_Cookbook_SE 0:de03cbbcd0ff 816 response_buffer[0] = ATT_HANDLE_VALUE_INDICATION;
mbed_Cookbook_SE 0:de03cbbcd0ff 817 return prepare_handle_value(att_connection, handle, value, value_len, response_buffer);
mbed_Cookbook_SE 0:de03cbbcd0ff 818 }
mbed_Cookbook_SE 0:de03cbbcd0ff 819
mbed_Cookbook_SE 0:de03cbbcd0ff 820 // MARK: Dispatcher
mbed_Cookbook_SE 0:de03cbbcd0ff 821 uint16_t att_handle_request(att_connection_t * att_connection,
mbed_Cookbook_SE 0:de03cbbcd0ff 822 uint8_t * request_buffer,
mbed_Cookbook_SE 0:de03cbbcd0ff 823 uint16_t request_len,
mbed_Cookbook_SE 0:de03cbbcd0ff 824 uint8_t * response_buffer){
mbed_Cookbook_SE 0:de03cbbcd0ff 825 uint16_t response_len = 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 826 uint16_t response_buffer_size = att_connection->mtu;
mbed_Cookbook_SE 0:de03cbbcd0ff 827
mbed_Cookbook_SE 0:de03cbbcd0ff 828 switch (request_buffer[0]){
mbed_Cookbook_SE 0:de03cbbcd0ff 829 case ATT_EXCHANGE_MTU_REQUEST:
mbed_Cookbook_SE 0:de03cbbcd0ff 830 response_len = handle_exchange_mtu_request(att_connection, request_buffer, request_len, response_buffer);
mbed_Cookbook_SE 0:de03cbbcd0ff 831 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 832 case ATT_FIND_INFORMATION_REQUEST:
mbed_Cookbook_SE 0:de03cbbcd0ff 833 response_len = handle_find_information_request(request_buffer, request_len,response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 834 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 835 case ATT_FIND_BY_TYPE_VALUE_REQUEST:
mbed_Cookbook_SE 0:de03cbbcd0ff 836 response_len = handle_find_by_type_value_request(request_buffer, request_len, response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 837 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 838 case ATT_READ_BY_TYPE_REQUEST:
mbed_Cookbook_SE 0:de03cbbcd0ff 839 response_len = handle_read_by_type_request(request_buffer, request_len, response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 840 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 841 case ATT_READ_REQUEST:
mbed_Cookbook_SE 0:de03cbbcd0ff 842 response_len = handle_read_request(request_buffer, request_len, response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 843 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 844 case ATT_READ_BLOB_REQUEST:
mbed_Cookbook_SE 0:de03cbbcd0ff 845 response_len = handle_read_blob_request(request_buffer, request_len, response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 846 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 847 case ATT_READ_MULTIPLE_REQUEST:
mbed_Cookbook_SE 0:de03cbbcd0ff 848 response_len = handle_read_multiple_request(request_buffer, request_len, response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 849 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 850 case ATT_READ_BY_GROUP_TYPE_REQUEST:
mbed_Cookbook_SE 0:de03cbbcd0ff 851 response_len = handle_read_by_group_type_request(request_buffer, request_len, response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 852 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 853 case ATT_WRITE_REQUEST:
mbed_Cookbook_SE 0:de03cbbcd0ff 854 response_len = handle_write_request(request_buffer, request_len, response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 855 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 856 case ATT_PREPARE_WRITE_REQUEST:
mbed_Cookbook_SE 0:de03cbbcd0ff 857 response_len = handle_prepare_write_request(request_buffer, request_len, response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 858 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 859 case ATT_EXECUTE_WRITE_REQUEST:
mbed_Cookbook_SE 0:de03cbbcd0ff 860 response_len = handle_execute_write_request(request_buffer, request_len, response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 861 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 862 case ATT_WRITE_COMMAND:
mbed_Cookbook_SE 0:de03cbbcd0ff 863 handle_write_command(request_buffer, request_len, response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 864 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 865 case ATT_SIGNED_WRITE_COMAND:
mbed_Cookbook_SE 0:de03cbbcd0ff 866 handle_signed_write_command(request_buffer, request_len, response_buffer, response_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 867 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 868 default:
mbed_Cookbook_SE 0:de03cbbcd0ff 869 log_info("Unhandled ATT Command: %02X, DATA: ", request_buffer[0]);
mbed_Cookbook_SE 0:de03cbbcd0ff 870 hexdump2(&request_buffer[9], request_len-9);
mbed_Cookbook_SE 0:de03cbbcd0ff 871 break;
mbed_Cookbook_SE 0:de03cbbcd0ff 872 }
mbed_Cookbook_SE 0:de03cbbcd0ff 873 return response_len;
mbed_Cookbook_SE 0:de03cbbcd0ff 874 }
mbed_Cookbook_SE 0:de03cbbcd0ff 875
mbed_Cookbook_SE 0:de03cbbcd0ff 876 #if 0
mbed_Cookbook_SE 0:de03cbbcd0ff 877
mbed_Cookbook_SE 0:de03cbbcd0ff 878 // test profile
mbed_Cookbook_SE 0:de03cbbcd0ff 879 #include "profile.h"
mbed_Cookbook_SE 0:de03cbbcd0ff 880
mbed_Cookbook_SE 0:de03cbbcd0ff 881 int main(){
mbed_Cookbook_SE 0:de03cbbcd0ff 882 int acl_buffer_size;
mbed_Cookbook_SE 0:de03cbbcd0ff 883 uint8_t acl_buffer[27];
mbed_Cookbook_SE 0:de03cbbcd0ff 884 att_set_db(profile_data);
mbed_Cookbook_SE 0:de03cbbcd0ff 885 att_dump_attributes();
mbed_Cookbook_SE 0:de03cbbcd0ff 886
mbed_Cookbook_SE 0:de03cbbcd0ff 887 uint8_t uuid_1[] = { 0x00, 0x18};
mbed_Cookbook_SE 0:de03cbbcd0ff 888 acl_buffer_size = handle_find_by_type_value_request2(acl_buffer, 19, 0, 0xffff, 0x2800, 2, (uint8_t *) &uuid_1);
mbed_Cookbook_SE 0:de03cbbcd0ff 889 hexdump2(acl_buffer, acl_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 890
mbed_Cookbook_SE 0:de03cbbcd0ff 891 uint8_t uuid_3[] = { 0x00, 0x2a};
mbed_Cookbook_SE 0:de03cbbcd0ff 892 acl_buffer_size = handle_read_by_type_request2(acl_buffer, 19, 0, 0xffff, 2, (uint8_t *) &uuid_3);
mbed_Cookbook_SE 0:de03cbbcd0ff 893 hexdump2(acl_buffer, acl_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 894
mbed_Cookbook_SE 0:de03cbbcd0ff 895 acl_buffer_size = handle_find_by_type_value_request2(acl_buffer, 19, 0, 0xffff, 0x2800, 2, (uint8_t *) &uuid_1);
mbed_Cookbook_SE 0:de03cbbcd0ff 896 hexdump2(acl_buffer, acl_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 897
mbed_Cookbook_SE 0:de03cbbcd0ff 898 uint8_t uuid_4[] = { 0x00, 0x28};
mbed_Cookbook_SE 0:de03cbbcd0ff 899 acl_buffer_size = handle_read_by_group_type_request2(acl_buffer, 20, 0, 0xffff, 2, (uint8_t *) &uuid_4);
mbed_Cookbook_SE 0:de03cbbcd0ff 900 hexdump2(acl_buffer, acl_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 901
mbed_Cookbook_SE 0:de03cbbcd0ff 902 acl_buffer_size = handle_find_information_request2(acl_buffer, 20, 0, 0xffff);
mbed_Cookbook_SE 0:de03cbbcd0ff 903 hexdump2(acl_buffer, acl_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 904 acl_buffer_size = handle_find_information_request2(acl_buffer, 20, 3, 0xffff);
mbed_Cookbook_SE 0:de03cbbcd0ff 905 hexdump2(acl_buffer, acl_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 906 acl_buffer_size = handle_find_information_request2(acl_buffer, 20, 5, 0xffff);
mbed_Cookbook_SE 0:de03cbbcd0ff 907 hexdump2(acl_buffer, acl_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 908
mbed_Cookbook_SE 0:de03cbbcd0ff 909 acl_buffer_size = handle_read_request2(acl_buffer, 19, 0x0003);
mbed_Cookbook_SE 0:de03cbbcd0ff 910 hexdump2(acl_buffer, acl_buffer_size);
mbed_Cookbook_SE 0:de03cbbcd0ff 911
mbed_Cookbook_SE 0:de03cbbcd0ff 912 return 0;
mbed_Cookbook_SE 0:de03cbbcd0ff 913 }
mbed_Cookbook_SE 0:de03cbbcd0ff 914 #endif