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/sdp_client.h" 50 #include "classic/sdp_client_rfcomm.h" 51 #include "classic/sdp_util.h" 52 #include "hci_cmd.h" 53 54 // called by test/sdp_client 55 void sdp_client_query_rfcomm_init(void); 56 57 typedef enum { 58 GET_PROTOCOL_LIST_LENGTH = 1, 59 GET_PROTOCOL_LENGTH, 60 GET_PROTOCOL_ID_HEADER_LENGTH, 61 GET_PROTOCOL_ID, 62 GET_PROTOCOL_VALUE_LENGTH, 63 GET_PROTOCOL_VALUE 64 } pdl_state_t; 65 66 67 // higher layer query - get rfcomm channel and name 68 69 const uint8_t des_attributeIDList[] = { 0x35, 0x05, 0x0A, 0x00, 0x01, 0x01, 0x00}; // Arribute: 0x0001 - 0x0100 70 71 static uint8_t des_serviceSearchPattern[5] = {0x35, 0x03, 0x19, 0x00, 0x00}; 72 73 static uint8_t sdp_service_name[SDP_SERVICE_NAME_LEN+1]; 74 static uint8_t sdp_service_name_len = 0; 75 static uint8_t sdp_rfcomm_channel_nr = 0; 76 static uint8_t sdp_service_name_header_size; 77 78 static pdl_state_t pdl_state = GET_PROTOCOL_LIST_LENGTH; 79 static int protocol_value_bytes_received = 0; 80 static uint16_t protocol_id = 0; 81 static int protocol_offset; 82 static int protocol_size; 83 static int protocol_id_bytes_to_read; 84 static int protocol_value_size; 85 static de_state_t de_header_state; 86 static de_state_t sn_de_header_state; 87 static btstack_packet_handler_t sdp_app_callback; 88 // 89 90 static void sdp_rfcomm_query_emit_service(void){ 91 uint8_t event[3+SDP_SERVICE_NAME_LEN+1]; 92 event[0] = SDP_EVENT_QUERY_RFCOMM_SERVICE; 93 event[1] = sdp_service_name_len + 1; 94 event[2] = sdp_rfcomm_channel_nr; 95 memcpy(&event[3], sdp_service_name, sdp_service_name_len); 96 event[3+sdp_service_name_len] = 0; 97 (*sdp_app_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 98 sdp_rfcomm_channel_nr = 0; 99 } 100 101 static void sdp_client_query_rfcomm_emit_busy(btstack_packet_handler_t callback){ 102 log_error("sdp_client_query_rfcomm started when not ready"); 103 uint8_t event[] = { SDP_EVENT_QUERY_COMPLETE, 1, SDP_QUERY_BUSY}; 104 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 105 } 106 107 static void handleProtocolDescriptorListData(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){ 108 // init state on first byte 109 if (data_offset == 0){ 110 pdl_state = GET_PROTOCOL_LIST_LENGTH; 111 } 112 113 // log_info("handleProtocolDescriptorListData (%u,%u) %02x", attribute_value_length, data_offset, data); 114 115 switch(pdl_state){ 116 117 case GET_PROTOCOL_LIST_LENGTH: 118 if (!de_state_size(data, &de_header_state)) break; 119 // log_info(" query: PD List payload is %d bytes.", de_header_state.de_size); 120 // log_info(" query: PD List offset %u, list size %u", de_header_state.de_offset, de_header_state.de_size); 121 122 pdl_state = GET_PROTOCOL_LENGTH; 123 break; 124 125 case GET_PROTOCOL_LENGTH: 126 // check size 127 if (!de_state_size(data, &de_header_state)) break; 128 // log_info(" query: PD Record payload is %d bytes.", de_header_state.de_size); 129 130 // cache protocol info 131 protocol_offset = de_header_state.de_offset; 132 protocol_size = de_header_state.de_size; 133 134 pdl_state = GET_PROTOCOL_ID_HEADER_LENGTH; 135 break; 136 137 case GET_PROTOCOL_ID_HEADER_LENGTH: 138 protocol_offset++; 139 if (!de_state_size(data, &de_header_state)) break; 140 141 protocol_id = 0; 142 protocol_id_bytes_to_read = de_header_state.de_size; 143 // log_info(" query: ID data is stored in %d bytes.", protocol_id_bytes_to_read); 144 pdl_state = GET_PROTOCOL_ID; 145 146 break; 147 148 case GET_PROTOCOL_ID: 149 protocol_offset++; 150 151 protocol_id = (protocol_id << 8) | data; 152 protocol_id_bytes_to_read--; 153 if (protocol_id_bytes_to_read > 0) break; 154 155 // log_info(" query: Protocol ID: %04x.", protocol_id); 156 157 if (protocol_offset >= protocol_size){ 158 pdl_state = GET_PROTOCOL_LENGTH; 159 // log_info(" query: Get next protocol"); 160 break; 161 } 162 163 pdl_state = GET_PROTOCOL_VALUE_LENGTH; 164 protocol_value_bytes_received = 0; 165 break; 166 167 case GET_PROTOCOL_VALUE_LENGTH: 168 protocol_offset++; 169 170 if (!de_state_size(data, &de_header_state)) break; 171 172 protocol_value_size = de_header_state.de_size; 173 pdl_state = GET_PROTOCOL_VALUE; 174 sdp_rfcomm_channel_nr = 0; 175 break; 176 177 case GET_PROTOCOL_VALUE: 178 protocol_offset++; 179 protocol_value_bytes_received++; 180 181 // log_info(" query: protocol_value_bytes_received %u, protocol_value_size %u", protocol_value_bytes_received, protocol_value_size); 182 183 if (protocol_value_bytes_received < protocol_value_size) break; 184 185 if (protocol_id == 0x0003){ 186 // log_info("\n\n ******* Data ***** %02x\n\n", data); 187 sdp_rfcomm_channel_nr = data; 188 } 189 190 // log_info(" query: protocol done"); 191 // log_info(" query: Protocol offset %u, protocol size %u", protocol_offset, protocol_size); 192 193 if (protocol_offset >= protocol_size) { 194 pdl_state = GET_PROTOCOL_LENGTH; 195 break; 196 197 } 198 pdl_state = GET_PROTOCOL_ID_HEADER_LENGTH; 199 // log_info(" query: Get next protocol"); 200 break; 201 default: 202 break; 203 } 204 } 205 206 static void handleServiceNameData(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){ 207 208 // Get Header Len 209 if (data_offset == 0){ 210 de_state_size(data, &sn_de_header_state); 211 sdp_service_name_header_size = sn_de_header_state.addon_header_bytes + 1; 212 return; 213 } 214 215 // Get Header 216 if (data_offset < sdp_service_name_header_size){ 217 de_state_size(data, &sn_de_header_state); 218 return; 219 } 220 221 // Process payload 222 int name_len = attribute_value_length - sdp_service_name_header_size; 223 int name_pos = data_offset - sdp_service_name_header_size; 224 225 if (name_pos < SDP_SERVICE_NAME_LEN){ 226 sdp_service_name[name_pos] = data; 227 name_pos++; 228 229 // terminate if name complete 230 if (name_pos >= name_len){ 231 sdp_service_name[name_pos] = 0; 232 sdp_service_name_len = name_pos; 233 } 234 235 // terminate if buffer full 236 if (name_pos == SDP_SERVICE_NAME_LEN){ 237 sdp_service_name[name_pos] = 0; 238 sdp_service_name_len = name_pos; 239 } 240 } 241 242 // notify on last char 243 if (data_offset == attribute_value_length - 1 && sdp_rfcomm_channel_nr!=0){ 244 sdp_rfcomm_query_emit_service(); 245 } 246 } 247 248 static void handle_sdp_parser_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 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("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 handleProtocolDescriptorListData(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 handleServiceNameData(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 void sdp_client_query_rfcomm_channel_and_name_for_search_pattern(btstack_packet_handler_t callback, bd_addr_t remote, uint8_t * serviceSearchPattern){ 306 if (!sdp_client_ready()){ 307 sdp_client_query_rfcomm_emit_busy(callback); 308 return; 309 } 310 sdp_app_callback = callback; 311 sdp_client_query_rfcomm_init(); 312 sdp_client_query(&handle_sdp_parser_event, remote, serviceSearchPattern, (uint8_t*)&des_attributeIDList[0]); 313 } 314 315 void sdp_client_query_rfcomm_channel_and_name_for_uuid(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid){ 316 if (!sdp_client_ready()){ 317 sdp_client_query_rfcomm_emit_busy(callback); 318 return; 319 } 320 big_endian_store_16(des_serviceSearchPattern, 3, uuid); 321 sdp_client_query_rfcomm_channel_and_name_for_search_pattern(callback, remote, (uint8_t*)des_serviceSearchPattern); 322 } 323