bt-sdp.c 29 KB

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