xref: /btstack/src/classic/sdp_client_rfcomm.c (revision cd5f23a3250874824c01a2b3326a9522fea3f99f)
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 <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 } protokoll_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_attributeIDList[]    = { 0x35, 0x05, 0x0A, 0x00, 0x01, 0x01, 0x00};
85 
86 static uint8_t  sdp_service_name[SDP_SERVICE_NAME_LEN+1];
87 static uint8_t  sdp_service_name_len = 0;
88 static uint8_t  sdp_rfcomm_channel_nr = 0;
89 
90 static uint8_t  sdp_service_name_header_size;
91 
92 static bool     sdp_client_rfcomm_serviceclass_matched;
93 static bool     sdp_client_rfcomm_match_serviceclass;
94 static uint16_t sdp_client_rfcomm_uuid16;
95 
96 static int      protocol_value_bytes_received = 0;
97 static int      protocol_value_size;
98 static int      protocol_offset;
99 static int      protocol_size;
100 static int      protocol_id_bytes_to_read;
101 static uint32_t protocol_id = 0;
102 
103 static de_state_t de_header_state;
104 static btstack_packet_handler_t sdp_app_callback;
105 //
106 
107 static void sdp_rfcomm_query_prepare(void){
108     sdp_rfcomm_channel_nr = 0;
109     sdp_service_name[0] = 0;
110     sdp_client_rfcomm_serviceclass_matched = false;
111 }
112 
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_service_name_len + 1;
117     event[2] = sdp_rfcomm_channel_nr;
118     (void)memcpy(&event[3], sdp_service_name, sdp_service_name_len);
119     event[3+sdp_service_name_len] = 0;
120     (*sdp_app_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
121 }
122 
123 static void sdp_client_query_rfcomm_handle_record_parsed(void){
124     if (sdp_rfcomm_channel_nr == 0) return;
125     if (sdp_client_rfcomm_match_serviceclass && (sdp_client_rfcomm_serviceclass_matched == false)) return;
126     sdp_rfcomm_query_emit_service();
127     sdp_rfcomm_query_prepare();
128 }
129 
130 // Format: DE Sequence of UUIDs
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(&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, &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             protocol_id = 0;
151             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             protocol_id_bytes_to_read = de_get_data_size(&data);
159             if (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_service_name[protocol_offset++] = data;
168             protocol_id_bytes_to_read--;
169             if (protocol_id_bytes_to_read > 0) break;
170             // parse 2/4/16 bytes UUID
171             switch (protocol_offset){
172                 case 2:
173                     protocol_id = big_endian_read_16(sdp_service_name, 0);
174                     break;
175                 case 4:
176                     protocol_id = big_endian_read_32(sdp_service_name, 0);
177                     break;
178                 case 16:
179                     if (uuid_has_bluetooth_prefix(sdp_service_name)){
180                         protocol_id = big_endian_read_32(sdp_service_name, 0);
181                     }
182                     break;
183                 default:
184                     break;
185             }
186             if (protocol_id == sdp_client_rfcomm_uuid16){
187                 sdp_client_rfcomm_serviceclass_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 
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(&de_header_state);
203         protokoll_descriptor_list_state = GET_PROTOCOL_LIST_LENGTH;
204     }
205 
206     switch(protokoll_descriptor_list_state){
207 
208         case GET_PROTOCOL_LIST_LENGTH:
209             if (!de_state_size(data, &de_header_state)) break;
210 
211             protokoll_descriptor_list_state = GET_PROTOCOL_LENGTH;
212             break;
213 
214         case GET_PROTOCOL_LENGTH:
215             // check size
216             if (!de_state_size(data, &de_header_state)) break;
217 
218             // cache protocol info
219             protocol_offset = de_header_state.de_offset;
220             protocol_size   = de_header_state.de_size;
221 
222             protokoll_descriptor_list_state = GET_PROTOCOL_ID_HEADER_LENGTH;
223             break;
224 
225        case GET_PROTOCOL_ID_HEADER_LENGTH:
226             protocol_offset++;
227             if (!de_state_size(data, &de_header_state)) break;
228 
229             protocol_id = 0;
230             protocol_id_bytes_to_read = de_header_state.de_size;
231             protokoll_descriptor_list_state = GET_PROTOCOL_ID;
232 
233             break;
234 
235         case GET_PROTOCOL_ID:
236             protocol_offset++;
237 
238             protocol_id = (protocol_id << 8) | data;
239             protocol_id_bytes_to_read--;
240             if (protocol_id_bytes_to_read > 0) break;
241 
242 
243             if (protocol_offset >= protocol_size){
244                 protokoll_descriptor_list_state = GET_PROTOCOL_LENGTH;
245                 break;
246             }
247 
248             protokoll_descriptor_list_state = GET_PROTOCOL_VALUE_LENGTH;
249             protocol_value_bytes_received = 0;
250             break;
251 
252         case GET_PROTOCOL_VALUE_LENGTH:
253             protocol_offset++;
254 
255             if (!de_state_size(data, &de_header_state)) break;
256 
257             protocol_value_size = de_header_state.de_size;
258             protokoll_descriptor_list_state = GET_PROTOCOL_VALUE;
259             sdp_rfcomm_channel_nr = 0;
260             break;
261 
262         case GET_PROTOCOL_VALUE:
263             protocol_offset++;
264             protocol_value_bytes_received++;
265 
266             if (protocol_value_bytes_received < protocol_value_size) break;
267 
268             if (protocol_id == BLUETOOTH_PROTOCOL_RFCOMM){
269                 //  log_info("\n\n *******  Data ***** %02x\n\n", data);
270                 sdp_rfcomm_channel_nr = data;
271             }
272 
273             if (protocol_offset >= protocol_size) {
274                 protokoll_descriptor_list_state = GET_PROTOCOL_LENGTH;
275                 break;
276 
277             }
278             protokoll_descriptor_list_state = GET_PROTOCOL_ID_HEADER_LENGTH;
279             break;
280         default:
281             break;
282     }
283 }
284 
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(&de_header_state);
290         de_state_size(data, &de_header_state);
291         sdp_service_name_header_size = de_header_state.addon_header_bytes + 1;
292         return;
293     }
294 
295     // Get Header
296     if (data_offset < sdp_service_name_header_size){
297         de_state_size(data, &de_header_state);
298         return;
299     }
300 
301     // Process payload
302     int name_len = attribute_value_length - sdp_service_name_header_size;
303     int name_pos = data_offset - sdp_service_name_header_size;
304 
305     if (name_pos < SDP_SERVICE_NAME_LEN){
306         sdp_service_name[name_pos] = data;
307         name_pos++;
308 
309         // terminate if name complete
310         if (name_pos >= name_len){
311             sdp_service_name[name_pos] = 0;
312             sdp_service_name_len = name_pos;
313         }
314 
315         // terminate if buffer full
316         if (name_pos == SDP_SERVICE_NAME_LEN){
317             sdp_service_name[name_pos] = 0;
318             sdp_service_name_len = name_pos;
319         }
320     }
321 
322     // notify on last char
323     if ((data_offset == (attribute_value_length - 1)) && (sdp_rfcomm_channel_nr!=0)){
324         sdp_client_query_rfcomm_handle_record_parsed();
325     }
326 }
327 
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_serviceclass){
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_app_callback)(HCI_EVENT_PACKET, 0, packet, size);
368             break;
369         default:
370             break;
371     }
372 }
373 
374 void sdp_client_query_rfcomm_init(void){
375     // init
376     protokoll_descriptor_list_state = GET_PROTOCOL_LIST_LENGTH;
377     protocol_offset = 0;
378     sdp_rfcomm_channel_nr = 0;
379     sdp_service_name[0] = 0;
380 }
381 
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_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_attributeIDList[0]);
386 }
387 
388 // Public API
389 
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_serviceclass = false;
393     return sdp_client_query_rfcomm(callback, remote, sdp_service_search_pattern_for_uuid16(uuid16));
394 }
395 
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_serviceclass = true;
399     sdp_client_rfcomm_uuid16 = uuid16;
400     return sdp_client_query_rfcomm(callback, remote, sdp_service_search_pattern_for_uuid16(uuid16));
401 }
402 
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_serviceclass = false;
406     return sdp_client_query_rfcomm(callback, remote, sdp_service_search_pattern_for_uuid128(uuid128));
407 }
408 
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_serviceclass = false;
412     return sdp_client_query_rfcomm(callback, remote, service_search_pattern);
413 }
414