xref: /btstack/src/classic/sdp_client.c (revision 8257e5f9e1a9f15ac2fe1e69adc5d2eeeadf3fff)
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_client.c
40  */
41 
42 #include "btstack_config.h"
43 #include "classic/sdp_client.h"
44 
45 #include "hci_cmd.h"
46 
47 #include "btstack_event.h"
48 #include "l2cap.h"
49 #include "classic/sdp_server.h"
50 #include "classic/sdp_util.h"
51 #include "btstack_debug.h"
52 
53 // Types SDP Parser - Data Element stream helper
54 typedef enum {
55     GET_LIST_LENGTH = 1,
56     GET_RECORD_LENGTH,
57     GET_ATTRIBUTE_ID_HEADER_LENGTH,
58     GET_ATTRIBUTE_ID,
59     GET_ATTRIBUTE_VALUE_LENGTH,
60     GET_ATTRIBUTE_VALUE
61 } sdp_parser_state_t;
62 
63 // Types SDP Client
64 typedef enum {
65     INIT, W4_CONNECT, W2_SEND, W4_RESPONSE, QUERY_COMPLETE
66 } sdp_client_state_t;
67 
68 
69 // Prototypes SDP Parser
70 void sdp_parser_init(btstack_packet_handler_t callback);
71 void sdp_parser_handle_chunk(uint8_t * data, uint16_t size);
72 void sdp_parser_handle_done(uint8_t status);
73 void sdp_parser_init_service_attribute_search(void);
74 void sdp_parser_init_service_search(void);
75 void sdp_parser_handle_service_search(uint8_t * data, uint16_t total_count, uint16_t record_handle_count);
76 
77 // Prototypes SDP Client
78 void sdp_client_reset(void);
79 void sdp_client_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
80 static uint16_t sdp_client_setup_service_search_attribute_request(uint8_t * data);
81 #ifdef ENABLE_SDP_EXTRA_QUERIES
82 static uint16_t sdp_client_setup_service_search_request(uint8_t * data);
83 static uint16_t sdp_client_setup_service_attribute_request(uint8_t * data);
84 static void     sdp_client_parse_service_search_response(uint8_t* packet);
85 static void     sdp_client_parse_service_attribute_response(uint8_t* packet);
86 #endif
87 
88 static uint8_t des_attributeIDList[] = { 0x35, 0x05, 0x0A, 0x00, 0x01, 0xff, 0xff};  // Attribute: 0x0001 - 0x0100
89 
90 // State DES Parser
91 static de_state_t de_header_state;
92 
93 // State SDP Parser
94 static sdp_parser_state_t  state = GET_LIST_LENGTH;
95 static uint16_t attribute_id = 0;
96 static uint16_t attribute_bytes_received = 0;
97 static uint16_t attribute_bytes_delivered = 0;
98 static uint16_t list_offset = 0;
99 static uint16_t list_size;
100 static uint16_t record_offset = 0;
101 static uint16_t record_size;
102 static uint16_t attribute_value_size;
103 static int record_counter = 0;
104 static btstack_packet_handler_t sdp_parser_callback;
105 
106 // State SDP Client
107 static uint16_t  mtu;
108 static uint16_t  sdp_cid = 0x40;
109 static const uint8_t * service_search_pattern;
110 static const uint8_t * attribute_id_list;
111 static uint16_t  transactionID = 0;
112 static uint8_t   continuationState[16];
113 static uint8_t   continuationStateLen;
114 static sdp_client_state_t sdp_client_state = INIT;
115 static SDP_PDU_ID_t PDU_ID = SDP_Invalid;
116 #ifdef ENABLE_SDP_EXTRA_QUERIES
117 static uint32_t serviceRecordHandle;
118 static uint32_t record_handle;
119 #endif
120 
121 // DES Parser
122 void de_state_init(de_state_t * de_state){
123     de_state->in_state_GET_DE_HEADER_LENGTH = 1;
124     de_state->addon_header_bytes = 0;
125     de_state->de_size = 0;
126     de_state->de_offset = 0;
127 }
128 
129 int de_state_size(uint8_t eventByte, de_state_t *de_state){
130     if (de_state->in_state_GET_DE_HEADER_LENGTH){
131         de_state->addon_header_bytes = de_get_header_size(&eventByte) - 1;
132         de_state->de_size = 0;
133         de_state->de_offset = 0;
134 
135         if (de_state->addon_header_bytes == 0){
136             de_state->de_size = de_get_data_size(&eventByte);
137             if (de_state->de_size == 0) {
138                 log_error("  ERROR: ID size is zero");
139             }
140             // log_info("Data element payload is %d bytes.", de_state->de_size);
141             return 1;
142         }
143         de_state->in_state_GET_DE_HEADER_LENGTH = 0;
144         return 0;
145     }
146 
147     if (de_state->addon_header_bytes > 0){
148         de_state->de_size = (de_state->de_size << 8) | eventByte;
149         de_state->addon_header_bytes--;
150     }
151     if (de_state->addon_header_bytes > 0) return 0;
152     // log_info("Data element payload is %d bytes.", de_state->de_size);
153     de_state->in_state_GET_DE_HEADER_LENGTH = 1;
154     return 1;
155 }
156 
157 // SDP Parser
158 static void sdp_parser_emit_value_byte(uint8_t event_byte){
159     uint8_t event[11];
160     event[0] = SDP_EVENT_QUERY_ATTRIBUTE_VALUE;
161     event[1] = 9;
162     little_endian_store_16(event, 2, record_counter);
163     little_endian_store_16(event, 4, attribute_id);
164     little_endian_store_16(event, 6, attribute_value_size);
165     little_endian_store_16(event, 8, attribute_bytes_delivered);
166     event[10] = event_byte;
167     (*sdp_parser_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
168 }
169 
170 static void sdp_parser_process_byte(uint8_t eventByte){
171     // count all bytes
172     list_offset++;
173     record_offset++;
174 
175     // log_info(" parse BYTE_RECEIVED %02x", eventByte);
176     switch(state){
177         case GET_LIST_LENGTH:
178             if (!de_state_size(eventByte, &de_header_state)) break;
179             list_offset = de_header_state.de_offset;
180             list_size = de_header_state.de_size;
181             // log_info("parser: List offset %u, list size %u", list_offset, list_size);
182 
183             record_counter = 0;
184             state = GET_RECORD_LENGTH;
185             break;
186 
187         case GET_RECORD_LENGTH:
188             // check size
189             if (!de_state_size(eventByte, &de_header_state)) break;
190             // log_info("parser: Record payload is %d bytes.", de_header_state.de_size);
191             record_offset = de_header_state.de_offset;
192             record_size = de_header_state.de_size;
193             state = GET_ATTRIBUTE_ID_HEADER_LENGTH;
194             break;
195 
196         case GET_ATTRIBUTE_ID_HEADER_LENGTH:
197             if (!de_state_size(eventByte, &de_header_state)) break;
198             attribute_id = 0;
199             log_info("ID data is stored in %d bytes.", (int) de_header_state.de_size);
200             state = GET_ATTRIBUTE_ID;
201             break;
202 
203         case GET_ATTRIBUTE_ID:
204             attribute_id = (attribute_id << 8) | eventByte;
205             de_header_state.de_size--;
206             if (de_header_state.de_size > 0) break;
207             log_info("parser: Attribute ID: %04x.", attribute_id);
208 
209             state = GET_ATTRIBUTE_VALUE_LENGTH;
210             attribute_bytes_received  = 0;
211             attribute_bytes_delivered = 0;
212             attribute_value_size      = 0;
213             de_state_init(&de_header_state);
214             break;
215 
216         case GET_ATTRIBUTE_VALUE_LENGTH:
217             attribute_bytes_received++;
218             sdp_parser_emit_value_byte(eventByte);
219             attribute_bytes_delivered++;
220             if (!de_state_size(eventByte, &de_header_state)) break;
221 
222             attribute_value_size = de_header_state.de_size + attribute_bytes_received;
223 
224             state = GET_ATTRIBUTE_VALUE;
225             break;
226 
227         case GET_ATTRIBUTE_VALUE:
228             attribute_bytes_received++;
229             sdp_parser_emit_value_byte(eventByte);
230             attribute_bytes_delivered++;
231             // log_info("paser: attribute_bytes_received %u, attribute_value_size %u", attribute_bytes_received, attribute_value_size);
232 
233             if (attribute_bytes_received < attribute_value_size) break;
234             // log_info("parser: Record offset %u, record size %u", record_offset, record_size);
235             if (record_offset != record_size){
236                 state = GET_ATTRIBUTE_ID_HEADER_LENGTH;
237                 // log_info("Get next attribute");
238                 break;
239             }
240             record_offset = 0;
241             // log_info("parser: List offset %u, list size %u", list_offset, list_size);
242 
243             if (list_size > 0 && list_offset != list_size){
244                 record_counter++;
245                 state = GET_RECORD_LENGTH;
246                 log_info("parser: END_OF_RECORD");
247                 break;
248             }
249             list_offset = 0;
250             de_state_init(&de_header_state);
251             state = GET_LIST_LENGTH;
252             record_counter = 0;
253             log_info("parser: END_OF_RECORD & DONE");
254             break;
255         default:
256             break;
257     }
258 }
259 
260 void sdp_parser_init(btstack_packet_handler_t callback){
261     // init
262     sdp_parser_callback = callback;
263     de_state_init(&de_header_state);
264     state = GET_LIST_LENGTH;
265     list_offset = 0;
266     record_offset = 0;
267     record_counter = 0;
268 }
269 
270 void sdp_parser_handle_chunk(uint8_t * data, uint16_t size){
271     int i;
272     for (i=0;i<size;i++){
273         sdp_parser_process_byte(data[i]);
274     }
275 }
276 
277 #ifdef ENABLE_SDP_EXTRA_QUERIES
278 void sdp_parser_init_service_attribute_search(void){
279     // init
280     de_state_init(&de_header_state);
281     state = GET_RECORD_LENGTH;
282     list_offset = 0;
283     record_offset = 0;
284     record_counter = 0;
285 }
286 
287 void sdp_parser_init_service_search(void){
288     record_offset = 0;
289 }
290 
291 void sdp_parser_handle_service_search(uint8_t * data, uint16_t total_count, uint16_t record_handle_count){
292     int i;
293     for (i=0;i<record_handle_count;i++){
294         record_handle = big_endian_read_32(data, i*4);
295         record_counter++;
296         uint8_t event[10];
297         event[0] = SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE;
298         event[1] = 8;
299         little_endian_store_16(event, 2, total_count);
300         little_endian_store_16(event, 4, record_counter);
301         little_endian_store_32(event, 6, record_handle);
302         (*sdp_parser_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
303     }
304 }
305 #endif
306 
307 void sdp_parser_handle_done(uint8_t status){
308     uint8_t event[3];
309     event[0] = SDP_EVENT_QUERY_COMPLETE;
310     event[1] = 1;
311     event[2] = status;
312     (*sdp_parser_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
313 }
314 
315 static void sdp_client_emit_busy(btstack_packet_handler_t callback){
316     log_error("sdp_client query initiated when not ready");
317     uint8_t event[] = { SDP_EVENT_QUERY_COMPLETE, 1, SDP_QUERY_BUSY};
318     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
319 }
320 
321 // SDP Client
322 
323 // TODO: inline if not needed (des(des))
324 
325 static int sdp_client_can_send_now(uint16_t channel){
326     if (sdp_client_state != W2_SEND) return 0;
327     if (!l2cap_can_send_packet_now(channel)) return 0;
328     return 1;
329 }
330 
331 static void sdp_client_parse_attribute_lists(uint8_t* packet, uint16_t length){
332     sdp_parser_handle_chunk(packet, length);
333 }
334 
335 
336 static void sdp_client_send_request(uint16_t channel){
337     l2cap_reserve_packet_buffer();
338     uint8_t * data = l2cap_get_outgoing_buffer();
339     uint16_t request_len = 0;
340 
341     switch (PDU_ID){
342 #ifdef ENABLE_SDP_EXTRA_QUERIES
343         case SDP_ServiceSearchResponse:
344             request_len = sdp_client_setup_service_search_request(data);
345             break;
346         case SDP_ServiceAttributeResponse:
347             request_len = sdp_client_setup_service_attribute_request(data);
348             break;
349 #endif
350         case SDP_ServiceSearchAttributeResponse:
351             request_len = sdp_client_setup_service_search_attribute_request(data);
352             break;
353         default:
354             log_error("SDP Client sdp_client_send_request :: PDU ID invalid. %u", PDU_ID);
355             return;
356     }
357 
358     // prevent re-entrance
359     sdp_client_state = W4_RESPONSE;
360     int err = l2cap_send_prepared(channel, request_len);
361     // l2cap_send_prepared shouldn't have failed as l2ap_can_send_packet_now() was true
362     switch (err){
363         case 0:
364             log_debug("l2cap_send() -> OK");
365             PDU_ID = SDP_Invalid;
366             break;
367         case BTSTACK_ACL_BUFFERS_FULL:
368             sdp_client_state = W2_SEND;
369             log_info("l2cap_send() ->BTSTACK_ACL_BUFFERS_FULL");
370             break;
371         default:
372             sdp_client_state = W2_SEND;
373             log_error("l2cap_send() -> err %d", err);
374             break;
375     }
376 }
377 
378 
379 static void sdp_client_parse_service_search_attribute_response(uint8_t* packet){
380     uint16_t offset = 3;
381     uint16_t parameterLength = big_endian_read_16(packet,offset);
382     offset+=2;
383     // AttributeListByteCount <= mtu
384     uint16_t attributeListByteCount = big_endian_read_16(packet,offset);
385     offset+=2;
386 
387     if (attributeListByteCount > mtu){
388         log_error("Error parsing ServiceSearchAttributeResponse: Number of bytes in found attribute list is larger then the MaximumAttributeByteCount.");
389         return;
390     }
391 
392     // AttributeLists
393     sdp_client_parse_attribute_lists(packet+offset, attributeListByteCount);
394     offset+=attributeListByteCount;
395 
396     continuationStateLen = packet[offset];
397     offset++;
398 
399     if (continuationStateLen > 16){
400         log_error("Error parsing ServiceSearchAttributeResponse: Number of bytes in continuation state exceedes 16.");
401         return;
402     }
403     memcpy(continuationState, packet+offset, continuationStateLen);
404     offset+=continuationStateLen;
405 
406     if (parameterLength != offset - 5){
407         log_error("Error parsing ServiceSearchAttributeResponse: wrong size of parameters, number of expected bytes%u, actual number %u.", parameterLength, offset);
408     }
409 }
410 
411 void sdp_client_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
412     // uint16_t handle;
413     if (packet_type == L2CAP_DATA_PACKET){
414         uint16_t responseTransactionID = big_endian_read_16(packet,1);
415         if ( responseTransactionID != transactionID){
416             log_error("Missmatching transaction ID, expected %u, found %u.", transactionID, responseTransactionID);
417             return;
418         }
419 
420         if (packet[0] != SDP_ServiceSearchAttributeResponse
421             && packet[0] != SDP_ServiceSearchResponse
422             && packet[0] != SDP_ServiceAttributeResponse){
423             log_error("Not a valid PDU ID, expected %u, %u or %u, found %u.", SDP_ServiceSearchResponse,
424                                     SDP_ServiceAttributeResponse, SDP_ServiceSearchAttributeResponse, packet[0]);
425             return;
426         }
427 
428         PDU_ID = (SDP_PDU_ID_t)packet[0];
429         log_info("SDP Client :: PDU ID. %u ,%u", PDU_ID, packet[0]);
430         switch (PDU_ID){
431 #ifdef ENABLE_SDP_EXTRA_QUERIES
432             case SDP_ServiceSearchResponse:
433                 sdp_client_parse_service_search_response(packet);
434                 break;
435             case SDP_ServiceAttributeResponse:
436                 sdp_client_parse_service_attribute_response(packet);
437                 break;
438 #endif
439             case SDP_ServiceSearchAttributeResponse:
440                 sdp_client_parse_service_search_attribute_response(packet);
441                 break;
442             default:
443                 log_error("SDP Client :: PDU ID invalid. %u ,%u", PDU_ID, packet[0]);
444                 return;
445         }
446 
447         // continuation set or DONE?
448         if (continuationStateLen == 0){
449             log_info("SDP Client Query DONE! ");
450             sdp_client_state = QUERY_COMPLETE;
451             l2cap_disconnect(sdp_cid, 0);
452             // sdp_parser_handle_done(0);
453             return;
454         }
455         // prepare next request and send
456         sdp_client_state = W2_SEND;
457         if (sdp_client_can_send_now(sdp_cid)) sdp_client_send_request(sdp_cid);
458         return;
459     }
460 
461     if (packet_type != HCI_EVENT_PACKET) return;
462 
463     switch(hci_event_packet_get_type(packet)){
464         case L2CAP_EVENT_CHANNEL_OPENED:
465             if (sdp_client_state != W4_CONNECT) break;
466             // data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16), local_mtu(16), remote_mtu(16)
467             if (packet[2]) {
468                 log_error("SDP Client Connection failed.");
469                 sdp_parser_handle_done(packet[2]);
470                 break;
471             }
472             sdp_cid = channel;
473             mtu = little_endian_read_16(packet, 17);
474             // handle = little_endian_read_16(packet, 9);
475             log_info("SDP Client Connected, cid %x, mtu %u.", sdp_cid, mtu);
476 
477             sdp_client_state = W2_SEND;
478             if (sdp_client_can_send_now(sdp_cid)) sdp_client_send_request(sdp_cid);
479 
480             break;
481         case L2CAP_EVENT_CAN_SEND_NOW:
482             if (sdp_client_can_send_now(sdp_cid)) sdp_client_send_request(sdp_cid);
483             break;
484         case L2CAP_EVENT_CHANNEL_CLOSED: {
485             if (sdp_cid != little_endian_read_16(packet, 2)) {
486                 // log_info("Received L2CAP_EVENT_CHANNEL_CLOSED for cid %x, current cid %x\n",  little_endian_read_16(packet, 2),sdp_cid);
487                 break;
488             }
489             log_info("SDP Client disconnected.");
490             uint8_t status = sdp_client_state == QUERY_COMPLETE ? 0 : SDP_QUERY_INCOMPLETE;
491             sdp_client_state = INIT;
492             sdp_parser_handle_done(status);
493             break;
494         }
495         default:
496             break;
497     }
498 }
499 
500 
501 static uint16_t sdp_client_setup_service_search_attribute_request(uint8_t * data){
502 
503     uint16_t offset = 0;
504     transactionID++;
505     // uint8_t SDP_PDU_ID_t.SDP_ServiceSearchRequest;
506     data[offset++] = SDP_ServiceSearchAttributeRequest;
507     // uint16_t transactionID
508     big_endian_store_16(data, offset, transactionID);
509     offset += 2;
510 
511     // param legnth
512     offset += 2;
513 
514     // parameters:
515     //     Service_search_pattern - DES (min 1 UUID, max 12)
516     uint16_t service_search_pattern_len = de_get_len(service_search_pattern);
517     memcpy(data + offset, service_search_pattern, service_search_pattern_len);
518     offset += service_search_pattern_len;
519 
520     //     MaximumAttributeByteCount - uint16_t  0x0007 - 0xffff -> mtu
521     big_endian_store_16(data, offset, mtu);
522     offset += 2;
523 
524     //     AttibuteIDList
525     uint16_t attribute_id_list_len = de_get_len(attribute_id_list);
526     memcpy(data + offset, attribute_id_list, attribute_id_list_len);
527     offset += attribute_id_list_len;
528 
529     //     ContinuationState - uint8_t number of cont. bytes N<=16
530     data[offset++] = continuationStateLen;
531     //                       - N-bytes previous response from server
532     memcpy(data + offset, continuationState, continuationStateLen);
533     offset += continuationStateLen;
534 
535     // uint16_t paramLength
536     big_endian_store_16(data, 3, offset - 5);
537 
538     return offset;
539 }
540 
541 #ifdef ENABLE_SDP_EXTRA_QUERIES
542 void sdp_client_parse_service_record_handle_list(uint8_t* packet, uint16_t total_count, uint16_t current_count){
543     sdp_parser_handle_service_search(packet, total_count, current_count);
544 }
545 
546 static uint16_t sdp_client_setup_service_search_request(uint8_t * data){
547     uint16_t offset = 0;
548     transactionID++;
549     // uint8_t SDP_PDU_ID_t.SDP_ServiceSearchRequest;
550     data[offset++] = SDP_ServiceSearchRequest;
551     // uint16_t transactionID
552     big_endian_store_16(data, offset, transactionID);
553     offset += 2;
554 
555     // param legnth
556     offset += 2;
557 
558     // parameters:
559     //     Service_search_pattern - DES (min 1 UUID, max 12)
560     uint16_t service_search_pattern_len = de_get_len(service_search_pattern);
561     memcpy(data + offset, service_search_pattern, service_search_pattern_len);
562     offset += service_search_pattern_len;
563 
564     //     MaximumAttributeByteCount - uint16_t  0x0007 - 0xffff -> mtu
565     big_endian_store_16(data, offset, mtu);
566     offset += 2;
567 
568     //     ContinuationState - uint8_t number of cont. bytes N<=16
569     data[offset++] = continuationStateLen;
570     //                       - N-bytes previous response from server
571     memcpy(data + offset, continuationState, continuationStateLen);
572     offset += continuationStateLen;
573 
574     // uint16_t paramLength
575     big_endian_store_16(data, 3, offset - 5);
576 
577     return offset;
578 }
579 
580 
581 static uint16_t sdp_client_setup_service_attribute_request(uint8_t * data){
582 
583     uint16_t offset = 0;
584     transactionID++;
585     // uint8_t SDP_PDU_ID_t.SDP_ServiceSearchRequest;
586     data[offset++] = SDP_ServiceAttributeRequest;
587     // uint16_t transactionID
588     big_endian_store_16(data, offset, transactionID);
589     offset += 2;
590 
591     // param legnth
592     offset += 2;
593 
594     // parameters:
595     //     ServiceRecordHandle
596     big_endian_store_32(data, offset, serviceRecordHandle);
597     offset += 4;
598 
599     //     MaximumAttributeByteCount - uint16_t  0x0007 - 0xffff -> mtu
600     big_endian_store_16(data, offset, mtu);
601     offset += 2;
602 
603     //     AttibuteIDList
604     uint16_t attribute_id_list_len = de_get_len(attribute_id_list);
605     memcpy(data + offset, attribute_id_list, attribute_id_list_len);
606     offset += attribute_id_list_len;
607 
608     //     ContinuationState - uint8_t number of cont. bytes N<=16
609     data[offset++] = continuationStateLen;
610     //                       - N-bytes previous response from server
611     memcpy(data + offset, continuationState, continuationStateLen);
612     offset += continuationStateLen;
613 
614     // uint16_t paramLength
615     big_endian_store_16(data, 3, offset - 5);
616 
617     return offset;
618 }
619 
620 static void sdp_client_parse_service_search_response(uint8_t* packet){
621     uint16_t offset = 3;
622     uint16_t parameterLength = big_endian_read_16(packet,offset);
623     offset+=2;
624 
625     uint16_t totalServiceRecordCount = big_endian_read_16(packet,offset);
626     offset+=2;
627 
628     uint16_t currentServiceRecordCount = big_endian_read_16(packet,offset);
629     offset+=2;
630     if (currentServiceRecordCount > totalServiceRecordCount){
631         log_error("CurrentServiceRecordCount is larger then TotalServiceRecordCount.");
632         return;
633     }
634 
635     sdp_client_parse_service_record_handle_list(packet+offset, totalServiceRecordCount, currentServiceRecordCount);
636     offset+=(currentServiceRecordCount * 4);
637 
638     continuationStateLen = packet[offset];
639     offset++;
640     if (continuationStateLen > 16){
641         log_error("Error parsing ServiceSearchResponse: Number of bytes in continuation state exceedes 16.");
642         return;
643     }
644     memcpy(continuationState, packet+offset, continuationStateLen);
645     offset+=continuationStateLen;
646 
647     if (parameterLength != offset - 5){
648         log_error("Error parsing ServiceSearchResponse: wrong size of parameters, number of expected bytes%u, actual number %u.", parameterLength, offset);
649     }
650 }
651 
652 static void sdp_client_parse_service_attribute_response(uint8_t* packet){
653     uint16_t offset = 3;
654     uint16_t parameterLength = big_endian_read_16(packet,offset);
655     offset+=2;
656 
657     // AttributeListByteCount <= mtu
658     uint16_t attributeListByteCount = big_endian_read_16(packet,offset);
659     offset+=2;
660 
661     if (attributeListByteCount > mtu){
662         log_error("Error parsing ServiceSearchAttributeResponse: Number of bytes in found attribute list is larger then the MaximumAttributeByteCount.");
663         return;
664     }
665 
666     // AttributeLists
667     sdp_client_parse_attribute_lists(packet+offset, attributeListByteCount);
668     offset+=attributeListByteCount;
669 
670     continuationStateLen = packet[offset];
671     offset++;
672 
673     if (continuationStateLen > 16){
674         log_error("Error parsing ServiceAttributeResponse: Number of bytes in continuation state exceedes 16.");
675         return;
676     }
677     memcpy(continuationState, packet+offset, continuationStateLen);
678     offset+=continuationStateLen;
679 
680     if (parameterLength != offset - 5){
681         log_error("Error parsing ServiceAttributeResponse: wrong size of parameters, number of expected bytes%u, actual number %u.", parameterLength, offset);
682     }
683 }
684 #endif
685 
686 // for testing only
687 void sdp_client_reset(void){
688     sdp_client_state = INIT;
689 }
690 
691 // Public API
692 
693 int sdp_client_ready(void){
694     return sdp_client_state == INIT;
695 }
696 
697 void sdp_client_query(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t * des_service_search_pattern, const uint8_t * des_attribute_id_list){
698     if (!sdp_client_ready()) {
699         sdp_client_emit_busy(callback);
700         return;
701     }
702     sdp_parser_init(callback);
703     service_search_pattern = des_service_search_pattern;
704     attribute_id_list = des_attribute_id_list;
705     continuationStateLen = 0;
706     PDU_ID = SDP_ServiceSearchAttributeResponse;
707 
708     sdp_client_state = W4_CONNECT;
709     l2cap_create_channel(sdp_client_packet_handler, remote, PSM_SDP, l2cap_max_mtu(), NULL);
710 }
711 
712 void sdp_client_query_uuid16(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid){
713     if (!sdp_client_ready()){
714         sdp_client_emit_busy(callback);
715         return;
716     }
717     uint8_t * service_service_search_pattern = sdp_service_search_pattern_for_uuid16(uuid);
718     sdp_client_query(callback, remote, service_service_search_pattern, des_attributeIDList);
719 }
720 
721 void sdp_client_query_uuid128(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t* uuid){
722     if (!sdp_client_ready()){
723         sdp_client_emit_busy(callback);
724         return;
725     }
726     uint8_t * service_service_search_pattern = sdp_service_search_pattern_for_uuid128(uuid);
727     sdp_client_query(callback, remote, service_service_search_pattern, des_attributeIDList);
728 }
729 
730 #ifdef ENABLE_SDP_EXTRA_QUERIES
731 void sdp_client_service_attribute_search(btstack_packet_handler_t callback, bd_addr_t remote, uint32_t search_service_record_handle, uint8_t * des_attribute_id_list){
732     if (!sdp_client_ready()) {
733         sdp_client_emit_busy(callback);
734         return;
735     }
736     sdp_parser_init(callback);
737     serviceRecordHandle = search_service_record_handle;
738     attribute_id_list = des_attribute_id_list;
739     continuationStateLen = 0;
740     PDU_ID = SDP_ServiceAttributeResponse;
741 
742     sdp_client_state = W4_CONNECT;
743     l2cap_create_channel(sdp_client_packet_handler, remote, PSM_SDP, l2cap_max_mtu(), NULL);
744 }
745 
746 void sdp_client_service_search(btstack_packet_handler_t callback, bd_addr_t remote, uint8_t * des_service_search_pattern){
747     if (!sdp_client_ready()) {
748         sdp_client_emit_busy(callback);
749         return;
750     }
751     sdp_parser_init(callback);
752     service_search_pattern = des_service_search_pattern;
753     continuationStateLen = 0;
754     PDU_ID = SDP_ServiceSearchResponse;
755 
756     sdp_client_state = W4_CONNECT;
757     l2cap_create_channel(sdp_client_packet_handler, remote, PSM_SDP, l2cap_max_mtu(), NULL);
758 }
759 #endif
760 
761