BTstack for Nucleo F401RE/FRDM-KL46Z example program

Dependencies:   F401RE-USBHost mbed

The usage is the same as KL46Z-BTstack_example.
使い方はKL46Z-BTstack_exampleと同じです。
/media/uploads/va009039/f401re-btstack.jpg

Committer:
va009039
Date:
Mon Jun 09 09:03:25 2014 +0000
Revision:
0:a05a07cd6fdf
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:a05a07cd6fdf 1 /*
va009039 0:a05a07cd6fdf 2 * Copyright (C) 2009-2012 by Matthias Ringwald
va009039 0:a05a07cd6fdf 3 *
va009039 0:a05a07cd6fdf 4 * Redistribution and use in source and binary forms, with or without
va009039 0:a05a07cd6fdf 5 * modification, are permitted provided that the following conditions
va009039 0:a05a07cd6fdf 6 * are met:
va009039 0:a05a07cd6fdf 7 *
va009039 0:a05a07cd6fdf 8 * 1. Redistributions of source code must retain the above copyright
va009039 0:a05a07cd6fdf 9 * notice, this list of conditions and the following disclaimer.
va009039 0:a05a07cd6fdf 10 * 2. Redistributions in binary form must reproduce the above copyright
va009039 0:a05a07cd6fdf 11 * notice, this list of conditions and the following disclaimer in the
va009039 0:a05a07cd6fdf 12 * documentation and/or other materials provided with the distribution.
va009039 0:a05a07cd6fdf 13 * 3. Neither the name of the copyright holders nor the names of
va009039 0:a05a07cd6fdf 14 * contributors may be used to endorse or promote products derived
va009039 0:a05a07cd6fdf 15 * from this software without specific prior written permission.
va009039 0:a05a07cd6fdf 16 * 4. Any redistribution, use, or modification is done solely for
va009039 0:a05a07cd6fdf 17 * personal benefit and not for any commercial purpose or for
va009039 0:a05a07cd6fdf 18 * monetary gain.
va009039 0:a05a07cd6fdf 19 *
va009039 0:a05a07cd6fdf 20 * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
va009039 0:a05a07cd6fdf 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
va009039 0:a05a07cd6fdf 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
va009039 0:a05a07cd6fdf 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
va009039 0:a05a07cd6fdf 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
va009039 0:a05a07cd6fdf 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
va009039 0:a05a07cd6fdf 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
va009039 0:a05a07cd6fdf 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
va009039 0:a05a07cd6fdf 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
va009039 0:a05a07cd6fdf 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
va009039 0:a05a07cd6fdf 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
va009039 0:a05a07cd6fdf 31 * SUCH DAMAGE.
va009039 0:a05a07cd6fdf 32 *
va009039 0:a05a07cd6fdf 33 * Please inquire about commercial licensing options at btstack@ringwald.ch
va009039 0:a05a07cd6fdf 34 *
va009039 0:a05a07cd6fdf 35 */
va009039 0:a05a07cd6fdf 36
va009039 0:a05a07cd6fdf 37 /*
va009039 0:a05a07cd6fdf 38 * Implementation of the Service Discovery Protocol Server
va009039 0:a05a07cd6fdf 39 */
va009039 0:a05a07cd6fdf 40
va009039 0:a05a07cd6fdf 41 #include "sdp.h"
va009039 0:a05a07cd6fdf 42
va009039 0:a05a07cd6fdf 43
va009039 0:a05a07cd6fdf 44 #include <stdio.h>
va009039 0:a05a07cd6fdf 45 #include <string.h>
va009039 0:a05a07cd6fdf 46
va009039 0:a05a07cd6fdf 47 #include <btstack/sdp_util.h>
va009039 0:a05a07cd6fdf 48
va009039 0:a05a07cd6fdf 49 #include "hci_dump.h"
va009039 0:a05a07cd6fdf 50 #include "l2cap.h"
va009039 0:a05a07cd6fdf 51
va009039 0:a05a07cd6fdf 52 #include "debug.h"
va009039 0:a05a07cd6fdf 53
va009039 0:a05a07cd6fdf 54 // max reserved ServiceRecordHandle
va009039 0:a05a07cd6fdf 55 #define maxReservedServiceRecordHandle 0xffff
va009039 0:a05a07cd6fdf 56
va009039 0:a05a07cd6fdf 57 // max SDP response
va009039 0:a05a07cd6fdf 58 #define SDP_RESPONSE_BUFFER_SIZE (HCI_ACL_BUFFER_SIZE-HCI_ACL_HEADER_SIZE)
va009039 0:a05a07cd6fdf 59
va009039 0:a05a07cd6fdf 60 static void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
va009039 0:a05a07cd6fdf 61
va009039 0:a05a07cd6fdf 62 // registered service records
va009039 0:a05a07cd6fdf 63 static linked_list_t sdp_service_records = NULL;
va009039 0:a05a07cd6fdf 64
va009039 0:a05a07cd6fdf 65 // our handles start after the reserved range
va009039 0:a05a07cd6fdf 66 static uint32_t sdp_next_service_record_handle = maxReservedServiceRecordHandle + 2;
va009039 0:a05a07cd6fdf 67
va009039 0:a05a07cd6fdf 68 static uint8_t sdp_response_buffer[SDP_RESPONSE_BUFFER_SIZE];
va009039 0:a05a07cd6fdf 69
va009039 0:a05a07cd6fdf 70 static void (*app_packet_handler)(void * connection, uint8_t packet_type,
va009039 0:a05a07cd6fdf 71 uint16_t channel, uint8_t *packet, uint16_t size) = NULL;
va009039 0:a05a07cd6fdf 72
va009039 0:a05a07cd6fdf 73 static uint16_t l2cap_cid = 0;
va009039 0:a05a07cd6fdf 74 static uint16_t sdp_response_size = 0;
va009039 0:a05a07cd6fdf 75
va009039 0:a05a07cd6fdf 76 void sdp_init(){
va009039 0:a05a07cd6fdf 77 // register with l2cap psm sevices - max MTU
va009039 0:a05a07cd6fdf 78 l2cap_register_service_internal(NULL, sdp_packet_handler, PSM_SDP, 0xffff);
va009039 0:a05a07cd6fdf 79 }
va009039 0:a05a07cd6fdf 80
va009039 0:a05a07cd6fdf 81 // register packet handler
va009039 0:a05a07cd6fdf 82 void sdp_register_packet_handler(void (*handler)(void * connection, uint8_t packet_type,
va009039 0:a05a07cd6fdf 83 uint16_t channel, uint8_t *packet, uint16_t size)){
va009039 0:a05a07cd6fdf 84 app_packet_handler = handler;
va009039 0:a05a07cd6fdf 85 l2cap_cid = 0;
va009039 0:a05a07cd6fdf 86 }
va009039 0:a05a07cd6fdf 87
va009039 0:a05a07cd6fdf 88 uint32_t sdp_get_service_record_handle(uint8_t * record){
va009039 0:a05a07cd6fdf 89 uint8_t * serviceRecordHandleAttribute = sdp_get_attribute_value_for_attribute_id(record, SDP_ServiceRecordHandle);
va009039 0:a05a07cd6fdf 90 if (!serviceRecordHandleAttribute) return 0;
va009039 0:a05a07cd6fdf 91 if (de_get_element_type(serviceRecordHandleAttribute) != DE_UINT) return 0;
va009039 0:a05a07cd6fdf 92 if (de_get_size_type(serviceRecordHandleAttribute) != DE_SIZE_32) return 0;
va009039 0:a05a07cd6fdf 93 return READ_NET_32(serviceRecordHandleAttribute, 1);
va009039 0:a05a07cd6fdf 94 }
va009039 0:a05a07cd6fdf 95
va009039 0:a05a07cd6fdf 96 // data: event(8), len(8), status(8), service_record_handle(32)
va009039 0:a05a07cd6fdf 97 static void sdp_emit_service_registered(void *connection, uint32_t handle, uint8_t status) {
va009039 0:a05a07cd6fdf 98 if (!app_packet_handler) return;
va009039 0:a05a07cd6fdf 99 uint8_t event[7];
va009039 0:a05a07cd6fdf 100 event[0] = SDP_SERVICE_REGISTERED;
va009039 0:a05a07cd6fdf 101 event[1] = sizeof(event) - 2;
va009039 0:a05a07cd6fdf 102 event[2] = status;
va009039 0:a05a07cd6fdf 103 bt_store_32(event, 3, handle);
va009039 0:a05a07cd6fdf 104 hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
va009039 0:a05a07cd6fdf 105 (*app_packet_handler)(connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
va009039 0:a05a07cd6fdf 106 }
va009039 0:a05a07cd6fdf 107
va009039 0:a05a07cd6fdf 108 service_record_item_t * sdp_get_record_for_handle(uint32_t handle){
va009039 0:a05a07cd6fdf 109 linked_item_t *it;
va009039 0:a05a07cd6fdf 110 for (it = (linked_item_t *) sdp_service_records; it ; it = it->next){
va009039 0:a05a07cd6fdf 111 service_record_item_t * item = (service_record_item_t *) it;
va009039 0:a05a07cd6fdf 112 if (item->service_record_handle == handle){
va009039 0:a05a07cd6fdf 113 return item;
va009039 0:a05a07cd6fdf 114 }
va009039 0:a05a07cd6fdf 115 }
va009039 0:a05a07cd6fdf 116 return NULL;
va009039 0:a05a07cd6fdf 117 }
va009039 0:a05a07cd6fdf 118
va009039 0:a05a07cd6fdf 119 // get next free, unregistered service record handle
va009039 0:a05a07cd6fdf 120 uint32_t sdp_create_service_record_handle(void){
va009039 0:a05a07cd6fdf 121 uint32_t handle = 0;
va009039 0:a05a07cd6fdf 122 do {
va009039 0:a05a07cd6fdf 123 handle = sdp_next_service_record_handle++;
va009039 0:a05a07cd6fdf 124 if (sdp_get_record_for_handle(handle)) handle = 0;
va009039 0:a05a07cd6fdf 125 } while (handle == 0);
va009039 0:a05a07cd6fdf 126 return handle;
va009039 0:a05a07cd6fdf 127 }
va009039 0:a05a07cd6fdf 128
va009039 0:a05a07cd6fdf 129 #ifdef EMBEDDED
va009039 0:a05a07cd6fdf 130
va009039 0:a05a07cd6fdf 131 // register service record internally - this special version doesn't copy the record, it should not be freeed
va009039 0:a05a07cd6fdf 132 // pre: AttributeIDs are in ascending order
va009039 0:a05a07cd6fdf 133 // pre: ServiceRecordHandle is first attribute and valid
va009039 0:a05a07cd6fdf 134 // pre: record
va009039 0:a05a07cd6fdf 135 // @returns ServiceRecordHandle or 0 if registration failed
va009039 0:a05a07cd6fdf 136 uint32_t sdp_register_service_internal(void *connection, service_record_item_t * record_item){
va009039 0:a05a07cd6fdf 137 // get user record handle
va009039 0:a05a07cd6fdf 138 uint32_t record_handle = record_item->service_record_handle;
va009039 0:a05a07cd6fdf 139 // get actual record
va009039 0:a05a07cd6fdf 140 uint8_t *record = record_item->service_record;
va009039 0:a05a07cd6fdf 141
va009039 0:a05a07cd6fdf 142 // check for ServiceRecordHandle attribute, returns pointer or null
va009039 0:a05a07cd6fdf 143 uint8_t * req_record_handle = sdp_get_attribute_value_for_attribute_id(record, SDP_ServiceRecordHandle);
va009039 0:a05a07cd6fdf 144 if (!req_record_handle) {
va009039 0:a05a07cd6fdf 145 log_error("SDP Error - record does not contain ServiceRecordHandle attribute\n");
va009039 0:a05a07cd6fdf 146 return 0;
va009039 0:a05a07cd6fdf 147 }
va009039 0:a05a07cd6fdf 148
va009039 0:a05a07cd6fdf 149 // validate service record handle is not in reserved range
va009039 0:a05a07cd6fdf 150 if (record_handle <= maxReservedServiceRecordHandle) record_handle = 0;
va009039 0:a05a07cd6fdf 151
va009039 0:a05a07cd6fdf 152 // check if already in use
va009039 0:a05a07cd6fdf 153 if (record_handle) {
va009039 0:a05a07cd6fdf 154 if (sdp_get_record_for_handle(record_handle)) {
va009039 0:a05a07cd6fdf 155 record_handle = 0;
va009039 0:a05a07cd6fdf 156 }
va009039 0:a05a07cd6fdf 157 }
va009039 0:a05a07cd6fdf 158
va009039 0:a05a07cd6fdf 159 // create new handle if needed
va009039 0:a05a07cd6fdf 160 if (!record_handle){
va009039 0:a05a07cd6fdf 161 record_handle = sdp_create_service_record_handle();
va009039 0:a05a07cd6fdf 162 // Write the handle back into the record too
va009039 0:a05a07cd6fdf 163 record_item->service_record_handle = record_handle;
va009039 0:a05a07cd6fdf 164 sdp_set_attribute_value_for_attribute_id(record, SDP_ServiceRecordHandle, record_handle);
va009039 0:a05a07cd6fdf 165 }
va009039 0:a05a07cd6fdf 166
va009039 0:a05a07cd6fdf 167 // add to linked list
va009039 0:a05a07cd6fdf 168 linked_list_add(&sdp_service_records, (linked_item_t *) record_item);
va009039 0:a05a07cd6fdf 169
va009039 0:a05a07cd6fdf 170 sdp_emit_service_registered(connection, 0, record_item->service_record_handle);
va009039 0:a05a07cd6fdf 171
va009039 0:a05a07cd6fdf 172 return record_handle;
va009039 0:a05a07cd6fdf 173 }
va009039 0:a05a07cd6fdf 174
va009039 0:a05a07cd6fdf 175 #else
va009039 0:a05a07cd6fdf 176
va009039 0:a05a07cd6fdf 177 // AttributeIDList used to remove ServiceRecordHandle
va009039 0:a05a07cd6fdf 178 static const uint8_t removeServiceRecordHandleAttributeIDList[] = { 0x36, 0x00, 0x05, 0x0A, 0x00, 0x01, 0xFF, 0xFF };
va009039 0:a05a07cd6fdf 179
va009039 0:a05a07cd6fdf 180 // register service record internally - the normal version creates a copy of the record
va009039 0:a05a07cd6fdf 181 // pre: AttributeIDs are in ascending order => ServiceRecordHandle is first attribute if present
va009039 0:a05a07cd6fdf 182 // @returns ServiceRecordHandle or 0 if registration failed
va009039 0:a05a07cd6fdf 183 uint32_t sdp_register_service_internal(void *connection, uint8_t * record){
va009039 0:a05a07cd6fdf 184
va009039 0:a05a07cd6fdf 185 // dump for now
va009039 0:a05a07cd6fdf 186 // printf("Register service record\n");
va009039 0:a05a07cd6fdf 187 // de_dump_data_element(record);
va009039 0:a05a07cd6fdf 188
va009039 0:a05a07cd6fdf 189 // get user record handle
va009039 0:a05a07cd6fdf 190 uint32_t record_handle = sdp_get_service_record_handle(record);
va009039 0:a05a07cd6fdf 191
va009039 0:a05a07cd6fdf 192 // validate service record handle is not in reserved range
va009039 0:a05a07cd6fdf 193 if (record_handle <= maxReservedServiceRecordHandle) record_handle = 0;
va009039 0:a05a07cd6fdf 194
va009039 0:a05a07cd6fdf 195 // check if already in use
va009039 0:a05a07cd6fdf 196 if (record_handle) {
va009039 0:a05a07cd6fdf 197 if (sdp_get_record_for_handle(record_handle)) {
va009039 0:a05a07cd6fdf 198 record_handle = 0;
va009039 0:a05a07cd6fdf 199 }
va009039 0:a05a07cd6fdf 200 }
va009039 0:a05a07cd6fdf 201
va009039 0:a05a07cd6fdf 202 // create new handle if needed
va009039 0:a05a07cd6fdf 203 if (!record_handle){
va009039 0:a05a07cd6fdf 204 record_handle = sdp_create_service_record_handle();
va009039 0:a05a07cd6fdf 205 }
va009039 0:a05a07cd6fdf 206
va009039 0:a05a07cd6fdf 207 // calculate size of new service record: DES (2 byte len)
va009039 0:a05a07cd6fdf 208 // + ServiceRecordHandle attribute (UINT16 UINT32) + size of existing attributes
va009039 0:a05a07cd6fdf 209 uint16_t recordSize = 3 + (3 + 5) + de_get_data_size(record);
va009039 0:a05a07cd6fdf 210
va009039 0:a05a07cd6fdf 211 // alloc memory for new service_record_item
va009039 0:a05a07cd6fdf 212 service_record_item_t * newRecordItem = (service_record_item_t *) malloc(recordSize + sizeof(service_record_item_t));
va009039 0:a05a07cd6fdf 213 if (!newRecordItem) {
va009039 0:a05a07cd6fdf 214 sdp_emit_service_registered(connection, 0, BTSTACK_MEMORY_ALLOC_FAILED);
va009039 0:a05a07cd6fdf 215 return 0;
va009039 0:a05a07cd6fdf 216 }
va009039 0:a05a07cd6fdf 217 // link new service item to client connection
va009039 0:a05a07cd6fdf 218 newRecordItem->connection = connection;
va009039 0:a05a07cd6fdf 219
va009039 0:a05a07cd6fdf 220 // set new handle
va009039 0:a05a07cd6fdf 221 newRecordItem->service_record_handle = record_handle;
va009039 0:a05a07cd6fdf 222
va009039 0:a05a07cd6fdf 223 // create updated service record
va009039 0:a05a07cd6fdf 224 uint8_t * newRecord = (uint8_t *) &(newRecordItem->service_record);
va009039 0:a05a07cd6fdf 225
va009039 0:a05a07cd6fdf 226 // create DES for new record
va009039 0:a05a07cd6fdf 227 de_create_sequence(newRecord);
va009039 0:a05a07cd6fdf 228
va009039 0:a05a07cd6fdf 229 // set service record handle
va009039 0:a05a07cd6fdf 230 de_add_number(newRecord, DE_UINT, DE_SIZE_16, 0);
va009039 0:a05a07cd6fdf 231 de_add_number(newRecord, DE_UINT, DE_SIZE_32, record_handle);
va009039 0:a05a07cd6fdf 232
va009039 0:a05a07cd6fdf 233 // add other attributes
va009039 0:a05a07cd6fdf 234 sdp_append_attributes_in_attributeIDList(record, (uint8_t *) removeServiceRecordHandleAttributeIDList, 0, recordSize, newRecord);
va009039 0:a05a07cd6fdf 235
va009039 0:a05a07cd6fdf 236 // dump for now
va009039 0:a05a07cd6fdf 237 // de_dump_data_element(newRecord);
va009039 0:a05a07cd6fdf 238 // printf("reserved size %u, actual size %u\n", recordSize, de_get_len(newRecord));
va009039 0:a05a07cd6fdf 239
va009039 0:a05a07cd6fdf 240 // add to linked list
va009039 0:a05a07cd6fdf 241 linked_list_add(&sdp_service_records, (linked_item_t *) newRecordItem);
va009039 0:a05a07cd6fdf 242
va009039 0:a05a07cd6fdf 243 sdp_emit_service_registered(connection, 0, newRecordItem->service_record_handle);
va009039 0:a05a07cd6fdf 244
va009039 0:a05a07cd6fdf 245 return record_handle;
va009039 0:a05a07cd6fdf 246 }
va009039 0:a05a07cd6fdf 247
va009039 0:a05a07cd6fdf 248 #endif
va009039 0:a05a07cd6fdf 249
va009039 0:a05a07cd6fdf 250 // unregister service record internally
va009039 0:a05a07cd6fdf 251 //
va009039 0:a05a07cd6fdf 252 // makes sure one client cannot remove service records of other clients
va009039 0:a05a07cd6fdf 253 //
va009039 0:a05a07cd6fdf 254 void sdp_unregister_service_internal(void *connection, uint32_t service_record_handle){
va009039 0:a05a07cd6fdf 255 service_record_item_t * record_item = sdp_get_record_for_handle(service_record_handle);
va009039 0:a05a07cd6fdf 256 if (record_item && record_item->connection == connection) {
va009039 0:a05a07cd6fdf 257 linked_list_remove(&sdp_service_records, (linked_item_t *) record_item);
va009039 0:a05a07cd6fdf 258 }
va009039 0:a05a07cd6fdf 259 }
va009039 0:a05a07cd6fdf 260
va009039 0:a05a07cd6fdf 261 // remove all service record for a client connection
va009039 0:a05a07cd6fdf 262 void sdp_unregister_services_for_connection(void *connection){
va009039 0:a05a07cd6fdf 263 linked_item_t *it = (linked_item_t *) &sdp_service_records;
va009039 0:a05a07cd6fdf 264 while (it->next){
va009039 0:a05a07cd6fdf 265 service_record_item_t *record_item = (service_record_item_t *) it->next;
va009039 0:a05a07cd6fdf 266 if (record_item->connection == connection){
va009039 0:a05a07cd6fdf 267 it->next = it->next->next;
va009039 0:a05a07cd6fdf 268 #ifndef EMBEDDED
va009039 0:a05a07cd6fdf 269 free(record_item);
va009039 0:a05a07cd6fdf 270 #endif
va009039 0:a05a07cd6fdf 271 } else {
va009039 0:a05a07cd6fdf 272 it = it->next;
va009039 0:a05a07cd6fdf 273 }
va009039 0:a05a07cd6fdf 274 }
va009039 0:a05a07cd6fdf 275 }
va009039 0:a05a07cd6fdf 276
va009039 0:a05a07cd6fdf 277 // PDU
va009039 0:a05a07cd6fdf 278 // PDU ID (1), Transaction ID (2), Param Length (2), Param 1, Param 2, ..
va009039 0:a05a07cd6fdf 279
va009039 0:a05a07cd6fdf 280 int sdp_create_error_response(uint16_t transaction_id, uint16_t error_code){
va009039 0:a05a07cd6fdf 281 sdp_response_buffer[0] = SDP_ErrorResponse;
va009039 0:a05a07cd6fdf 282 net_store_16(sdp_response_buffer, 1, transaction_id);
va009039 0:a05a07cd6fdf 283 net_store_16(sdp_response_buffer, 3, 2);
va009039 0:a05a07cd6fdf 284 net_store_16(sdp_response_buffer, 5, error_code); // invalid syntax
va009039 0:a05a07cd6fdf 285 return 7;
va009039 0:a05a07cd6fdf 286 }
va009039 0:a05a07cd6fdf 287
va009039 0:a05a07cd6fdf 288 int sdp_handle_service_search_request(uint8_t * packet, uint16_t remote_mtu){
va009039 0:a05a07cd6fdf 289
va009039 0:a05a07cd6fdf 290 // get request details
va009039 0:a05a07cd6fdf 291 uint16_t transaction_id = READ_NET_16(packet, 1);
va009039 0:a05a07cd6fdf 292 // not used yet - uint16_t param_len = READ_NET_16(packet, 3);
va009039 0:a05a07cd6fdf 293 uint8_t * serviceSearchPattern = &packet[5];
va009039 0:a05a07cd6fdf 294 uint16_t serviceSearchPatternLen = de_get_len(serviceSearchPattern);
va009039 0:a05a07cd6fdf 295 uint16_t maximumServiceRecordCount = READ_NET_16(packet, 5 + serviceSearchPatternLen);
va009039 0:a05a07cd6fdf 296 uint8_t * continuationState = &packet[5+serviceSearchPatternLen+2];
va009039 0:a05a07cd6fdf 297
va009039 0:a05a07cd6fdf 298 // calc maxumumServiceRecordCount based on remote MTU
va009039 0:a05a07cd6fdf 299 uint16_t maxNrServiceRecordsPerResponse = (remote_mtu - (9+3))/4;
va009039 0:a05a07cd6fdf 300
va009039 0:a05a07cd6fdf 301 // continuation state contains index of next service record to examine
va009039 0:a05a07cd6fdf 302 int continuation = 0;
va009039 0:a05a07cd6fdf 303 uint16_t continuation_index = 0;
va009039 0:a05a07cd6fdf 304 if (continuationState[0] == 2){
va009039 0:a05a07cd6fdf 305 continuation_index = READ_NET_16(continuationState, 1);
va009039 0:a05a07cd6fdf 306 }
va009039 0:a05a07cd6fdf 307
va009039 0:a05a07cd6fdf 308 // get and limit total count
va009039 0:a05a07cd6fdf 309 linked_item_t *it;
va009039 0:a05a07cd6fdf 310 uint16_t total_service_count = 0;
va009039 0:a05a07cd6fdf 311 for (it = (linked_item_t *) sdp_service_records; it ; it = it->next){
va009039 0:a05a07cd6fdf 312 service_record_item_t * item = (service_record_item_t *) it;
va009039 0:a05a07cd6fdf 313 if (!sdp_record_matches_service_search_pattern(item->service_record, serviceSearchPattern)) continue;
va009039 0:a05a07cd6fdf 314 total_service_count++;
va009039 0:a05a07cd6fdf 315 }
va009039 0:a05a07cd6fdf 316 if (total_service_count > maximumServiceRecordCount){
va009039 0:a05a07cd6fdf 317 total_service_count = maximumServiceRecordCount;
va009039 0:a05a07cd6fdf 318 }
va009039 0:a05a07cd6fdf 319
va009039 0:a05a07cd6fdf 320 // ServiceRecordHandleList at 9
va009039 0:a05a07cd6fdf 321 uint16_t pos = 9;
va009039 0:a05a07cd6fdf 322 uint16_t current_service_count = 0;
va009039 0:a05a07cd6fdf 323 uint16_t current_service_index = 0;
va009039 0:a05a07cd6fdf 324 uint16_t matching_service_count = 0;
va009039 0:a05a07cd6fdf 325 for (it = (linked_item_t *) sdp_service_records; it ; it = it->next, ++current_service_index){
va009039 0:a05a07cd6fdf 326 service_record_item_t * item = (service_record_item_t *) it;
va009039 0:a05a07cd6fdf 327
va009039 0:a05a07cd6fdf 328 if (!sdp_record_matches_service_search_pattern(item->service_record, serviceSearchPattern)) continue;
va009039 0:a05a07cd6fdf 329 matching_service_count++;
va009039 0:a05a07cd6fdf 330
va009039 0:a05a07cd6fdf 331 if (current_service_index < continuation_index) continue;
va009039 0:a05a07cd6fdf 332
va009039 0:a05a07cd6fdf 333 net_store_32(sdp_response_buffer, pos, item->service_record_handle);
va009039 0:a05a07cd6fdf 334 pos += 4;
va009039 0:a05a07cd6fdf 335 current_service_count++;
va009039 0:a05a07cd6fdf 336
va009039 0:a05a07cd6fdf 337 if (matching_service_count >= total_service_count) break;
va009039 0:a05a07cd6fdf 338
va009039 0:a05a07cd6fdf 339 if (current_service_count >= maxNrServiceRecordsPerResponse){
va009039 0:a05a07cd6fdf 340 continuation = 1;
va009039 0:a05a07cd6fdf 341 continuation_index = current_service_index + 1;
va009039 0:a05a07cd6fdf 342 break;
va009039 0:a05a07cd6fdf 343 }
va009039 0:a05a07cd6fdf 344 }
va009039 0:a05a07cd6fdf 345
va009039 0:a05a07cd6fdf 346 // Store continuation state
va009039 0:a05a07cd6fdf 347 if (continuation) {
va009039 0:a05a07cd6fdf 348 sdp_response_buffer[pos++] = 2;
va009039 0:a05a07cd6fdf 349 net_store_16(sdp_response_buffer, pos, continuation_index);
va009039 0:a05a07cd6fdf 350 pos += 2;
va009039 0:a05a07cd6fdf 351 } else {
va009039 0:a05a07cd6fdf 352 sdp_response_buffer[pos++] = 0;
va009039 0:a05a07cd6fdf 353 }
va009039 0:a05a07cd6fdf 354
va009039 0:a05a07cd6fdf 355 // header
va009039 0:a05a07cd6fdf 356 sdp_response_buffer[0] = SDP_ServiceSearchResponse;
va009039 0:a05a07cd6fdf 357 net_store_16(sdp_response_buffer, 1, transaction_id);
va009039 0:a05a07cd6fdf 358 net_store_16(sdp_response_buffer, 3, pos - 5); // size of variable payload
va009039 0:a05a07cd6fdf 359 net_store_16(sdp_response_buffer, 5, total_service_count);
va009039 0:a05a07cd6fdf 360 net_store_16(sdp_response_buffer, 7, current_service_count);
va009039 0:a05a07cd6fdf 361
va009039 0:a05a07cd6fdf 362 return pos;
va009039 0:a05a07cd6fdf 363 }
va009039 0:a05a07cd6fdf 364
va009039 0:a05a07cd6fdf 365 int sdp_handle_service_attribute_request(uint8_t * packet, uint16_t remote_mtu){
va009039 0:a05a07cd6fdf 366
va009039 0:a05a07cd6fdf 367 // get request details
va009039 0:a05a07cd6fdf 368 uint16_t transaction_id = READ_NET_16(packet, 1);
va009039 0:a05a07cd6fdf 369 // not used yet - uint16_t param_len = READ_NET_16(packet, 3);
va009039 0:a05a07cd6fdf 370 uint32_t serviceRecordHandle = READ_NET_32(packet, 5);
va009039 0:a05a07cd6fdf 371 uint16_t maximumAttributeByteCount = READ_NET_16(packet, 9);
va009039 0:a05a07cd6fdf 372 uint8_t * attributeIDList = &packet[11];
va009039 0:a05a07cd6fdf 373 uint16_t attributeIDListLen = de_get_len(attributeIDList);
va009039 0:a05a07cd6fdf 374 uint8_t * continuationState = &packet[11+attributeIDListLen];
va009039 0:a05a07cd6fdf 375
va009039 0:a05a07cd6fdf 376 // calc maximumAttributeByteCount based on remote MTU
va009039 0:a05a07cd6fdf 377 uint16_t maximumAttributeByteCount2 = remote_mtu - (7+3);
va009039 0:a05a07cd6fdf 378 if (maximumAttributeByteCount2 < maximumAttributeByteCount) {
va009039 0:a05a07cd6fdf 379 maximumAttributeByteCount = maximumAttributeByteCount2;
va009039 0:a05a07cd6fdf 380 }
va009039 0:a05a07cd6fdf 381
va009039 0:a05a07cd6fdf 382 // continuation state contains the offset into the complete response
va009039 0:a05a07cd6fdf 383 uint16_t continuation_offset = 0;
va009039 0:a05a07cd6fdf 384 if (continuationState[0] == 2){
va009039 0:a05a07cd6fdf 385 continuation_offset = READ_NET_16(continuationState, 1);
va009039 0:a05a07cd6fdf 386 }
va009039 0:a05a07cd6fdf 387
va009039 0:a05a07cd6fdf 388 // get service record
va009039 0:a05a07cd6fdf 389 service_record_item_t * item = sdp_get_record_for_handle(serviceRecordHandle);
va009039 0:a05a07cd6fdf 390 if (!item){
va009039 0:a05a07cd6fdf 391 // service record handle doesn't exist
va009039 0:a05a07cd6fdf 392 return sdp_create_error_response(transaction_id, 0x0002); /// invalid Service Record Handle
va009039 0:a05a07cd6fdf 393 }
va009039 0:a05a07cd6fdf 394
va009039 0:a05a07cd6fdf 395
va009039 0:a05a07cd6fdf 396 // AttributeList - starts at offset 7
va009039 0:a05a07cd6fdf 397 uint16_t pos = 7;
va009039 0:a05a07cd6fdf 398
va009039 0:a05a07cd6fdf 399 if (continuation_offset == 0){
va009039 0:a05a07cd6fdf 400
va009039 0:a05a07cd6fdf 401 // get size of this record
va009039 0:a05a07cd6fdf 402 uint16_t filtered_attributes_size = spd_get_filtered_size(item->service_record, attributeIDList);
va009039 0:a05a07cd6fdf 403
va009039 0:a05a07cd6fdf 404 // store DES
va009039 0:a05a07cd6fdf 405 de_store_descriptor_with_len(&sdp_response_buffer[pos], DE_DES, DE_SIZE_VAR_16, filtered_attributes_size);
va009039 0:a05a07cd6fdf 406 maximumAttributeByteCount -= 3;
va009039 0:a05a07cd6fdf 407 pos += 3;
va009039 0:a05a07cd6fdf 408 }
va009039 0:a05a07cd6fdf 409
va009039 0:a05a07cd6fdf 410 // copy maximumAttributeByteCount from record
va009039 0:a05a07cd6fdf 411 uint16_t bytes_used;
va009039 0:a05a07cd6fdf 412 int complete = sdp_filter_attributes_in_attributeIDList(item->service_record, attributeIDList, continuation_offset, maximumAttributeByteCount, &bytes_used, &sdp_response_buffer[pos]);
va009039 0:a05a07cd6fdf 413 pos += bytes_used;
va009039 0:a05a07cd6fdf 414
va009039 0:a05a07cd6fdf 415 uint16_t attributeListByteCount = pos - 7;
va009039 0:a05a07cd6fdf 416
va009039 0:a05a07cd6fdf 417 if (complete) {
va009039 0:a05a07cd6fdf 418 sdp_response_buffer[pos++] = 0;
va009039 0:a05a07cd6fdf 419 } else {
va009039 0:a05a07cd6fdf 420 continuation_offset += bytes_used;
va009039 0:a05a07cd6fdf 421 sdp_response_buffer[pos++] = 2;
va009039 0:a05a07cd6fdf 422 net_store_16(sdp_response_buffer, pos, continuation_offset);
va009039 0:a05a07cd6fdf 423 pos += 2;
va009039 0:a05a07cd6fdf 424 }
va009039 0:a05a07cd6fdf 425
va009039 0:a05a07cd6fdf 426 // header
va009039 0:a05a07cd6fdf 427 sdp_response_buffer[0] = SDP_ServiceAttributeResponse;
va009039 0:a05a07cd6fdf 428 net_store_16(sdp_response_buffer, 1, transaction_id);
va009039 0:a05a07cd6fdf 429 net_store_16(sdp_response_buffer, 3, pos - 5); // size of variable payload
va009039 0:a05a07cd6fdf 430 net_store_16(sdp_response_buffer, 5, attributeListByteCount);
va009039 0:a05a07cd6fdf 431
va009039 0:a05a07cd6fdf 432 return pos;
va009039 0:a05a07cd6fdf 433 }
va009039 0:a05a07cd6fdf 434
va009039 0:a05a07cd6fdf 435 static uint16_t sdp_get_size_for_service_search_attribute_response(uint8_t * serviceSearchPattern, uint8_t * attributeIDList){
va009039 0:a05a07cd6fdf 436 uint16_t total_response_size = 0;
va009039 0:a05a07cd6fdf 437 linked_item_t *it;
va009039 0:a05a07cd6fdf 438 for (it = (linked_item_t *) sdp_service_records; it ; it = it->next){
va009039 0:a05a07cd6fdf 439 service_record_item_t * item = (service_record_item_t *) it;
va009039 0:a05a07cd6fdf 440
va009039 0:a05a07cd6fdf 441 if (!sdp_record_matches_service_search_pattern(item->service_record, serviceSearchPattern)) continue;
va009039 0:a05a07cd6fdf 442
va009039 0:a05a07cd6fdf 443 // for all service records that match
va009039 0:a05a07cd6fdf 444 total_response_size += 3 + spd_get_filtered_size(item->service_record, attributeIDList);
va009039 0:a05a07cd6fdf 445 }
va009039 0:a05a07cd6fdf 446 return total_response_size;
va009039 0:a05a07cd6fdf 447 }
va009039 0:a05a07cd6fdf 448
va009039 0:a05a07cd6fdf 449 int sdp_handle_service_search_attribute_request(uint8_t * packet, uint16_t remote_mtu){
va009039 0:a05a07cd6fdf 450
va009039 0:a05a07cd6fdf 451 // SDP header before attribute sevice list: 7
va009039 0:a05a07cd6fdf 452 // Continuation, worst case: 5
va009039 0:a05a07cd6fdf 453
va009039 0:a05a07cd6fdf 454 // get request details
va009039 0:a05a07cd6fdf 455 uint16_t transaction_id = READ_NET_16(packet, 1);
va009039 0:a05a07cd6fdf 456 // not used yet - uint16_t param_len = READ_NET_16(packet, 3);
va009039 0:a05a07cd6fdf 457 uint8_t * serviceSearchPattern = &packet[5];
va009039 0:a05a07cd6fdf 458 uint16_t serviceSearchPatternLen = de_get_len(serviceSearchPattern);
va009039 0:a05a07cd6fdf 459 uint16_t maximumAttributeByteCount = READ_NET_16(packet, 5 + serviceSearchPatternLen);
va009039 0:a05a07cd6fdf 460 uint8_t * attributeIDList = &packet[5+serviceSearchPatternLen+2];
va009039 0:a05a07cd6fdf 461 uint16_t attributeIDListLen = de_get_len(attributeIDList);
va009039 0:a05a07cd6fdf 462 uint8_t * continuationState = &packet[5+serviceSearchPatternLen+2+attributeIDListLen];
va009039 0:a05a07cd6fdf 463
va009039 0:a05a07cd6fdf 464 // calc maximumAttributeByteCount based on remote MTU, SDP header and reserved Continuation block
va009039 0:a05a07cd6fdf 465 uint16_t maximumAttributeByteCount2 = remote_mtu - 12;
va009039 0:a05a07cd6fdf 466 if (maximumAttributeByteCount2 < maximumAttributeByteCount) {
va009039 0:a05a07cd6fdf 467 maximumAttributeByteCount = maximumAttributeByteCount2;
va009039 0:a05a07cd6fdf 468 }
va009039 0:a05a07cd6fdf 469
va009039 0:a05a07cd6fdf 470 // continuation state contains: index of next service record to examine
va009039 0:a05a07cd6fdf 471 // continuation state contains: byte offset into this service record
va009039 0:a05a07cd6fdf 472 uint16_t continuation_service_index = 0;
va009039 0:a05a07cd6fdf 473 uint16_t continuation_offset = 0;
va009039 0:a05a07cd6fdf 474 if (continuationState[0] == 4){
va009039 0:a05a07cd6fdf 475 continuation_service_index = READ_NET_16(continuationState, 1);
va009039 0:a05a07cd6fdf 476 continuation_offset = READ_NET_16(continuationState, 3);
va009039 0:a05a07cd6fdf 477 }
va009039 0:a05a07cd6fdf 478
va009039 0:a05a07cd6fdf 479 // printf("--> sdp_handle_service_search_attribute_request, cont %u/%u, max %u\n", continuation_service_index, continuation_offset, maximumAttributeByteCount);
va009039 0:a05a07cd6fdf 480
va009039 0:a05a07cd6fdf 481 // AttributeLists - starts at offset 7
va009039 0:a05a07cd6fdf 482 uint16_t pos = 7;
va009039 0:a05a07cd6fdf 483
va009039 0:a05a07cd6fdf 484 // add DES with total size for first request
va009039 0:a05a07cd6fdf 485 if (continuation_service_index == 0 && continuation_offset == 0){
va009039 0:a05a07cd6fdf 486 uint16_t total_response_size = sdp_get_size_for_service_search_attribute_response(serviceSearchPattern, attributeIDList);
va009039 0:a05a07cd6fdf 487 de_store_descriptor_with_len(&sdp_response_buffer[pos], DE_DES, DE_SIZE_VAR_16, total_response_size);
va009039 0:a05a07cd6fdf 488 // log_info("total response size %u\n", total_response_size);
va009039 0:a05a07cd6fdf 489 pos += 3;
va009039 0:a05a07cd6fdf 490 maximumAttributeByteCount -= 3;
va009039 0:a05a07cd6fdf 491 }
va009039 0:a05a07cd6fdf 492
va009039 0:a05a07cd6fdf 493 // create attribute list
va009039 0:a05a07cd6fdf 494 int first_answer = 1;
va009039 0:a05a07cd6fdf 495 int continuation = 0;
va009039 0:a05a07cd6fdf 496 uint16_t current_service_index = 0;
va009039 0:a05a07cd6fdf 497 linked_item_t *it = (linked_item_t *) sdp_service_records;
va009039 0:a05a07cd6fdf 498 for ( ; it ; it = it->next, ++current_service_index){
va009039 0:a05a07cd6fdf 499 service_record_item_t * item = (service_record_item_t *) it;
va009039 0:a05a07cd6fdf 500
va009039 0:a05a07cd6fdf 501 if (current_service_index < continuation_service_index ) continue;
va009039 0:a05a07cd6fdf 502 if (!sdp_record_matches_service_search_pattern(item->service_record, serviceSearchPattern)) continue;
va009039 0:a05a07cd6fdf 503
va009039 0:a05a07cd6fdf 504 if (continuation_offset == 0){
va009039 0:a05a07cd6fdf 505
va009039 0:a05a07cd6fdf 506 // get size of this record
va009039 0:a05a07cd6fdf 507 uint16_t filtered_attributes_size = spd_get_filtered_size(item->service_record, attributeIDList);
va009039 0:a05a07cd6fdf 508
va009039 0:a05a07cd6fdf 509 // stop if complete record doesn't fits into response but we already have a partial response
va009039 0:a05a07cd6fdf 510 if ((filtered_attributes_size + 3 > maximumAttributeByteCount) && !first_answer) {
va009039 0:a05a07cd6fdf 511 continuation = 1;
va009039 0:a05a07cd6fdf 512 break;
va009039 0:a05a07cd6fdf 513 }
va009039 0:a05a07cd6fdf 514
va009039 0:a05a07cd6fdf 515 // store DES
va009039 0:a05a07cd6fdf 516 de_store_descriptor_with_len(&sdp_response_buffer[pos], DE_DES, DE_SIZE_VAR_16, filtered_attributes_size);
va009039 0:a05a07cd6fdf 517 pos += 3;
va009039 0:a05a07cd6fdf 518 maximumAttributeByteCount -= 3;
va009039 0:a05a07cd6fdf 519 }
va009039 0:a05a07cd6fdf 520
va009039 0:a05a07cd6fdf 521 first_answer = 0;
va009039 0:a05a07cd6fdf 522
va009039 0:a05a07cd6fdf 523 // copy maximumAttributeByteCount from record
va009039 0:a05a07cd6fdf 524 uint16_t bytes_used;
va009039 0:a05a07cd6fdf 525 int complete = sdp_filter_attributes_in_attributeIDList(item->service_record, attributeIDList, continuation_offset, maximumAttributeByteCount, &bytes_used, &sdp_response_buffer[pos]);
va009039 0:a05a07cd6fdf 526 pos += bytes_used;
va009039 0:a05a07cd6fdf 527 maximumAttributeByteCount -= bytes_used;
va009039 0:a05a07cd6fdf 528
va009039 0:a05a07cd6fdf 529 if (complete) {
va009039 0:a05a07cd6fdf 530 continuation_offset = 0;
va009039 0:a05a07cd6fdf 531 continue;
va009039 0:a05a07cd6fdf 532 }
va009039 0:a05a07cd6fdf 533
va009039 0:a05a07cd6fdf 534 continuation = 1;
va009039 0:a05a07cd6fdf 535 continuation_offset += bytes_used;
va009039 0:a05a07cd6fdf 536 break;
va009039 0:a05a07cd6fdf 537 }
va009039 0:a05a07cd6fdf 538
va009039 0:a05a07cd6fdf 539 uint16_t attributeListsByteCount = pos - 7;
va009039 0:a05a07cd6fdf 540
va009039 0:a05a07cd6fdf 541 // Continuation State
va009039 0:a05a07cd6fdf 542 if (continuation){
va009039 0:a05a07cd6fdf 543 sdp_response_buffer[pos++] = 4;
va009039 0:a05a07cd6fdf 544 net_store_16(sdp_response_buffer, pos, (uint16_t) current_service_index);
va009039 0:a05a07cd6fdf 545 pos += 2;
va009039 0:a05a07cd6fdf 546 net_store_16(sdp_response_buffer, pos, continuation_offset);
va009039 0:a05a07cd6fdf 547 pos += 2;
va009039 0:a05a07cd6fdf 548 } else {
va009039 0:a05a07cd6fdf 549 // complete
va009039 0:a05a07cd6fdf 550 sdp_response_buffer[pos++] = 0;
va009039 0:a05a07cd6fdf 551 }
va009039 0:a05a07cd6fdf 552
va009039 0:a05a07cd6fdf 553 // create SDP header
va009039 0:a05a07cd6fdf 554 sdp_response_buffer[0] = SDP_ServiceSearchAttributeResponse;
va009039 0:a05a07cd6fdf 555 net_store_16(sdp_response_buffer, 1, transaction_id);
va009039 0:a05a07cd6fdf 556 net_store_16(sdp_response_buffer, 3, pos - 5); // size of variable payload
va009039 0:a05a07cd6fdf 557 net_store_16(sdp_response_buffer, 5, attributeListsByteCount);
va009039 0:a05a07cd6fdf 558
va009039 0:a05a07cd6fdf 559 return pos;
va009039 0:a05a07cd6fdf 560 }
va009039 0:a05a07cd6fdf 561
va009039 0:a05a07cd6fdf 562 static void sdp_try_respond(void){
va009039 0:a05a07cd6fdf 563 if (!sdp_response_size ) return;
va009039 0:a05a07cd6fdf 564 if (!l2cap_cid) return;
va009039 0:a05a07cd6fdf 565 if (!l2cap_can_send_packet_now(l2cap_cid)) return;
va009039 0:a05a07cd6fdf 566
va009039 0:a05a07cd6fdf 567 // update state before sending packet (avoid getting called when new l2cap credit gets emitted)
va009039 0:a05a07cd6fdf 568 uint16_t size = sdp_response_size;
va009039 0:a05a07cd6fdf 569 sdp_response_size = 0;
va009039 0:a05a07cd6fdf 570 l2cap_send_internal(l2cap_cid, sdp_response_buffer, size);
va009039 0:a05a07cd6fdf 571 }
va009039 0:a05a07cd6fdf 572
va009039 0:a05a07cd6fdf 573 // we assume that we don't get two requests in a row
va009039 0:a05a07cd6fdf 574 static void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
va009039 0:a05a07cd6fdf 575 uint16_t transaction_id;
va009039 0:a05a07cd6fdf 576 SDP_PDU_ID_t pdu_id;
va009039 0:a05a07cd6fdf 577 uint16_t remote_mtu;
va009039 0:a05a07cd6fdf 578 // uint16_t param_len;
va009039 0:a05a07cd6fdf 579
va009039 0:a05a07cd6fdf 580 switch (packet_type) {
va009039 0:a05a07cd6fdf 581
va009039 0:a05a07cd6fdf 582 case L2CAP_DATA_PACKET:
va009039 0:a05a07cd6fdf 583 pdu_id = (SDP_PDU_ID_t) packet[0];
va009039 0:a05a07cd6fdf 584 transaction_id = READ_NET_16(packet, 1);
va009039 0:a05a07cd6fdf 585 // param_len = READ_NET_16(packet, 3);
va009039 0:a05a07cd6fdf 586 remote_mtu = l2cap_get_remote_mtu_for_local_cid(channel);
va009039 0:a05a07cd6fdf 587 // account for our buffer
va009039 0:a05a07cd6fdf 588 if (remote_mtu > SDP_RESPONSE_BUFFER_SIZE){
va009039 0:a05a07cd6fdf 589 remote_mtu = SDP_RESPONSE_BUFFER_SIZE;
va009039 0:a05a07cd6fdf 590 }
va009039 0:a05a07cd6fdf 591
va009039 0:a05a07cd6fdf 592 // printf("SDP Request: type %u, transaction id %u, len %u, mtu %u\n", pdu_id, transaction_id, param_len, remote_mtu);
va009039 0:a05a07cd6fdf 593 switch (pdu_id){
va009039 0:a05a07cd6fdf 594
va009039 0:a05a07cd6fdf 595 case SDP_ServiceSearchRequest:
va009039 0:a05a07cd6fdf 596 sdp_response_size = sdp_handle_service_search_request(packet, remote_mtu);
va009039 0:a05a07cd6fdf 597 break;
va009039 0:a05a07cd6fdf 598
va009039 0:a05a07cd6fdf 599 case SDP_ServiceAttributeRequest:
va009039 0:a05a07cd6fdf 600 sdp_response_size = sdp_handle_service_attribute_request(packet, remote_mtu);
va009039 0:a05a07cd6fdf 601 break;
va009039 0:a05a07cd6fdf 602
va009039 0:a05a07cd6fdf 603 case SDP_ServiceSearchAttributeRequest:
va009039 0:a05a07cd6fdf 604 sdp_response_size = sdp_handle_service_search_attribute_request(packet, remote_mtu);
va009039 0:a05a07cd6fdf 605 break;
va009039 0:a05a07cd6fdf 606
va009039 0:a05a07cd6fdf 607 default:
va009039 0:a05a07cd6fdf 608 sdp_response_size = sdp_create_error_response(transaction_id, 0x0003); // invalid syntax
va009039 0:a05a07cd6fdf 609 break;
va009039 0:a05a07cd6fdf 610 }
va009039 0:a05a07cd6fdf 611
va009039 0:a05a07cd6fdf 612 sdp_try_respond();
va009039 0:a05a07cd6fdf 613
va009039 0:a05a07cd6fdf 614 break;
va009039 0:a05a07cd6fdf 615
va009039 0:a05a07cd6fdf 616 case HCI_EVENT_PACKET:
va009039 0:a05a07cd6fdf 617
va009039 0:a05a07cd6fdf 618 switch (packet[0]) {
va009039 0:a05a07cd6fdf 619
va009039 0:a05a07cd6fdf 620 case L2CAP_EVENT_INCOMING_CONNECTION:
va009039 0:a05a07cd6fdf 621 if (l2cap_cid) {
va009039 0:a05a07cd6fdf 622 // CONNECTION REJECTED DUE TO LIMITED RESOURCES
va009039 0:a05a07cd6fdf 623 l2cap_decline_connection_internal(channel, 0x0d);
va009039 0:a05a07cd6fdf 624 break;
va009039 0:a05a07cd6fdf 625 }
va009039 0:a05a07cd6fdf 626 // accept
va009039 0:a05a07cd6fdf 627 l2cap_cid = channel;
va009039 0:a05a07cd6fdf 628 sdp_response_size = 0;
va009039 0:a05a07cd6fdf 629 l2cap_accept_connection_internal(channel);
va009039 0:a05a07cd6fdf 630 break;
va009039 0:a05a07cd6fdf 631
va009039 0:a05a07cd6fdf 632 case L2CAP_EVENT_CHANNEL_OPENED:
va009039 0:a05a07cd6fdf 633 if (packet[2]) {
va009039 0:a05a07cd6fdf 634 // open failed -> reset
va009039 0:a05a07cd6fdf 635 l2cap_cid = 0;
va009039 0:a05a07cd6fdf 636 }
va009039 0:a05a07cd6fdf 637 break;
va009039 0:a05a07cd6fdf 638
va009039 0:a05a07cd6fdf 639 case L2CAP_EVENT_CREDITS:
va009039 0:a05a07cd6fdf 640 case DAEMON_EVENT_HCI_PACKET_SENT:
va009039 0:a05a07cd6fdf 641 sdp_try_respond();
va009039 0:a05a07cd6fdf 642 break;
va009039 0:a05a07cd6fdf 643
va009039 0:a05a07cd6fdf 644 case L2CAP_EVENT_CHANNEL_CLOSED:
va009039 0:a05a07cd6fdf 645 if (channel == l2cap_cid){
va009039 0:a05a07cd6fdf 646 // reset
va009039 0:a05a07cd6fdf 647 l2cap_cid = 0;
va009039 0:a05a07cd6fdf 648 }
va009039 0:a05a07cd6fdf 649 break;
va009039 0:a05a07cd6fdf 650
va009039 0:a05a07cd6fdf 651 default:
va009039 0:a05a07cd6fdf 652 // other event
va009039 0:a05a07cd6fdf 653 break;
va009039 0:a05a07cd6fdf 654 }
va009039 0:a05a07cd6fdf 655 break;
va009039 0:a05a07cd6fdf 656
va009039 0:a05a07cd6fdf 657 default:
va009039 0:a05a07cd6fdf 658 // other packet type
va009039 0:a05a07cd6fdf 659 break;
va009039 0:a05a07cd6fdf 660 }
va009039 0:a05a07cd6fdf 661 }
va009039 0:a05a07cd6fdf 662