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