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_service_search_pattern[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_handle_protocol_descriptor_list_data(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){ 103 UNUSED(attribute_value_length); 104 105 // init state on first byte 106 if (data_offset == 0){ 107 pdl_state = GET_PROTOCOL_LIST_LENGTH; 108 } 109 110 // log_info("sdp_client_query_rfcomm_handle_protocol_descriptor_list_data (%u,%u) %02x", attribute_value_length, data_offset, data); 111 112 switch(pdl_state){ 113 114 case GET_PROTOCOL_LIST_LENGTH: 115 if (!de_state_size(data, &de_header_state)) break; 116 // log_info(" query: PD List payload is %d bytes.", de_header_state.de_size); 117 // log_info(" query: PD List offset %u, list size %u", de_header_state.de_offset, de_header_state.de_size); 118 119 pdl_state = GET_PROTOCOL_LENGTH; 120 break; 121 122 case GET_PROTOCOL_LENGTH: 123 // check size 124 if (!de_state_size(data, &de_header_state)) break; 125 // log_info(" query: PD Record payload is %d bytes.", de_header_state.de_size); 126 127 // cache protocol info 128 protocol_offset = de_header_state.de_offset; 129 protocol_size = de_header_state.de_size; 130 131 pdl_state = GET_PROTOCOL_ID_HEADER_LENGTH; 132 break; 133 134 case GET_PROTOCOL_ID_HEADER_LENGTH: 135 protocol_offset++; 136 if (!de_state_size(data, &de_header_state)) break; 137 138 protocol_id = 0; 139 protocol_id_bytes_to_read = de_header_state.de_size; 140 // log_info(" query: ID data is stored in %d bytes.", protocol_id_bytes_to_read); 141 pdl_state = GET_PROTOCOL_ID; 142 143 break; 144 145 case GET_PROTOCOL_ID: 146 protocol_offset++; 147 148 protocol_id = (protocol_id << 8) | data; 149 protocol_id_bytes_to_read--; 150 if (protocol_id_bytes_to_read > 0) break; 151 152 // log_info(" query: Protocol ID: %04x.", protocol_id); 153 154 if (protocol_offset >= protocol_size){ 155 pdl_state = GET_PROTOCOL_LENGTH; 156 // log_info(" query: Get next protocol"); 157 break; 158 } 159 160 pdl_state = GET_PROTOCOL_VALUE_LENGTH; 161 protocol_value_bytes_received = 0; 162 break; 163 164 case GET_PROTOCOL_VALUE_LENGTH: 165 protocol_offset++; 166 167 if (!de_state_size(data, &de_header_state)) break; 168 169 protocol_value_size = de_header_state.de_size; 170 pdl_state = GET_PROTOCOL_VALUE; 171 sdp_rfcomm_channel_nr = 0; 172 break; 173 174 case GET_PROTOCOL_VALUE: 175 protocol_offset++; 176 protocol_value_bytes_received++; 177 178 // log_info(" query: protocol_value_bytes_received %u, protocol_value_size %u", protocol_value_bytes_received, protocol_value_size); 179 180 if (protocol_value_bytes_received < protocol_value_size) break; 181 182 if (protocol_id == 0x0003){ 183 // log_info("\n\n ******* Data ***** %02x\n\n", data); 184 sdp_rfcomm_channel_nr = data; 185 } 186 187 // log_info(" query: protocol done"); 188 // log_info(" query: Protocol offset %u, protocol size %u", protocol_offset, protocol_size); 189 190 if (protocol_offset >= protocol_size) { 191 pdl_state = GET_PROTOCOL_LENGTH; 192 break; 193 194 } 195 pdl_state = GET_PROTOCOL_ID_HEADER_LENGTH; 196 // log_info(" query: Get next protocol"); 197 break; 198 default: 199 break; 200 } 201 } 202 203 static void sdp_client_query_rfcomm_handle_service_name_data(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){ 204 205 // Get Header Len 206 if (data_offset == 0){ 207 de_state_size(data, &sn_de_header_state); 208 sdp_service_name_header_size = sn_de_header_state.addon_header_bytes + 1; 209 return; 210 } 211 212 // Get Header 213 if (data_offset < sdp_service_name_header_size){ 214 de_state_size(data, &sn_de_header_state); 215 return; 216 } 217 218 // Process payload 219 int name_len = attribute_value_length - sdp_service_name_header_size; 220 int name_pos = data_offset - sdp_service_name_header_size; 221 222 if (name_pos < SDP_SERVICE_NAME_LEN){ 223 sdp_service_name[name_pos] = data; 224 name_pos++; 225 226 // terminate if name complete 227 if (name_pos >= name_len){ 228 sdp_service_name[name_pos] = 0; 229 sdp_service_name_len = name_pos; 230 } 231 232 // terminate if buffer full 233 if (name_pos == SDP_SERVICE_NAME_LEN){ 234 sdp_service_name[name_pos] = 0; 235 sdp_service_name_len = name_pos; 236 } 237 } 238 239 // notify on last char 240 if (data_offset == attribute_value_length - 1 && sdp_rfcomm_channel_nr!=0){ 241 sdp_rfcomm_query_emit_service(); 242 } 243 } 244 245 static void sdp_client_query_rfcomm_handle_sdp_parser_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 246 UNUSED(packet_type); 247 UNUSED(channel); 248 249 switch (hci_event_packet_get_type(packet)){ 250 case SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE: 251 // handle service without a name 252 if (sdp_rfcomm_channel_nr){ 253 sdp_rfcomm_query_emit_service(); 254 } 255 256 // prepare for new record 257 sdp_rfcomm_channel_nr = 0; 258 sdp_service_name[0] = 0; 259 break; 260 case SDP_EVENT_QUERY_ATTRIBUTE_VALUE: 261 // log_info("sdp_client_query_rfcomm_handle_sdp_parser_event [ AID, ALen, DOff, Data] : [%x, %u, %u] BYTE %02x", 262 // ve->attribute_id, sdp_event_query_attribute_byte_get_attribute_length(packet), 263 // sdp_event_query_attribute_byte_get_data_offset(packet), sdp_event_query_attribute_byte_get_data(packet)); 264 switch (sdp_event_query_attribute_byte_get_attribute_id(packet)){ 265 case SDP_ProtocolDescriptorList: 266 // find rfcomm channel 267 sdp_client_query_rfcomm_handle_protocol_descriptor_list_data(sdp_event_query_attribute_byte_get_attribute_length(packet), 268 sdp_event_query_attribute_byte_get_data_offset(packet), 269 sdp_event_query_attribute_byte_get_data(packet)); 270 break; 271 case 0x0100: 272 // get service name 273 sdp_client_query_rfcomm_handle_service_name_data(sdp_event_query_attribute_byte_get_attribute_length(packet), 274 sdp_event_query_attribute_byte_get_data_offset(packet), 275 sdp_event_query_attribute_byte_get_data(packet)); 276 break; 277 default: 278 // give up 279 return; 280 } 281 break; 282 case SDP_EVENT_QUERY_COMPLETE: 283 // handle service without a name 284 if (sdp_rfcomm_channel_nr){ 285 sdp_rfcomm_query_emit_service(); 286 } 287 (*sdp_app_callback)(HCI_EVENT_PACKET, 0, packet, size); 288 break; 289 } 290 // insert higher level code HERE 291 } 292 293 void sdp_client_query_rfcomm_init(void){ 294 // init 295 de_state_init(&de_header_state); 296 de_state_init(&sn_de_header_state); 297 pdl_state = GET_PROTOCOL_LIST_LENGTH; 298 protocol_offset = 0; 299 sdp_rfcomm_channel_nr = 0; 300 sdp_service_name[0] = 0; 301 } 302 303 // Public API 304 305 uint8_t sdp_client_query_rfcomm_channel_and_name_for_search_pattern(btstack_packet_handler_t callback, bd_addr_t remote, uint8_t * service_search_pattern){ 306 307 if (!sdp_client_ready()) return SDP_QUERY_BUSY; 308 309 sdp_app_callback = callback; 310 sdp_client_query_rfcomm_init(); 311 sdp_client_query(&sdp_client_query_rfcomm_handle_sdp_parser_event, remote, service_search_pattern, (uint8_t*)&des_attributeIDList[0]); 312 return 0; 313 } 314 315 uint8_t sdp_client_query_rfcomm_channel_and_name_for_uuid(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid){ 316 317 if (!sdp_client_ready()) return SDP_QUERY_BUSY; 318 319 big_endian_store_16(des_service_search_pattern, 3, uuid); 320 sdp_client_query_rfcomm_channel_and_name_for_search_pattern(callback, remote, (uint8_t*)des_service_search_pattern); 321 return 0; 322 } 323