2
0

bt-sdp.c 29 KB

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