1 /* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 /* 39 * sdp_rfcomm_query.c 40 */ 41 42 #include <stdint.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 47 #include "btstack_debug.h" 48 #include "btstack_event.h" 49 #include "classic/core.h" 50 #include "classic/sdp_client.h" 51 #include "classic/sdp_client_rfcomm.h" 52 #include "classic/sdp_util.h" 53 #include "hci_cmd.h" 54 55 // called by test/sdp_client 56 void sdp_client_query_rfcomm_init(void); 57 58 typedef enum { 59 GET_PROTOCOL_LIST_LENGTH = 1, 60 GET_PROTOCOL_LENGTH, 61 GET_PROTOCOL_ID_HEADER_LENGTH, 62 GET_PROTOCOL_ID, 63 GET_PROTOCOL_VALUE_LENGTH, 64 GET_PROTOCOL_VALUE 65 } pdl_state_t; 66 67 68 // higher layer query - get rfcomm channel and name 69 70 const uint8_t des_attributeIDList[] = { 0x35, 0x05, 0x0A, 0x00, 0x01, 0x01, 0x00}; // Arribute: 0x0001 - 0x0100 71 72 static uint8_t des_serviceSearchPattern[5] = {0x35, 0x03, 0x19, 0x00, 0x00}; 73 74 static uint8_t sdp_service_name[SDP_SERVICE_NAME_LEN+1]; 75 static uint8_t sdp_service_name_len = 0; 76 static uint8_t sdp_rfcomm_channel_nr = 0; 77 static uint8_t sdp_service_name_header_size; 78 79 static pdl_state_t pdl_state = GET_PROTOCOL_LIST_LENGTH; 80 static int protocol_value_bytes_received = 0; 81 static uint16_t protocol_id = 0; 82 static int protocol_offset; 83 static int protocol_size; 84 static int protocol_id_bytes_to_read; 85 static int protocol_value_size; 86 static de_state_t de_header_state; 87 static de_state_t sn_de_header_state; 88 static btstack_packet_handler_t sdp_app_callback; 89 // 90 91 static void sdp_rfcomm_query_emit_service(void){ 92 uint8_t event[3+SDP_SERVICE_NAME_LEN+1]; 93 event[0] = SDP_EVENT_QUERY_RFCOMM_SERVICE; 94 event[1] = sdp_service_name_len + 1; 95 event[2] = sdp_rfcomm_channel_nr; 96 memcpy(&event[3], sdp_service_name, sdp_service_name_len); 97 event[3+sdp_service_name_len] = 0; 98 (*sdp_app_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 99 sdp_rfcomm_channel_nr = 0; 100 } 101 102 static void sdp_client_query_rfcomm_emit_busy(btstack_packet_handler_t callback){ 103 log_error("sdp_client_query_rfcomm started when not ready"); 104 uint8_t event[] = { SDP_EVENT_QUERY_COMPLETE, 1, SDP_QUERY_BUSY}; 105 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 106 } 107 108 static void handleProtocolDescriptorListData(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){ 109 // init state on first byte 110 if (data_offset == 0){ 111 pdl_state = GET_PROTOCOL_LIST_LENGTH; 112 } 113 114 // log_info("handleProtocolDescriptorListData (%u,%u) %02x", attribute_value_length, data_offset, data); 115 116 switch(pdl_state){ 117 118 case GET_PROTOCOL_LIST_LENGTH: 119 if (!de_state_size(data, &de_header_state)) break; 120 // log_info(" query: PD List payload is %d bytes.", de_header_state.de_size); 121 // log_info(" query: PD List offset %u, list size %u", de_header_state.de_offset, de_header_state.de_size); 122 123 pdl_state = GET_PROTOCOL_LENGTH; 124 break; 125 126 case GET_PROTOCOL_LENGTH: 127 // check size 128 if (!de_state_size(data, &de_header_state)) break; 129 // log_info(" query: PD Record payload is %d bytes.", de_header_state.de_size); 130 131 // cache protocol info 132 protocol_offset = de_header_state.de_offset; 133 protocol_size = de_header_state.de_size; 134 135 pdl_state = GET_PROTOCOL_ID_HEADER_LENGTH; 136 break; 137 138 case GET_PROTOCOL_ID_HEADER_LENGTH: 139 protocol_offset++; 140 if (!de_state_size(data, &de_header_state)) break; 141 142 protocol_id = 0; 143 protocol_id_bytes_to_read = de_header_state.de_size; 144 // log_info(" query: ID data is stored in %d bytes.", protocol_id_bytes_to_read); 145 pdl_state = GET_PROTOCOL_ID; 146 147 break; 148 149 case GET_PROTOCOL_ID: 150 protocol_offset++; 151 152 protocol_id = (protocol_id << 8) | data; 153 protocol_id_bytes_to_read--; 154 if (protocol_id_bytes_to_read > 0) break; 155 156 // log_info(" query: Protocol ID: %04x.", protocol_id); 157 158 if (protocol_offset >= protocol_size){ 159 pdl_state = GET_PROTOCOL_LENGTH; 160 // log_info(" query: Get next protocol"); 161 break; 162 } 163 164 pdl_state = GET_PROTOCOL_VALUE_LENGTH; 165 protocol_value_bytes_received = 0; 166 break; 167 168 case GET_PROTOCOL_VALUE_LENGTH: 169 protocol_offset++; 170 171 if (!de_state_size(data, &de_header_state)) break; 172 173 protocol_value_size = de_header_state.de_size; 174 pdl_state = GET_PROTOCOL_VALUE; 175 sdp_rfcomm_channel_nr = 0; 176 break; 177 178 case GET_PROTOCOL_VALUE: 179 protocol_offset++; 180 protocol_value_bytes_received++; 181 182 // log_info(" query: protocol_value_bytes_received %u, protocol_value_size %u", protocol_value_bytes_received, protocol_value_size); 183 184 if (protocol_value_bytes_received < protocol_value_size) break; 185 186 if (protocol_id == 0x0003){ 187 // log_info("\n\n ******* Data ***** %02x\n\n", data); 188 sdp_rfcomm_channel_nr = data; 189 } 190 191 // log_info(" query: protocol done"); 192 // log_info(" query: Protocol offset %u, protocol size %u", protocol_offset, protocol_size); 193 194 if (protocol_offset >= protocol_size) { 195 pdl_state = GET_PROTOCOL_LENGTH; 196 break; 197 198 } 199 pdl_state = GET_PROTOCOL_ID_HEADER_LENGTH; 200 // log_info(" query: Get next protocol"); 201 break; 202 default: 203 break; 204 } 205 } 206 207 static void handleServiceNameData(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){ 208 209 // Get Header Len 210 if (data_offset == 0){ 211 de_state_size(data, &sn_de_header_state); 212 sdp_service_name_header_size = sn_de_header_state.addon_header_bytes + 1; 213 return; 214 } 215 216 // Get Header 217 if (data_offset < sdp_service_name_header_size){ 218 de_state_size(data, &sn_de_header_state); 219 return; 220 } 221 222 // Process payload 223 int name_len = attribute_value_length - sdp_service_name_header_size; 224 int name_pos = data_offset - sdp_service_name_header_size; 225 226 if (name_pos < SDP_SERVICE_NAME_LEN){ 227 sdp_service_name[name_pos] = data; 228 name_pos++; 229 230 // terminate if name complete 231 if (name_pos >= name_len){ 232 sdp_service_name[name_pos] = 0; 233 sdp_service_name_len = name_pos; 234 } 235 236 // terminate if buffer full 237 if (name_pos == SDP_SERVICE_NAME_LEN){ 238 sdp_service_name[name_pos] = 0; 239 sdp_service_name_len = name_pos; 240 } 241 } 242 243 // notify on last char 244 if (data_offset == attribute_value_length - 1 && sdp_rfcomm_channel_nr!=0){ 245 sdp_rfcomm_query_emit_service(); 246 } 247 } 248 249 static void handle_sdp_parser_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 250 switch (hci_event_packet_get_type(packet)){ 251 case SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE: 252 // handle service without a name 253 if (sdp_rfcomm_channel_nr){ 254 sdp_rfcomm_query_emit_service(); 255 } 256 257 // prepare for new record 258 sdp_rfcomm_channel_nr = 0; 259 sdp_service_name[0] = 0; 260 break; 261 case SDP_EVENT_QUERY_ATTRIBUTE_VALUE: 262 // log_info("handle_sdp_parser_event [ AID, ALen, DOff, Data] : [%x, %u, %u] BYTE %02x", 263 // ve->attribute_id, sdp_event_query_attribute_byte_get_attribute_length(packet), 264 // sdp_event_query_attribute_byte_get_data_offset(packet), sdp_event_query_attribute_byte_get_data(packet)); 265 switch (sdp_event_query_attribute_byte_get_attribute_id(packet)){ 266 case SDP_ProtocolDescriptorList: 267 // find rfcomm channel 268 handleProtocolDescriptorListData(sdp_event_query_attribute_byte_get_attribute_length(packet), 269 sdp_event_query_attribute_byte_get_data_offset(packet), 270 sdp_event_query_attribute_byte_get_data(packet)); 271 break; 272 case 0x0100: 273 // get service name 274 handleServiceNameData(sdp_event_query_attribute_byte_get_attribute_length(packet), 275 sdp_event_query_attribute_byte_get_data_offset(packet), 276 sdp_event_query_attribute_byte_get_data(packet)); 277 break; 278 default: 279 // give up 280 return; 281 } 282 break; 283 case SDP_EVENT_QUERY_COMPLETE: 284 // handle service without a name 285 if (sdp_rfcomm_channel_nr){ 286 sdp_rfcomm_query_emit_service(); 287 } 288 (*sdp_app_callback)(HCI_EVENT_PACKET, 0, packet, size); 289 break; 290 } 291 // insert higher level code HERE 292 } 293 294 void sdp_client_query_rfcomm_init(void){ 295 // init 296 de_state_init(&de_header_state); 297 de_state_init(&sn_de_header_state); 298 pdl_state = GET_PROTOCOL_LIST_LENGTH; 299 protocol_offset = 0; 300 sdp_rfcomm_channel_nr = 0; 301 sdp_service_name[0] = 0; 302 } 303 304 // Public API 305 306 void sdp_client_query_rfcomm_channel_and_name_for_search_pattern(btstack_packet_handler_t callback, bd_addr_t remote, uint8_t * serviceSearchPattern){ 307 if (!sdp_client_ready()){ 308 sdp_client_query_rfcomm_emit_busy(callback); 309 return; 310 } 311 sdp_app_callback = callback; 312 sdp_client_query_rfcomm_init(); 313 sdp_client_query(&handle_sdp_parser_event, remote, serviceSearchPattern, (uint8_t*)&des_attributeIDList[0]); 314 } 315 316 void sdp_client_query_rfcomm_channel_and_name_for_uuid(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid){ 317 if (!sdp_client_ready()){ 318 sdp_client_query_rfcomm_emit_busy(callback); 319 return; 320 } 321 big_endian_store_16(des_serviceSearchPattern, 3, uuid); 322 sdp_client_query_rfcomm_channel_and_name_for_search_pattern(callback, remote, (uint8_t*)des_serviceSearchPattern); 323 } 324