JBBoardに接続したモーター2つをRCBControllerでコントロールするテストです。

Dependencies:   FatFileSystem TB6612FNG2 mbed

Fork of JBB_BTLE_Test by Jksoft Blue mbed Board Developer

Committer:
todotani
Date:
Thu Feb 07 14:01:01 2013 +0000
Revision:
1:6078e430af82
Child:
6:cf06ba884429
BLE demo for mbed; Ported SBDBT (RunningElectronics) firmware for BLE to mbed. It can communicate with iOS

Who changed what in which revision?

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