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 #define BTSTACK_FILE__ "sdp_client_rfcomm.c" 39 40 /* 41 * sdp_rfcomm_query.c 42 */ 43 44 #include <stdint.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 49 #include "bluetooth_sdp.h" 50 #include "btstack_debug.h" 51 #include "btstack_event.h" 52 #include "classic/core.h" 53 #include "classic/sdp_client.h" 54 #include "classic/sdp_client_rfcomm.h" 55 #include "classic/sdp_util.h" 56 #include "hci_cmd.h" 57 58 // called by test/sdp_client 59 void sdp_client_query_rfcomm_init(void); 60 61 typedef enum { 62 GET_PROTOCOL_LIST_LENGTH = 1, 63 GET_PROTOCOL_LENGTH, 64 GET_PROTOCOL_ID_HEADER_LENGTH, 65 GET_PROTOCOL_ID, 66 GET_PROTOCOL_VALUE_LENGTH, 67 GET_PROTOCOL_VALUE 68 } pdl_state_t; 69 70 71 // higher layer query - get rfcomm channel and name 72 73 // All attributes: 0x0001 - 0x0100 74 static const uint8_t des_attributeIDList[] = { 0x35, 0x05, 0x0A, 0x00, 0x01, 0x01, 0x00}; 75 76 static uint8_t sdp_service_name[SDP_SERVICE_NAME_LEN+1]; 77 static uint8_t sdp_service_name_len = 0; 78 static uint8_t sdp_rfcomm_channel_nr = 0; 79 static uint8_t sdp_service_name_header_size; 80 81 static pdl_state_t pdl_state = GET_PROTOCOL_LIST_LENGTH; 82 static int protocol_value_bytes_received = 0; 83 static uint16_t protocol_id = 0; 84 static int protocol_offset; 85 static int protocol_size; 86 static int protocol_id_bytes_to_read; 87 static int protocol_value_size; 88 static de_state_t de_header_state; 89 static de_state_t sn_de_header_state; 90 static btstack_packet_handler_t sdp_app_callback; 91 // 92 93 static void sdp_rfcomm_query_emit_service(void){ 94 uint8_t event[3+SDP_SERVICE_NAME_LEN+1]; 95 event[0] = SDP_EVENT_QUERY_RFCOMM_SERVICE; 96 event[1] = sdp_service_name_len + 1; 97 event[2] = sdp_rfcomm_channel_nr; 98 (void)memcpy(&event[3], sdp_service_name, sdp_service_name_len); 99 event[3+sdp_service_name_len] = 0; 100 (*sdp_app_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 101 sdp_rfcomm_channel_nr = 0; 102 } 103 104 static void sdp_client_query_rfcomm_handle_protocol_descriptor_list_data(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){ 105 UNUSED(attribute_value_length); 106 107 // init state on first byte 108 if (data_offset == 0){ 109 pdl_state = GET_PROTOCOL_LIST_LENGTH; 110 } 111 112 // log_info("sdp_client_query_rfcomm_handle_protocol_descriptor_list_data (%u,%u) %02x", attribute_value_length, data_offset, data); 113 114 switch(pdl_state){ 115 116 case GET_PROTOCOL_LIST_LENGTH: 117 if (!de_state_size(data, &de_header_state)) break; 118 // log_info(" query: PD List payload is %d bytes.", de_header_state.de_size); 119 // log_info(" query: PD List offset %u, list size %u", de_header_state.de_offset, de_header_state.de_size); 120 121 pdl_state = GET_PROTOCOL_LENGTH; 122 break; 123 124 case GET_PROTOCOL_LENGTH: 125 // check size 126 if (!de_state_size(data, &de_header_state)) break; 127 // log_info(" query: PD Record payload is %d bytes.", de_header_state.de_size); 128 129 // cache protocol info 130 protocol_offset = de_header_state.de_offset; 131 protocol_size = de_header_state.de_size; 132 133 pdl_state = GET_PROTOCOL_ID_HEADER_LENGTH; 134 break; 135 136 case GET_PROTOCOL_ID_HEADER_LENGTH: 137 protocol_offset++; 138 if (!de_state_size(data, &de_header_state)) break; 139 140 protocol_id = 0; 141 protocol_id_bytes_to_read = de_header_state.de_size; 142 // log_info(" query: ID data is stored in %d bytes.", protocol_id_bytes_to_read); 143 pdl_state = GET_PROTOCOL_ID; 144 145 break; 146 147 case GET_PROTOCOL_ID: 148 protocol_offset++; 149 150 protocol_id = (protocol_id << 8) | data; 151 protocol_id_bytes_to_read--; 152 if (protocol_id_bytes_to_read > 0) break; 153 154 // log_info(" query: Protocol ID: %04x.", protocol_id); 155 156 if (protocol_offset >= protocol_size){ 157 pdl_state = GET_PROTOCOL_LENGTH; 158 // log_info(" query: Get next protocol"); 159 break; 160 } 161 162 pdl_state = GET_PROTOCOL_VALUE_LENGTH; 163 protocol_value_bytes_received = 0; 164 break; 165 166 case GET_PROTOCOL_VALUE_LENGTH: 167 protocol_offset++; 168 169 if (!de_state_size(data, &de_header_state)) break; 170 171 protocol_value_size = de_header_state.de_size; 172 pdl_state = GET_PROTOCOL_VALUE; 173 sdp_rfcomm_channel_nr = 0; 174 break; 175 176 case GET_PROTOCOL_VALUE: 177 protocol_offset++; 178 protocol_value_bytes_received++; 179 180 // log_info(" query: protocol_value_bytes_received %u, protocol_value_size %u", protocol_value_bytes_received, protocol_value_size); 181 182 if (protocol_value_bytes_received < protocol_value_size) break; 183 184 if (protocol_id == BLUETOOTH_PROTOCOL_RFCOMM){ 185 // log_info("\n\n ******* Data ***** %02x\n\n", data); 186 sdp_rfcomm_channel_nr = data; 187 } 188 189 // log_info(" query: protocol done"); 190 // log_info(" query: Protocol offset %u, protocol size %u", protocol_offset, protocol_size); 191 192 if (protocol_offset >= protocol_size) { 193 pdl_state = GET_PROTOCOL_LENGTH; 194 break; 195 196 } 197 pdl_state = GET_PROTOCOL_ID_HEADER_LENGTH; 198 // log_info(" query: Get next protocol"); 199 break; 200 default: 201 break; 202 } 203 } 204 205 static void sdp_client_query_rfcomm_handle_service_name_data(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){ 206 207 // Get Header Len 208 if (data_offset == 0){ 209 de_state_size(data, &sn_de_header_state); 210 sdp_service_name_header_size = sn_de_header_state.addon_header_bytes + 1; 211 return; 212 } 213 214 // Get Header 215 if (data_offset < sdp_service_name_header_size){ 216 de_state_size(data, &sn_de_header_state); 217 return; 218 } 219 220 // Process payload 221 int name_len = attribute_value_length - sdp_service_name_header_size; 222 int name_pos = data_offset - sdp_service_name_header_size; 223 224 if (name_pos < SDP_SERVICE_NAME_LEN){ 225 sdp_service_name[name_pos] = data; 226 name_pos++; 227 228 // terminate if name complete 229 if (name_pos >= name_len){ 230 sdp_service_name[name_pos] = 0; 231 sdp_service_name_len = name_pos; 232 } 233 234 // terminate if buffer full 235 if (name_pos == SDP_SERVICE_NAME_LEN){ 236 sdp_service_name[name_pos] = 0; 237 sdp_service_name_len = name_pos; 238 } 239 } 240 241 // notify on last char 242 if ((data_offset == (attribute_value_length - 1)) && (sdp_rfcomm_channel_nr!=0)){ 243 sdp_rfcomm_query_emit_service(); 244 } 245 } 246 247 static void sdp_client_query_rfcomm_handle_sdp_parser_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 248 UNUSED(packet_type); 249 UNUSED(channel); 250 251 switch (hci_event_packet_get_type(packet)){ 252 case SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE: 253 // handle service without a name 254 if (sdp_rfcomm_channel_nr){ 255 sdp_rfcomm_query_emit_service(); 256 } 257 258 // prepare for new record 259 sdp_rfcomm_channel_nr = 0; 260 sdp_service_name[0] = 0; 261 break; 262 case SDP_EVENT_QUERY_ATTRIBUTE_VALUE: 263 // log_info("sdp_client_query_rfcomm_handle_sdp_parser_event [ AID, ALen, DOff, Data] : [%x, %u, %u] BYTE %02x", 264 // ve->attribute_id, sdp_event_query_attribute_byte_get_attribute_length(packet), 265 // sdp_event_query_attribute_byte_get_data_offset(packet), sdp_event_query_attribute_byte_get_data(packet)); 266 switch (sdp_event_query_attribute_byte_get_attribute_id(packet)){ 267 case BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST: 268 // find rfcomm channel 269 sdp_client_query_rfcomm_handle_protocol_descriptor_list_data(sdp_event_query_attribute_byte_get_attribute_length(packet), 270 sdp_event_query_attribute_byte_get_data_offset(packet), 271 sdp_event_query_attribute_byte_get_data(packet)); 272 break; 273 case 0x0100: 274 // get service name 275 sdp_client_query_rfcomm_handle_service_name_data(sdp_event_query_attribute_byte_get_attribute_length(packet), 276 sdp_event_query_attribute_byte_get_data_offset(packet), 277 sdp_event_query_attribute_byte_get_data(packet)); 278 break; 279 default: 280 // give up 281 return; 282 } 283 break; 284 case SDP_EVENT_QUERY_COMPLETE: 285 // handle service without a name 286 if (sdp_rfcomm_channel_nr){ 287 sdp_rfcomm_query_emit_service(); 288 } 289 (*sdp_app_callback)(HCI_EVENT_PACKET, 0, packet, size); 290 break; 291 } 292 // insert higher level code HERE 293 } 294 295 void sdp_client_query_rfcomm_init(void){ 296 // init 297 de_state_init(&de_header_state); 298 de_state_init(&sn_de_header_state); 299 pdl_state = GET_PROTOCOL_LIST_LENGTH; 300 protocol_offset = 0; 301 sdp_rfcomm_channel_nr = 0; 302 sdp_service_name[0] = 0; 303 } 304 305 // Public API 306 307 uint8_t sdp_client_query_rfcomm_channel_and_name_for_search_pattern(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t * service_search_pattern){ 308 if (!sdp_client_ready()) return SDP_QUERY_BUSY; 309 310 sdp_app_callback = callback; 311 sdp_client_query_rfcomm_init(); 312 return sdp_client_query(&sdp_client_query_rfcomm_handle_sdp_parser_event, remote, service_search_pattern, (uint8_t*)&des_attributeIDList[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 uuid16){ 316 if (!sdp_client_ready()) return SDP_QUERY_BUSY; 317 return sdp_client_query_rfcomm_channel_and_name_for_search_pattern(callback, remote, sdp_service_search_pattern_for_uuid16(uuid16)); 318 } 319 320 uint8_t sdp_client_query_rfcomm_channel_and_name_for_uuid128(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t * uuid128){ 321 if (!sdp_client_ready()) return SDP_QUERY_BUSY; 322 return sdp_client_query_rfcomm_channel_and_name_for_search_pattern(callback, remote, sdp_service_search_pattern_for_uuid128(uuid128)); 323 } 324