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