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