Fix arm-softmmu breakage
[qemu] / hw / bt-sdp.c
1 /*
2  * Service Discover Protocol server for QEMU L2CAP devices
3  *
4  * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "qemu-common.h"
22 #include "bt.h"
23
24 struct bt_l2cap_sdp_state_s {
25     struct bt_l2cap_conn_params_s *channel;
26
27     struct sdp_service_record_s {
28         int match;
29
30         int *uuid;
31         int uuids;
32         struct sdp_service_attribute_s {
33             int match;
34
35             int attribute_id;
36             int len;
37             void *pair;
38         } *attribute_list;
39         int attributes;
40     } *service_list;
41     int services;
42 };
43
44 static ssize_t sdp_datalen(const uint8_t **element, ssize_t *left)
45 {
46     size_t len = *(*element) ++ & SDP_DSIZE_MASK;
47
48     if (!*left)
49         return -1;
50     (*left) --;
51
52     if (len < SDP_DSIZE_NEXT1)
53         return 1 << len;
54     else if (len == SDP_DSIZE_NEXT1) {
55         if (*left < 1)
56             return -1;
57         (*left) --;
58
59         return *(*element) ++;
60     } else if (len == SDP_DSIZE_NEXT2) {
61         if (*left < 2)
62             return -1;
63         (*left) -= 2;
64
65         len = (*(*element) ++) << 8;
66         return len | (*(*element) ++);
67     } else {
68         if (*left < 4)
69             return -1;
70         (*left) -= 4;
71
72         len = (*(*element) ++) << 24;
73         len |= (*(*element) ++) << 16;
74         len |= (*(*element) ++) << 8;
75         return len | (*(*element) ++);
76     }
77 }
78
79 static const uint8_t bt_base_uuid[12] = {
80     0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb,
81 };
82
83 static int sdp_uuid_match(struct sdp_service_record_s *record,
84                 const uint8_t *uuid, ssize_t datalen)
85 {
86     int *lo, hi, val;
87
88     if (datalen == 16 || datalen == 4) {
89         if (datalen == 16 && memcmp(uuid + 4, bt_base_uuid, 12))
90             return 0;
91
92         if (uuid[0] | uuid[1])
93             return 0;
94         uuid += 2;
95     }
96
97     val = (uuid[0] << 8) | uuid[1];
98     lo = record->uuid;
99     hi = record->uuids;
100     while (hi >>= 1)
101         if (lo[hi] <= val)
102             lo += hi;
103
104     return *lo == val;
105 }
106
107 #define CONTINUATION_PARAM_SIZE (1 + sizeof(int))
108 #define MAX_PDU_OUT_SIZE        96      /* Arbitrary */
109 #define PDU_HEADER_SIZE         5
110 #define MAX_RSP_PARAM_SIZE      (MAX_PDU_OUT_SIZE - PDU_HEADER_SIZE - \
111                 CONTINUATION_PARAM_SIZE)
112
113 static int sdp_svc_match(struct bt_l2cap_sdp_state_s *sdp,
114                 const uint8_t **req, ssize_t *len)
115 {
116     size_t datalen;
117     int i;
118
119     if ((**req & ~SDP_DSIZE_MASK) != SDP_DTYPE_UUID)
120         return 1;
121
122     datalen = sdp_datalen(req, len);
123     if (datalen != 2 && datalen != 4 && datalen != 16)
124         return 1;
125
126     for (i = 0; i < sdp->services; i ++)
127         if (sdp_uuid_match(&sdp->service_list[i], *req, datalen))
128             sdp->service_list[i].match = 1;
129
130     (*req) += datalen;
131     (*len) -= datalen;
132
133     return 0;
134 }
135
136 static ssize_t sdp_svc_search(struct bt_l2cap_sdp_state_s *sdp,
137                 uint8_t *rsp, const uint8_t *req, ssize_t len)
138 {
139     ssize_t seqlen;
140     int i, count, start, end, max;
141     int32_t handle;
142
143     /* Perform the search */
144     for (i = 0; i < sdp->services; i ++)
145         sdp->service_list[i].match = 0;
146
147     if (len < 1)
148         return -SDP_INVALID_SYNTAX;
149     if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
150         seqlen = sdp_datalen(&req, &len);
151         if (seqlen < 3 || len < seqlen)
152             return -SDP_INVALID_SYNTAX;
153         len -= seqlen;
154
155         while (seqlen)
156             if (sdp_svc_match(sdp, &req, &seqlen))
157                 return -SDP_INVALID_SYNTAX;
158     } else if (sdp_svc_match(sdp, &req, &seqlen))
159         return -SDP_INVALID_SYNTAX;
160
161     if (len < 3)
162         return -SDP_INVALID_SYNTAX;
163     end = (req[0] << 8) | req[1];
164     req += 2;
165     len -= 2;
166
167     if (*req) {
168         if (len <= sizeof(int))
169             return -SDP_INVALID_SYNTAX;
170         len -= sizeof(int);
171         memcpy(&start, req + 1, sizeof(int));
172     } else
173         start = 0;
174
175     if (len > 1);
176         return -SDP_INVALID_SYNTAX;
177
178     /* Output the results */
179     len = 4;
180     count = 0;
181     end = start;
182     for (i = 0; i < sdp->services; i ++)
183         if (sdp->service_list[i].match) {
184             if (count >= start && count < max && len + 4 < MAX_RSP_PARAM_SIZE) {
185                 handle = i;
186                 memcpy(rsp + len, &handle, 4);
187                 len += 4;
188                 end = count + 1;
189             }
190
191             count ++;
192         }
193
194     rsp[0] = count >> 8;
195     rsp[1] = count & 0xff;
196     rsp[2] = (end - start) >> 8;
197     rsp[3] = (end - start) & 0xff;
198
199     if (end < count) {
200         rsp[len ++] = sizeof(int);
201         memcpy(rsp + len, &end, sizeof(int));
202         len += 4;
203     } else
204         rsp[len ++] = 0;
205
206     return len;
207 }
208
209 static int sdp_attr_match(struct sdp_service_record_s *record,
210                 const uint8_t **req, ssize_t *len)
211 {
212     int i, start, end;
213
214     if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_2)) {
215         (*req) ++;
216         if (*len < 3)
217             return 1;
218
219         start = (*(*req) ++) << 8;
220         start |= *(*req) ++;
221         end = start;
222         *len -= 3;
223     } else if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_4)) {
224         (*req) ++;
225         if (*len < 5)
226             return 1;
227
228         start = (*(*req) ++) << 8;
229         start |= *(*req) ++;
230         end = (*(*req) ++) << 8;
231         end |= *(*req) ++;
232         *len -= 5;
233     } else
234         return 1;
235
236     for (i = 0; i < record->attributes; i ++)
237         if (record->attribute_list[i].attribute_id >= start &&
238                         record->attribute_list[i].attribute_id <= end)
239             record->attribute_list[i].match = 1;
240
241     return 0;
242 }
243
244 static ssize_t sdp_attr_get(struct bt_l2cap_sdp_state_s *sdp,
245                 uint8_t *rsp, const uint8_t *req, ssize_t len)
246 {
247     ssize_t seqlen;
248     int i, start, end, max;
249     int32_t handle;
250     struct sdp_service_record_s *record;
251     uint8_t *lst;
252
253     /* Perform the search */
254     if (len < 7)
255         return -SDP_INVALID_SYNTAX;
256     memcpy(&handle, req, 4);
257     req += 4;
258     len -= 4;
259
260     if (handle < 0 || handle > sdp->services)
261         return -SDP_INVALID_RECORD_HANDLE;
262     record = &sdp->service_list[handle];
263
264     for (i = 0; i < record->attributes; i ++)
265         record->attribute_list[i].match = 0;
266
267     max = (req[0] << 8) | req[1];
268     req += 2;
269     len -= 2;
270     if (max < 0x0007)
271         return -SDP_INVALID_SYNTAX;
272
273     if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
274         seqlen = sdp_datalen(&req, &len);
275         if (seqlen < 3 || len < seqlen)
276             return -SDP_INVALID_SYNTAX;
277         len -= seqlen;
278
279         while (seqlen)
280             if (sdp_attr_match(record, &req, &seqlen))
281                 return -SDP_INVALID_SYNTAX;
282     } else if (sdp_attr_match(record, &req, &seqlen))
283         return -SDP_INVALID_SYNTAX;
284
285     if (len < 1)
286         return -SDP_INVALID_SYNTAX;
287
288     if (*req) {
289         if (len <= sizeof(int))
290             return -SDP_INVALID_SYNTAX;
291         len -= sizeof(int);
292         memcpy(&start, req + 1, sizeof(int));
293     } else
294         start = 0;
295
296     if (len > 1)
297         return -SDP_INVALID_SYNTAX;
298
299     /* Output the results */
300     lst = rsp + 2;
301     max = MIN(max, MAX_RSP_PARAM_SIZE);
302     len = 3 - start;
303     end = 0;
304     for (i = 0; i < record->attributes; i ++)
305         if (record->attribute_list[i].match) {
306             if (len >= 0 && len + record->attribute_list[i].len < max) {
307                 memcpy(lst + len, record->attribute_list[i].pair,
308                                 record->attribute_list[i].len);
309                 end = len + record->attribute_list[i].len;
310             }
311             len += record->attribute_list[i].len;
312         }
313     if (0 >= start) {
314        lst[0] = SDP_DTYPE_SEQ | SDP_DSIZE_NEXT2;
315        lst[1] = (len + start - 3) >> 8;
316        lst[2] = (len + start - 3) & 0xff;
317     }
318
319     rsp[0] = end >> 8;
320     rsp[1] = end & 0xff;
321
322     if (end < len) {
323         len = end + start;
324         lst[end ++] = sizeof(int);
325         memcpy(lst + end, &len, sizeof(int));
326         end += sizeof(int);
327     } else
328         lst[end ++] = 0;
329
330     return end + 2;
331 }
332
333 static int sdp_svc_attr_match(struct bt_l2cap_sdp_state_s *sdp,
334                 const uint8_t **req, ssize_t *len)
335 {
336     int i, j, start, end;
337     struct sdp_service_record_s *record;
338
339     if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_2)) {
340         (*req) ++;
341         if (*len < 3)
342             return 1;
343
344         start = (*(*req) ++) << 8;
345         start |= *(*req) ++;
346         end = start;
347         *len -= 3;
348     } else if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_4)) {
349         (*req) ++;
350         if (*len < 5)
351             return 1;
352
353         start = (*(*req) ++) << 8;
354         start |= *(*req) ++;
355         end = (*(*req) ++) << 8;
356         end |= *(*req) ++;
357         *len -= 5;
358     } else
359         return 1;
360
361     for (i = 0; i < sdp->services; i ++)
362         if ((record = &sdp->service_list[i])->match)
363             for (j = 0; j < record->attributes; j ++)
364                 if (record->attribute_list[j].attribute_id >= start &&
365                                 record->attribute_list[j].attribute_id <= end)
366                     record->attribute_list[j].match = 1;
367
368     return 0;
369 }
370
371 static ssize_t sdp_svc_search_attr_get(struct bt_l2cap_sdp_state_s *sdp,
372                 uint8_t *rsp, const uint8_t *req, ssize_t len)
373 {
374     ssize_t seqlen;
375     int i, j, start, end, max;
376     struct sdp_service_record_s *record;
377     uint8_t *lst;
378
379     /* Perform the search */
380     for (i = 0; i < sdp->services; i ++) {
381         sdp->service_list[i].match = 0;
382             for (j = 0; j < sdp->service_list[i].attributes; j ++)
383                 sdp->service_list[i].attribute_list[j].match = 0;
384     }
385
386     if (len < 1)
387         return -SDP_INVALID_SYNTAX;
388     if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
389         seqlen = sdp_datalen(&req, &len);
390         if (seqlen < 3 || len < seqlen)
391             return -SDP_INVALID_SYNTAX;
392         len -= seqlen;
393
394         while (seqlen)
395             if (sdp_svc_match(sdp, &req, &seqlen))
396                 return -SDP_INVALID_SYNTAX;
397     } else if (sdp_svc_match(sdp, &req, &seqlen))
398         return -SDP_INVALID_SYNTAX;
399
400     if (len < 3)
401         return -SDP_INVALID_SYNTAX;
402     max = (req[0] << 8) | req[1];
403     req += 2;
404     len -= 2;
405     if (max < 0x0007)
406         return -SDP_INVALID_SYNTAX;
407
408     if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
409         seqlen = sdp_datalen(&req, &len);
410         if (seqlen < 3 || len < seqlen)
411             return -SDP_INVALID_SYNTAX;
412         len -= seqlen;
413
414         while (seqlen)
415             if (sdp_svc_attr_match(sdp, &req, &seqlen))
416                 return -SDP_INVALID_SYNTAX;
417     } else if (sdp_svc_attr_match(sdp, &req, &seqlen))
418         return -SDP_INVALID_SYNTAX;
419
420     if (len < 1)
421         return -SDP_INVALID_SYNTAX;
422
423     if (*req) {
424         if (len <= sizeof(int))
425             return -SDP_INVALID_SYNTAX;
426         len -= sizeof(int);
427         memcpy(&start, req + 1, sizeof(int));
428     } else
429         start = 0;
430
431     if (len > 1)
432         return -SDP_INVALID_SYNTAX;
433
434     /* Output the results */
435     /* This assumes empty attribute lists are never to be returned even
436      * for matching Service Records.  In practice this shouldn't happen
437      * as the requestor will usually include the always present
438      * ServiceRecordHandle AttributeID in AttributeIDList.  */
439     lst = rsp + 2;
440     max = MIN(max, MAX_RSP_PARAM_SIZE);
441     len = 3 - start;
442     end = 0;
443     for (i = 0; i < sdp->services; i ++)
444         if ((record = &sdp->service_list[i])->match) {
445             len += 3;
446             seqlen = len;
447             for (j = 0; j < record->attributes; j ++)
448                 if (record->attribute_list[j].match) {
449                     if (len >= 0)
450                         if (len + record->attribute_list[j].len < max) {
451                             memcpy(lst + len, record->attribute_list[j].pair,
452                                             record->attribute_list[j].len);
453                             end = len + record->attribute_list[j].len;
454                         }
455                     len += record->attribute_list[j].len;
456                 }
457             if (seqlen == len)
458                 len -= 3;
459             else if (seqlen >= 3 && seqlen < max) {
460                 lst[seqlen - 3] = SDP_DTYPE_SEQ | SDP_DSIZE_NEXT2;
461                 lst[seqlen - 2] = (len - seqlen) >> 8;
462                 lst[seqlen - 1] = (len - seqlen) & 0xff;
463             }
464         }
465     if (len == 3 - start)
466         len -= 3;
467     else if (0 >= start) {
468        lst[0] = SDP_DTYPE_SEQ | SDP_DSIZE_NEXT2;
469        lst[1] = (len + start - 3) >> 8;
470        lst[2] = (len + start - 3) & 0xff;
471     }
472
473     rsp[0] = end >> 8;
474     rsp[1] = end & 0xff;
475
476     if (end < len) {
477         len = end + start;
478         lst[end ++] = sizeof(int);
479         memcpy(lst + end, &len, sizeof(int));
480         end += sizeof(int);
481     } else
482         lst[end ++] = 0;
483
484     return end + 2;
485 }
486
487 static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len)
488 {
489     struct bt_l2cap_sdp_state_s *sdp = opaque;
490     enum bt_sdp_cmd pdu_id;
491     uint8_t rsp[MAX_PDU_OUT_SIZE - PDU_HEADER_SIZE], *sdu_out;
492     int transaction_id, plen;
493     int err = 0;
494     int rsp_len = 0;
495
496     if (len < 5) {
497         fprintf(stderr, "%s: short SDP PDU (%iB).\n", __FUNCTION__, len);
498         return;
499     }
500
501     pdu_id = *data ++;
502     transaction_id = (data[0] << 8) | data[1];
503     plen = (data[2] << 8) | data[3];
504     data += 4;
505     len -= 5;
506
507     if (len != plen) {
508         fprintf(stderr, "%s: wrong SDP PDU length (%iB != %iB).\n",
509                         __FUNCTION__, plen, len);
510         err = SDP_INVALID_PDU_SIZE;
511         goto respond;
512     }
513
514     switch (pdu_id) {
515     case SDP_SVC_SEARCH_REQ:
516         rsp_len = sdp_svc_search(sdp, rsp, data, len);
517         pdu_id = SDP_SVC_SEARCH_RSP;
518         break;
519
520     case SDP_SVC_ATTR_REQ:
521         rsp_len = sdp_attr_get(sdp, rsp, data, len);
522         pdu_id = SDP_SVC_ATTR_RSP;
523         break;
524
525     case SDP_SVC_SEARCH_ATTR_REQ:
526         rsp_len = sdp_svc_search_attr_get(sdp, rsp, data, len);
527         pdu_id = SDP_SVC_SEARCH_ATTR_RSP;
528         break;
529
530     case SDP_ERROR_RSP:
531     case SDP_SVC_ATTR_RSP:
532     case SDP_SVC_SEARCH_RSP:
533     case SDP_SVC_SEARCH_ATTR_RSP:
534     default:
535         fprintf(stderr, "%s: unexpected SDP PDU ID %02x.\n",
536                         __FUNCTION__, pdu_id);
537         err = SDP_INVALID_SYNTAX;
538         break;
539     }
540
541     if (rsp_len < 0) {
542         err = -rsp_len;
543         rsp_len = 0;
544     }
545
546 respond:
547     if (err) {
548         pdu_id = SDP_ERROR_RSP;
549         rsp[rsp_len ++] = err >> 8;
550         rsp[rsp_len ++] = err & 0xff;
551     }
552
553     sdu_out = sdp->channel->sdu_out(sdp->channel, rsp_len + PDU_HEADER_SIZE);
554
555     sdu_out[0] = pdu_id;
556     sdu_out[1] = transaction_id >> 8;
557     sdu_out[2] = transaction_id & 0xff;
558     sdu_out[3] = rsp_len >> 8;
559     sdu_out[4] = rsp_len & 0xff;
560     memcpy(sdu_out + PDU_HEADER_SIZE, rsp, rsp_len);
561
562     sdp->channel->sdu_submit(sdp->channel);
563 }
564
565 static void bt_l2cap_sdp_close_ch(void *opaque)
566 {
567     struct bt_l2cap_sdp_state_s *sdp = opaque;
568     int i;
569
570     for (i = 0; i < sdp->services; i ++) {
571         qemu_free(sdp->service_list[i].attribute_list->pair);
572         qemu_free(sdp->service_list[i].attribute_list);
573         qemu_free(sdp->service_list[i].uuid);
574     }
575     qemu_free(sdp->service_list);
576     qemu_free(sdp);
577 }
578
579 struct sdp_def_service_s {
580     uint16_t class_uuid;
581     struct sdp_def_attribute_s {
582         uint16_t id;
583         struct sdp_def_data_element_s {
584             uint8_t type;
585             union {
586                 uint32_t uint;
587                 const char *str;
588                 struct sdp_def_data_element_s *list;
589             } value;
590         } data;
591     } attributes[];
592 };
593
594 /* Calculate a safe byte count to allocate that will store the given
595  * element, at the same time count elements of a UUID type.  */
596 static int sdp_attr_max_size(struct sdp_def_data_element_s *element,
597                 int *uuids)
598 {
599     int type = element->type & ~SDP_DSIZE_MASK;
600     int len;
601
602     if (type == SDP_DTYPE_UINT || type == SDP_DTYPE_UUID ||
603                     type == SDP_DTYPE_BOOL) {
604         if (type == SDP_DTYPE_UUID)
605             (*uuids) ++;
606         return 1 + (1 << (element->type & SDP_DSIZE_MASK));
607     }
608
609     if (type == SDP_DTYPE_STRING || type == SDP_DTYPE_URL) {
610         if (element->type & SDP_DSIZE_MASK) {
611             for (len = 0; element->value.str[len] |
612                             element->value.str[len + 1]; len ++);
613             return len;
614         } else
615             return 2 + strlen(element->value.str);
616     }
617
618     if (type != SDP_DTYPE_SEQ)
619         exit(-1);
620     len = 2;
621     element = element->value.list;
622     while (element->type)
623         len += sdp_attr_max_size(element ++, uuids);
624     if (len > 255)
625         exit (-1);
626
627     return len;
628 }
629
630 static int sdp_attr_write(uint8_t *data,
631                 struct sdp_def_data_element_s *element, int **uuid)
632 {
633     int type = element->type & ~SDP_DSIZE_MASK;
634     int len = 0;
635
636     if (type == SDP_DTYPE_UINT || type == SDP_DTYPE_BOOL) {
637         data[len ++] = element->type;
638         if ((element->type & SDP_DSIZE_MASK) == SDP_DSIZE_1)
639             data[len ++] = (element->value.uint >>  0) & 0xff;
640         else if ((element->type & SDP_DSIZE_MASK) == SDP_DSIZE_2) {
641             data[len ++] = (element->value.uint >>  8) & 0xff;
642             data[len ++] = (element->value.uint >>  0) & 0xff;
643         } else if ((element->type & SDP_DSIZE_MASK) == SDP_DSIZE_4) {
644             data[len ++] = (element->value.uint >>  24) & 0xff;
645             data[len ++] = (element->value.uint >>  16) & 0xff;
646             data[len ++] = (element->value.uint >>  8) & 0xff;
647             data[len ++] = (element->value.uint >>  0) & 0xff;
648         }
649
650         return len;
651     }
652
653     if (type == SDP_DTYPE_UUID) {
654         *(*uuid) ++ = element->value.uint;
655
656         data[len ++] = element->type;
657         data[len ++] = (element->value.uint >>  24) & 0xff;
658         data[len ++] = (element->value.uint >>  16) & 0xff;
659         data[len ++] = (element->value.uint >>  8) & 0xff;
660         data[len ++] = (element->value.uint >>  0) & 0xff;
661         memcpy(data + len, bt_base_uuid, 12);
662
663         return len + 12;
664     }
665
666     data[0] = type | SDP_DSIZE_NEXT1;
667     if (type == SDP_DTYPE_STRING || type == SDP_DTYPE_URL) {
668         if (element->type & SDP_DSIZE_MASK)
669             for (len = 0; element->value.str[len] |
670                             element->value.str[len + 1]; len ++);
671         else
672             len = strlen(element->value.str);
673         memcpy(data + 2, element->value.str, data[1] = len);
674
675         return len + 2;
676     }
677
678     len = 2;
679     element = element->value.list;
680     while (element->type)
681         len += sdp_attr_write(data + len, element ++, uuid);
682     data[1] = len - 2;
683
684     return len;
685 }
686
687 static int sdp_attributeid_compare(const struct sdp_service_attribute_s *a,
688                 const struct sdp_service_attribute_s *b)
689 {
690     return (int) b->attribute_id - a->attribute_id;
691 }
692
693 static int sdp_uuid_compare(const int *a, const int *b)
694 {
695     return *a - *b;
696 }
697
698 static void sdp_service_record_build(struct sdp_service_record_s *record,
699                 struct sdp_def_service_s *def, int handle)
700 {
701     int len = 0;
702     uint8_t *data;
703     int *uuid;
704
705     record->uuids = 0;
706     while (def->attributes[record->attributes].data.type) {
707         len += 3;
708         len += sdp_attr_max_size(&def->attributes[record->attributes ++].data,
709                         &record->uuids);
710     }
711     record->uuids = 1 << ffs(record->uuids - 1);
712     record->attribute_list =
713             qemu_mallocz(record->attributes * sizeof(*record->attribute_list));
714     record->uuid =
715             qemu_mallocz(record->uuids * sizeof(*record->uuid));
716     data = qemu_malloc(len);
717
718     record->attributes = 0;
719     uuid = record->uuid;
720     while (def->attributes[record->attributes].data.type) {
721         record->attribute_list[record->attributes].pair = data;
722
723         len = 0;
724         data[len ++] = SDP_DTYPE_UINT | SDP_DSIZE_2;
725         data[len ++] = def->attributes[record->attributes].id >> 8;
726         data[len ++] = def->attributes[record->attributes].id & 0xff;
727         len += sdp_attr_write(data + len,
728                         &def->attributes[record->attributes].data, &uuid);
729
730         /* Special case: assign a ServiceRecordHandle in sequence */
731         if (def->attributes[record->attributes].id == SDP_ATTR_RECORD_HANDLE)
732             def->attributes[record->attributes].data.value.uint = handle;
733         /* Note: we could also assign a ServiceDescription based on
734          * sdp->device.device->lmp_name.  */
735
736         record->attribute_list[record->attributes ++].len = len;
737         data += len;
738     }
739
740     /* Sort the attribute list by the AttributeID */
741     qsort(record->attribute_list, record->attributes,
742                     sizeof(*record->attribute_list),
743                     (void *) sdp_attributeid_compare);
744     /* Sort the searchable UUIDs list for bisection */
745     qsort(record->uuid, record->uuids,
746                     sizeof(*record->uuid),
747                     (void *) sdp_uuid_compare);
748 }
749
750 static void sdp_service_db_build(struct bt_l2cap_sdp_state_s *sdp,
751                 struct sdp_def_service_s **service)
752 {
753     sdp->services = 0;
754     while (service[sdp->services])
755         sdp->services ++;
756     sdp->service_list =
757             qemu_mallocz(sdp->services * sizeof(*sdp->service_list));
758
759     sdp->services = 0;
760     while (*service) {
761         sdp_service_record_build(&sdp->service_list[sdp->services],
762                         *service, sdp->services);
763         service ++;
764         sdp->services ++;
765     }
766 }
767
768 #define LAST { .type = 0 }
769 #define SERVICE(name, attrs)                            \
770     static struct sdp_def_service_s glue(glue(sdp_service_, name), _s) = { \
771         .attributes = { attrs { .data = LAST } },       \
772     };
773 #define ATTRIBUTE(attrid, val)  { .id = glue(SDP_ATTR_, attrid), .data = val },
774 #define UINT8(val)      {                               \
775         .type       = SDP_DTYPE_UINT | SDP_DSIZE_1,     \
776         .value.uint = val,                              \
777     },
778 #define UINT16(val)     {                               \
779         .type       = SDP_DTYPE_UINT | SDP_DSIZE_2,     \
780         .value.uint = val,                              \
781     },
782 #define UINT32(val)     {                               \
783         .type       = SDP_DTYPE_UINT | SDP_DSIZE_4,     \
784         .value.uint = val,                              \
785     },
786 #define UUID128(val)    {                               \
787         .type       = SDP_DTYPE_UUID | SDP_DSIZE_16,    \
788         .value.uint = val,                              \
789     },
790 #define TRUE    {                               \
791         .type       = SDP_DTYPE_BOOL | SDP_DSIZE_1,     \
792         .value.uint = 1,                                \
793     },
794 #define FALSE   {                               \
795         .type       = SDP_DTYPE_BOOL | SDP_DSIZE_1,     \
796         .value.uint = 0,                                \
797     },
798 #define STRING(val)     {                               \
799         .type       = SDP_DTYPE_STRING,                 \
800         .value.str  = val,                              \
801     },
802 #define ARRAY(...)      {                               \
803         .type       = SDP_DTYPE_STRING | SDP_DSIZE_2,   \
804         .value.str  = (char []) { __VA_ARGS__, 0, 0 },  \
805     },
806 #define URL(val)        {                               \
807         .type       = SDP_DTYPE_URL,                    \
808         .value.str  = val,                              \
809     },
810 #if 1
811 #define LIST(val)       {                               \
812         .type       = SDP_DTYPE_SEQ,                    \
813         .value.list = (struct sdp_def_data_element_s []) { val LAST }, \
814     },
815 #endif
816
817 /* Try to keep each single attribute below MAX_PDU_OUT_SIZE bytes
818  * in resulting SDP data representation size.  */
819
820 SERVICE(hid,
821     ATTRIBUTE(RECORD_HANDLE,   UINT32(0))       /* Filled in later */
822     ATTRIBUTE(SVCLASS_ID_LIST, LIST(UUID128(HID_SVCLASS_ID)))
823     ATTRIBUTE(RECORD_STATE,    UINT32(1))
824     ATTRIBUTE(PROTO_DESC_LIST, LIST(
825         LIST(UUID128(L2CAP_UUID) UINT16(BT_PSM_HID_CTRL))
826         LIST(UUID128(HIDP_UUID))
827     ))
828     ATTRIBUTE(BROWSE_GRP_LIST, LIST(UUID128(0x1002)))
829     ATTRIBUTE(LANG_BASE_ATTR_ID_LIST, LIST(
830         UINT16(0x656e) UINT16(0x006a) UINT16(0x0100)
831     ))
832     ATTRIBUTE(PFILE_DESC_LIST, LIST(
833         LIST(UUID128(HID_PROFILE_ID) UINT16(0x0100))
834     ))
835     ATTRIBUTE(DOC_URL,         URL("http://bellard.org/qemu/user-doc.html"))
836     ATTRIBUTE(SVCNAME_PRIMARY, STRING("QEMU Bluetooth HID"))
837     ATTRIBUTE(SVCDESC_PRIMARY, STRING("QEMU Keyboard/Mouse"))
838     ATTRIBUTE(SVCPROV_PRIMARY, STRING("QEMU " QEMU_VERSION))
839
840     /* Profile specific */
841     ATTRIBUTE(DEVICE_RELEASE_NUMBER,    UINT16(0x0091)) /* Deprecated, remove */
842     ATTRIBUTE(PARSER_VERSION,           UINT16(0x0111))
843     /* TODO: extract from l2cap_device->device.class[0] */
844     ATTRIBUTE(DEVICE_SUBCLASS,          UINT8(0x40))
845     ATTRIBUTE(COUNTRY_CODE,             UINT8(0x15))
846     ATTRIBUTE(VIRTUAL_CABLE,            TRUE)
847     ATTRIBUTE(RECONNECT_INITIATE,       FALSE)
848     /* TODO: extract from hid->usbdev->report_desc */
849     ATTRIBUTE(DESCRIPTOR_LIST,          LIST(
850         LIST(UINT8(0x22) ARRAY(
851             0x05, 0x01, /* Usage Page (Generic Desktop) */
852             0x09, 0x06, /* Usage (Keyboard) */
853             0xa1, 0x01, /* Collection (Application) */
854             0x75, 0x01, /*   Report Size (1) */
855             0x95, 0x08, /*   Report Count (8) */
856             0x05, 0x07, /*   Usage Page (Key Codes) */
857             0x19, 0xe0, /*   Usage Minimum (224) */
858             0x29, 0xe7, /*   Usage Maximum (231) */
859             0x15, 0x00, /*   Logical Minimum (0) */
860             0x25, 0x01, /*   Logical Maximum (1) */
861             0x81, 0x02, /*   Input (Data, Variable, Absolute) */
862             0x95, 0x01, /*   Report Count (1) */
863             0x75, 0x08, /*   Report Size (8) */
864             0x81, 0x01, /*   Input (Constant) */
865             0x95, 0x05, /*   Report Count (5) */
866             0x75, 0x01, /*   Report Size (1) */
867             0x05, 0x08, /*   Usage Page (LEDs) */
868             0x19, 0x01, /*   Usage Minimum (1) */
869             0x29, 0x05, /*   Usage Maximum (5) */
870             0x91, 0x02, /*   Output (Data, Variable, Absolute) */
871             0x95, 0x01, /*   Report Count (1) */
872             0x75, 0x03, /*   Report Size (3) */
873             0x91, 0x01, /*   Output (Constant) */
874             0x95, 0x06, /*   Report Count (6) */
875             0x75, 0x08, /*   Report Size (8) */
876             0x15, 0x00, /*   Logical Minimum (0) */
877             0x25, 0xff, /*   Logical Maximum (255) */
878             0x05, 0x07, /*   Usage Page (Key Codes) */
879             0x19, 0x00, /*   Usage Minimum (0) */
880             0x29, 0xff, /*   Usage Maximum (255) */
881             0x81, 0x00, /*   Input (Data, Array) */
882             0xc0        /* End Collection */
883     ))))
884     ATTRIBUTE(LANG_ID_BASE_LIST,        LIST(
885         LIST(UINT16(0x0409) UINT16(0x0100))
886     ))
887     ATTRIBUTE(SDP_DISABLE,              FALSE)
888     ATTRIBUTE(BATTERY_POWER,            TRUE)
889     ATTRIBUTE(REMOTE_WAKEUP,            TRUE)
890     ATTRIBUTE(BOOT_DEVICE,              TRUE)   /* XXX: untested */
891     ATTRIBUTE(SUPERVISION_TIMEOUT,      UINT16(0x0c80))
892     ATTRIBUTE(NORMALLY_CONNECTABLE,     TRUE)
893     ATTRIBUTE(PROFILE_VERSION,          UINT16(0x0100))
894 )
895
896 SERVICE(sdp,
897     ATTRIBUTE(RECORD_HANDLE,   UINT32(0))       /* Filled in later */
898     ATTRIBUTE(SVCLASS_ID_LIST, LIST(UUID128(SDP_SERVER_SVCLASS_ID)))
899     ATTRIBUTE(RECORD_STATE,    UINT32(1))
900     ATTRIBUTE(PROTO_DESC_LIST, LIST(
901         LIST(UUID128(L2CAP_UUID) UINT16(BT_PSM_SDP))
902         LIST(UUID128(SDP_UUID))
903     ))
904     ATTRIBUTE(BROWSE_GRP_LIST, LIST(UUID128(0x1002)))
905     ATTRIBUTE(LANG_BASE_ATTR_ID_LIST, LIST(
906         UINT16(0x656e) UINT16(0x006a) UINT16(0x0100)
907     ))
908     ATTRIBUTE(PFILE_DESC_LIST, LIST(
909         LIST(UUID128(SDP_SERVER_PROFILE_ID) UINT16(0x0100))
910     ))
911     ATTRIBUTE(DOC_URL,         URL("http://bellard.org/qemu/user-doc.html"))
912     ATTRIBUTE(SVCPROV_PRIMARY, STRING("QEMU " QEMU_VERSION))
913
914     /* Profile specific */
915     ATTRIBUTE(VERSION_NUM_LIST, LIST(UINT16(0x0100)))
916     ATTRIBUTE(SVCDB_STATE    , UINT32(1))
917 )
918
919 SERVICE(pnp,
920     ATTRIBUTE(RECORD_HANDLE,   UINT32(0))       /* Filled in later */
921     ATTRIBUTE(SVCLASS_ID_LIST, LIST(UUID128(PNP_INFO_SVCLASS_ID)))
922     ATTRIBUTE(RECORD_STATE,    UINT32(1))
923     ATTRIBUTE(PROTO_DESC_LIST, LIST(
924         LIST(UUID128(L2CAP_UUID) UINT16(BT_PSM_SDP))
925         LIST(UUID128(SDP_UUID))
926     ))
927     ATTRIBUTE(BROWSE_GRP_LIST, LIST(UUID128(0x1002)))
928     ATTRIBUTE(LANG_BASE_ATTR_ID_LIST, LIST(
929         UINT16(0x656e) UINT16(0x006a) UINT16(0x0100)
930     ))
931     ATTRIBUTE(PFILE_DESC_LIST, LIST(
932         LIST(UUID128(PNP_INFO_PROFILE_ID) UINT16(0x0100))
933     ))
934     ATTRIBUTE(DOC_URL,         URL("http://bellard.org/qemu/user-doc.html"))
935     ATTRIBUTE(SVCPROV_PRIMARY, STRING("QEMU " QEMU_VERSION))
936
937     /* Profile specific */
938     ATTRIBUTE(SPECIFICATION_ID, UINT16(0x0100))
939     ATTRIBUTE(VERSION,         UINT16(0x0100))
940     ATTRIBUTE(PRIMARY_RECORD,  TRUE)
941 )
942
943 static int bt_l2cap_sdp_new_ch(struct bt_l2cap_device_s *dev,
944                 struct bt_l2cap_conn_params_s *params)
945 {
946     struct bt_l2cap_sdp_state_s *sdp = qemu_mallocz(sizeof(*sdp));
947     struct sdp_def_service_s *services[] = {
948         &sdp_service_sdp_s,
949         &sdp_service_hid_s,
950         &sdp_service_pnp_s,
951         NULL,
952     };
953
954     sdp->channel = params;
955     sdp->channel->opaque = sdp;
956     sdp->channel->close = bt_l2cap_sdp_close_ch;
957     sdp->channel->sdu_in = bt_l2cap_sdp_sdu_in;
958
959     sdp_service_db_build(sdp, services);
960
961     return 0;
962 }
963
964 void bt_l2cap_sdp_init(struct bt_l2cap_device_s *dev)
965 {
966     bt_l2cap_psm_register(dev, BT_PSM_SDP,
967                     MAX_PDU_OUT_SIZE, bt_l2cap_sdp_new_ch);
968 }