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 BLUEKITCHEN
24 * GMBH 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 <string.h>
46
47 #include "bluetooth_sdp.h"
48 #include "btstack_debug.h"
49 #include "btstack_event.h"
50 #include "classic/core.h"
51 #include "classic/sdp_client.h"
52 #include "classic/sdp_client_rfcomm.h"
53 #include "classic/sdp_util.h"
54 #include "hci_cmd.h"
55
56 #if (SDP_SERVICE_NAME_LEN < 16)
57 #error "SDP_SERVICE_NAME_LEN must be at least 16 bytes"
58 #endif
59
60 // called by test/sdp_client
61 void sdp_client_query_rfcomm_init(void);
62
63 static enum {
64 GET_PROTOCOL_LIST_LENGTH = 1,
65 GET_PROTOCOL_LENGTH,
66 GET_PROTOCOL_ID_HEADER_LENGTH,
67 GET_PROTOCOL_ID,
68 GET_PROTOCOL_VALUE_LENGTH,
69 GET_PROTOCOL_VALUE
70 } protocol_descriptor_list_state;
71
72 static enum {
73 GET_SERVICE_LIST_LENGTH = 1,
74 GET_SERVICE_LIST_ITEM_GET_UUID_TYPE,
75 GET_SERVICE_LIST_ITEM,
76 GET_SERVICE_LIST_ITEM_SHORT,
77 GET_SERVICE_LIST_ITEM_LONG,
78 GET_SERVICE_INVALID,
79 } service_class_id_list_state;
80
81 // higher layer query - get rfcomm channel and name
82
83 // All attributes: 0x0001 - 0x0100
84 static const uint8_t des_attribute_id_list[] = {0x35, 0x05, 0x0A, 0x00, 0x01, 0x01, 0x00};
85
86 static uint8_t sdp_client_rfcomm_service_name[SDP_SERVICE_NAME_LEN + 1];
87 static uint8_t sdp_client_rfcomm_service_name_len = 0;
88 static uint8_t sdp_client_rfcomm_channel_nr = 0;
89
90 static uint8_t sdp_client_rfcomm_service_name_header_size;
91
92 static bool sdp_client_rfcomm_servicec_lass_matched;
93 static bool sdp_client_rfcomm_match_service_class;
94 static uint16_t sdp_client_rfcomm_uuid16;
95
96 static int sdp_client_rfcomm_protocol_value_bytes_received = 0;
97 static int sdp_client_rfcomm_protocol_value_size;
98 static int sdp_client_rfcomm_protocol_offset;
99 static int sdp_client_rfcomm_protocol_size;
100 static int sdp_client_rfcomm_protocol_id_bytes_to_read;
101 static uint32_t sdp_client_rfcomm_protocol_id = 0;
102
103 static de_state_t sdp_client_rfcomm_de_header_state;
104 static btstack_packet_handler_t sdp_client_rfcomm_app_callback;
105 //
106
sdp_rfcomm_query_prepare(void)107 static void sdp_rfcomm_query_prepare(void){
108 sdp_client_rfcomm_channel_nr = 0;
109 sdp_client_rfcomm_service_name[0] = 0;
110 sdp_client_rfcomm_servicec_lass_matched = false;
111 }
112
sdp_rfcomm_query_emit_service(void)113 static void sdp_rfcomm_query_emit_service(void){
114 uint8_t event[3+SDP_SERVICE_NAME_LEN+1];
115 event[0] = SDP_EVENT_QUERY_RFCOMM_SERVICE;
116 event[1] = sdp_client_rfcomm_service_name_len + 2;
117 event[2] = sdp_client_rfcomm_channel_nr;
118 (void)memcpy(&event[3], sdp_client_rfcomm_service_name, sdp_client_rfcomm_service_name_len);
119 event[3 + sdp_client_rfcomm_service_name_len] = 0;
120 (*sdp_client_rfcomm_app_callback)(HCI_EVENT_PACKET, 0, event, 3 + sdp_client_rfcomm_service_name_len + 1);
121 }
122
sdp_client_query_rfcomm_handle_record_parsed(void)123 static void sdp_client_query_rfcomm_handle_record_parsed(void){
124 if (sdp_client_rfcomm_channel_nr == 0) return;
125 if (sdp_client_rfcomm_match_service_class && (sdp_client_rfcomm_servicec_lass_matched == false)) return;
126 sdp_rfcomm_query_emit_service();
127 sdp_rfcomm_query_prepare();
128 }
129
130 // Format: DE Sequence of UUIDs
sdp_client_query_rfcomm_handle_service_class_list_data(uint32_t attribute_value_length,uint32_t data_offset,uint8_t data)131 static void sdp_client_query_rfcomm_handle_service_class_list_data(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){
132 UNUSED(attribute_value_length);
133
134 // init state on first byte
135 if (data_offset == 0){
136 service_class_id_list_state = GET_SERVICE_LIST_LENGTH;
137 de_state_init(&sdp_client_rfcomm_de_header_state);
138 }
139
140 // process data
141 switch(service_class_id_list_state){
142
143 case GET_SERVICE_LIST_LENGTH:
144 // read DES sequence header
145 if (!de_state_size(data, &sdp_client_rfcomm_de_header_state)) break;
146 service_class_id_list_state = GET_SERVICE_LIST_ITEM_GET_UUID_TYPE;
147 break;
148
149 case GET_SERVICE_LIST_ITEM_GET_UUID_TYPE:
150 sdp_client_rfcomm_protocol_id = 0;
151 sdp_client_rfcomm_protocol_offset = 0;
152 // validate UUID type
153 if (de_get_element_type(&data) != DE_UUID) {
154 service_class_id_list_state = GET_SERVICE_INVALID;
155 break;
156 }
157 // get UUID length
158 sdp_client_rfcomm_protocol_id_bytes_to_read = de_get_data_size(&data);
159 if (sdp_client_rfcomm_protocol_id_bytes_to_read > 16) {
160 service_class_id_list_state = GET_SERVICE_INVALID;
161 break;
162 }
163 service_class_id_list_state = GET_SERVICE_LIST_ITEM;
164 break;
165
166 case GET_SERVICE_LIST_ITEM:
167 sdp_client_rfcomm_service_name[sdp_client_rfcomm_protocol_offset++] = data;
168 sdp_client_rfcomm_protocol_id_bytes_to_read--;
169 if (sdp_client_rfcomm_protocol_id_bytes_to_read > 0) break;
170 // parse 2/4/16 bytes UUID
171 switch (sdp_client_rfcomm_protocol_offset){
172 case 2:
173 sdp_client_rfcomm_protocol_id = big_endian_read_16(sdp_client_rfcomm_service_name, 0);
174 break;
175 case 4:
176 sdp_client_rfcomm_protocol_id = big_endian_read_32(sdp_client_rfcomm_service_name, 0);
177 break;
178 case 16:
179 if (uuid_has_bluetooth_prefix(sdp_client_rfcomm_service_name)){
180 sdp_client_rfcomm_protocol_id = big_endian_read_32(sdp_client_rfcomm_service_name, 0);
181 }
182 break;
183 default:
184 break;
185 }
186 if (sdp_client_rfcomm_protocol_id == sdp_client_rfcomm_uuid16){
187 sdp_client_rfcomm_servicec_lass_matched = true;
188 }
189 service_class_id_list_state = GET_SERVICE_LIST_ITEM_GET_UUID_TYPE;
190 break;
191
192 default:
193 break;
194 }
195 }
196
sdp_client_query_rfcomm_handle_protocol_descriptor_list_data(uint32_t attribute_value_length,uint32_t data_offset,uint8_t data)197 static void sdp_client_query_rfcomm_handle_protocol_descriptor_list_data(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){
198 UNUSED(attribute_value_length);
199
200 // init state on first byte
201 if (data_offset == 0){
202 de_state_init(&sdp_client_rfcomm_de_header_state);
203 protocol_descriptor_list_state = GET_PROTOCOL_LIST_LENGTH;
204 }
205
206 switch(protocol_descriptor_list_state){
207
208 case GET_PROTOCOL_LIST_LENGTH:
209 if (!de_state_size(data, &sdp_client_rfcomm_de_header_state)) break;
210
211 protocol_descriptor_list_state = GET_PROTOCOL_LENGTH;
212 break;
213
214 case GET_PROTOCOL_LENGTH:
215 // check size
216 if (!de_state_size(data, &sdp_client_rfcomm_de_header_state)) break;
217
218 // cache protocol info
219 sdp_client_rfcomm_protocol_offset = sdp_client_rfcomm_de_header_state.de_offset;
220 sdp_client_rfcomm_protocol_size = sdp_client_rfcomm_de_header_state.de_size;
221
222 protocol_descriptor_list_state = GET_PROTOCOL_ID_HEADER_LENGTH;
223 break;
224
225 case GET_PROTOCOL_ID_HEADER_LENGTH:
226 sdp_client_rfcomm_protocol_offset++;
227 if (!de_state_size(data, &sdp_client_rfcomm_de_header_state)) break;
228
229 sdp_client_rfcomm_protocol_id = 0;
230 sdp_client_rfcomm_protocol_id_bytes_to_read = sdp_client_rfcomm_de_header_state.de_size;
231 protocol_descriptor_list_state = GET_PROTOCOL_ID;
232
233 break;
234
235 case GET_PROTOCOL_ID:
236 sdp_client_rfcomm_protocol_offset++;
237
238 sdp_client_rfcomm_protocol_id = (sdp_client_rfcomm_protocol_id << 8) | data;
239 sdp_client_rfcomm_protocol_id_bytes_to_read--;
240 if (sdp_client_rfcomm_protocol_id_bytes_to_read > 0) break;
241
242
243 if (sdp_client_rfcomm_protocol_offset >= sdp_client_rfcomm_protocol_size){
244 protocol_descriptor_list_state = GET_PROTOCOL_LENGTH;
245 break;
246 }
247
248 protocol_descriptor_list_state = GET_PROTOCOL_VALUE_LENGTH;
249 sdp_client_rfcomm_protocol_value_bytes_received = 0;
250 break;
251
252 case GET_PROTOCOL_VALUE_LENGTH:
253 sdp_client_rfcomm_protocol_offset++;
254
255 if (!de_state_size(data, &sdp_client_rfcomm_de_header_state)) break;
256
257 sdp_client_rfcomm_protocol_value_size = sdp_client_rfcomm_de_header_state.de_size;
258 protocol_descriptor_list_state = GET_PROTOCOL_VALUE;
259 sdp_client_rfcomm_channel_nr = 0;
260 break;
261
262 case GET_PROTOCOL_VALUE:
263 sdp_client_rfcomm_protocol_offset++;
264 sdp_client_rfcomm_protocol_value_bytes_received++;
265
266 if (sdp_client_rfcomm_protocol_value_bytes_received < sdp_client_rfcomm_protocol_value_size) break;
267
268 if (sdp_client_rfcomm_protocol_id == BLUETOOTH_PROTOCOL_RFCOMM){
269 // log_info("\n\n ******* Data ***** %02x\n\n", data);
270 sdp_client_rfcomm_channel_nr = data;
271 }
272
273 if (sdp_client_rfcomm_protocol_offset >= sdp_client_rfcomm_protocol_size) {
274 protocol_descriptor_list_state = GET_PROTOCOL_LENGTH;
275 break;
276
277 }
278 protocol_descriptor_list_state = GET_PROTOCOL_ID_HEADER_LENGTH;
279 break;
280 default:
281 break;
282 }
283 }
284
sdp_client_query_rfcomm_handle_service_name_data(uint32_t attribute_value_length,uint32_t data_offset,uint8_t data)285 static void sdp_client_query_rfcomm_handle_service_name_data(uint32_t attribute_value_length, uint32_t data_offset, uint8_t data){
286
287 // Get Header Len
288 if (data_offset == 0){
289 de_state_init(&sdp_client_rfcomm_de_header_state);
290 de_state_size(data, &sdp_client_rfcomm_de_header_state);
291 sdp_client_rfcomm_service_name_header_size = sdp_client_rfcomm_de_header_state.addon_header_bytes + 1;
292 return;
293 }
294
295 // Get Header
296 if (data_offset < sdp_client_rfcomm_service_name_header_size){
297 de_state_size(data, &sdp_client_rfcomm_de_header_state);
298 return;
299 }
300
301 // Process payload
302 int name_len = attribute_value_length - sdp_client_rfcomm_service_name_header_size;
303 int name_pos = data_offset - sdp_client_rfcomm_service_name_header_size;
304
305 if (name_pos < SDP_SERVICE_NAME_LEN){
306 sdp_client_rfcomm_service_name[name_pos] = data;
307 name_pos++;
308
309 // terminate if name complete
310 if (name_pos >= name_len){
311 sdp_client_rfcomm_service_name[name_pos] = 0;
312 sdp_client_rfcomm_service_name_len = name_pos;
313 }
314
315 // terminate if buffer full
316 if (name_pos == SDP_SERVICE_NAME_LEN){
317 sdp_client_rfcomm_service_name[name_pos] = 0;
318 sdp_client_rfcomm_service_name_len = name_pos;
319 }
320 }
321
322 // notify on last char
323 if ((data_offset == (attribute_value_length - 1)) && (sdp_client_rfcomm_channel_nr != 0)){
324 sdp_client_query_rfcomm_handle_record_parsed();
325 }
326 }
327
sdp_client_query_rfcomm_handle_sdp_parser_event(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)328 static void sdp_client_query_rfcomm_handle_sdp_parser_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
329 UNUSED(packet_type);
330 UNUSED(channel);
331
332 switch (hci_event_packet_get_type(packet)){
333 case SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE:
334 sdp_client_query_rfcomm_handle_record_parsed();
335
336 // prepare for new record
337 sdp_rfcomm_query_prepare();
338 break;
339 case SDP_EVENT_QUERY_ATTRIBUTE_VALUE:
340 switch (sdp_event_query_attribute_byte_get_attribute_id(packet)){
341 case BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST:
342 if (sdp_client_rfcomm_match_service_class){
343 sdp_client_query_rfcomm_handle_service_class_list_data(sdp_event_query_attribute_byte_get_attribute_length(packet),
344 sdp_event_query_attribute_byte_get_data_offset(packet),
345 sdp_event_query_attribute_byte_get_data(packet));
346 }
347 break;
348 case BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST:
349 // find rfcomm channel
350 sdp_client_query_rfcomm_handle_protocol_descriptor_list_data(sdp_event_query_attribute_byte_get_attribute_length(packet),
351 sdp_event_query_attribute_byte_get_data_offset(packet),
352 sdp_event_query_attribute_byte_get_data(packet));
353 break;
354 case 0x0100:
355 // get service name
356 sdp_client_query_rfcomm_handle_service_name_data(sdp_event_query_attribute_byte_get_attribute_length(packet),
357 sdp_event_query_attribute_byte_get_data_offset(packet),
358 sdp_event_query_attribute_byte_get_data(packet));
359 break;
360 default:
361 // give up
362 return;
363 }
364 break;
365 case SDP_EVENT_QUERY_COMPLETE:
366 sdp_client_query_rfcomm_handle_record_parsed();
367 (*sdp_client_rfcomm_app_callback)(HCI_EVENT_PACKET, 0, packet, size);
368 break;
369 default:
370 break;
371 }
372 }
373
sdp_client_query_rfcomm_init(void)374 void sdp_client_query_rfcomm_init(void){
375 // init
376 protocol_descriptor_list_state = GET_PROTOCOL_LIST_LENGTH;
377 sdp_client_rfcomm_protocol_offset = 0;
378 sdp_client_rfcomm_channel_nr = 0;
379 sdp_client_rfcomm_service_name[0] = 0;
380 }
381
sdp_client_query_rfcomm(btstack_packet_handler_t callback,bd_addr_t remote,const uint8_t * service_search_pattern)382 static uint8_t sdp_client_query_rfcomm(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t * service_search_pattern){
383 sdp_client_rfcomm_app_callback = callback;
384 sdp_client_query_rfcomm_init();
385 return sdp_client_query(&sdp_client_query_rfcomm_handle_sdp_parser_event, remote, service_search_pattern, (uint8_t*)&des_attribute_id_list[0]);
386 }
387
388 // Public API
389
sdp_client_query_rfcomm_channel_and_name_for_uuid(btstack_packet_handler_t callback,bd_addr_t remote,uint16_t uuid16)390 uint8_t sdp_client_query_rfcomm_channel_and_name_for_uuid(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid16){
391 if (!sdp_client_ready()) return SDP_QUERY_BUSY;
392 sdp_client_rfcomm_match_service_class = false;
393 return sdp_client_query_rfcomm(callback, remote, sdp_service_search_pattern_for_uuid16(uuid16));
394 }
395
sdp_client_query_rfcomm_channel_and_name_for_service_class_uuid(btstack_packet_handler_t callback,bd_addr_t remote,uint16_t uuid16)396 uint8_t sdp_client_query_rfcomm_channel_and_name_for_service_class_uuid(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid16){
397 if (!sdp_client_ready()) return SDP_QUERY_BUSY;
398 sdp_client_rfcomm_match_service_class = true;
399 sdp_client_rfcomm_uuid16 = uuid16;
400 return sdp_client_query_rfcomm(callback, remote, sdp_service_search_pattern_for_uuid16(uuid16));
401 }
402
sdp_client_query_rfcomm_channel_and_name_for_uuid128(btstack_packet_handler_t callback,bd_addr_t remote,const uint8_t * uuid128)403 uint8_t sdp_client_query_rfcomm_channel_and_name_for_uuid128(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t * uuid128){
404 if (!sdp_client_ready()) return SDP_QUERY_BUSY;
405 sdp_client_rfcomm_match_service_class = false;
406 return sdp_client_query_rfcomm(callback, remote, sdp_service_search_pattern_for_uuid128(uuid128));
407 }
408
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)409 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){
410 if (!sdp_client_ready()) return SDP_QUERY_BUSY;
411 sdp_client_rfcomm_match_service_class = false;
412 return sdp_client_query_rfcomm(callback, remote, service_search_pattern);
413 }
414