avdtp.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2004-2011 Marcel Holtmann <marcel@holtmann.org>
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <errno.h>
  16. #include <unistd.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include "parser.h"
  20. static char *si2str(uint8_t si)
  21. {
  22. switch (si & 0x7f) {
  23. case 0x01:
  24. return "Discover";
  25. case 0x02:
  26. return "Capabilities";
  27. case 0x03:
  28. return "Set config";
  29. case 0x04:
  30. return "Get config";
  31. case 0x05:
  32. return "Reconfigure";
  33. case 0x06:
  34. return "Open";
  35. case 0x07:
  36. return "Start";
  37. case 0x08:
  38. return "Close";
  39. case 0x09:
  40. return "Suspend";
  41. case 0x0a:
  42. return "Abort";
  43. case 0x0b:
  44. return "Security";
  45. case 0x0c:
  46. return "All Capabilities";
  47. case 0x0d:
  48. return "Delay Report";
  49. default:
  50. return "Unknown";
  51. }
  52. }
  53. static char *pt2str(uint8_t hdr)
  54. {
  55. switch (hdr & 0x0c) {
  56. case 0x00:
  57. return "Single";
  58. case 0x04:
  59. return "Start";
  60. case 0x08:
  61. return "Cont";
  62. case 0x0c:
  63. return "End";
  64. default:
  65. return "Unk";
  66. }
  67. }
  68. static char *mt2str(uint8_t hdr)
  69. {
  70. switch (hdr & 0x03) {
  71. case 0x00:
  72. return "cmd";
  73. case 0x02:
  74. return "rsp";
  75. case 0x03:
  76. return "rej";
  77. default:
  78. return "rfd";
  79. }
  80. }
  81. static char *media2str(uint8_t type)
  82. {
  83. switch (type) {
  84. case 0:
  85. return "Audio";
  86. case 1:
  87. return "Video";
  88. case 2:
  89. return "Multimedia";
  90. default:
  91. return "Reserved";
  92. }
  93. }
  94. static char *codec2str(uint8_t type, uint8_t codec)
  95. {
  96. switch (type) {
  97. case 0:
  98. switch (codec) {
  99. case 0:
  100. return "SBC";
  101. case 1:
  102. return "MPEG-1,2 Audio";
  103. case 2:
  104. return "MPEG-2,4 AAC";
  105. case 4:
  106. return "ATRAC family";
  107. case 255:
  108. return "non-A2DP";
  109. default:
  110. return "Reserved";
  111. }
  112. break;
  113. case 1:
  114. switch (codec) {
  115. case 1:
  116. return "H.263 baseline";
  117. case 2:
  118. return "MPEG-4 Visual Simple Profile";
  119. case 3:
  120. return "H.263 profile 3";
  121. case 4:
  122. return "H.263 profile 8";
  123. case 255:
  124. return "Non-VDP";
  125. default:
  126. return "Reserved";
  127. }
  128. break;
  129. }
  130. return "Unknown";
  131. }
  132. static char *vndcodec2str(uint32_t vendor, uint16_t vndcodec)
  133. {
  134. if (vendor == 0x0000004f && vndcodec == 0x0001)
  135. return "aptX";
  136. else if (vendor == 0x0000012d && vndcodec == 0x00aa)
  137. return "LDAC";
  138. return "Unknown";
  139. }
  140. static char *cat2str(uint8_t cat)
  141. {
  142. switch (cat) {
  143. case 1:
  144. return "Media Transport";
  145. case 2:
  146. return "Reporting";
  147. case 3:
  148. return "Recovery";
  149. case 4:
  150. return "Content Protection";
  151. case 5:
  152. return "Header Compression";
  153. case 6:
  154. return "Multiplexing";
  155. case 7:
  156. return "Media Codec";
  157. case 8:
  158. return "Delay Reporting";
  159. default:
  160. return "Reserved";
  161. }
  162. }
  163. static void errorcode(int level, struct frame *frm)
  164. {
  165. uint8_t code;
  166. p_indent(level, frm);
  167. code = p_get_u8(frm);
  168. printf("Error code %d\n", code);
  169. }
  170. static void acp_seid(int level, struct frame *frm)
  171. {
  172. uint8_t seid;
  173. p_indent(level, frm);
  174. seid = p_get_u8(frm);
  175. printf("ACP SEID %d\n", seid >> 2);
  176. }
  177. static void acp_int_seid(int level, struct frame *frm)
  178. {
  179. uint8_t acp_seid, int_seid;
  180. p_indent(level, frm);
  181. acp_seid = p_get_u8(frm);
  182. int_seid = p_get_u8(frm);
  183. printf("ACP SEID %d - INT SEID %d\n", acp_seid >> 2, int_seid >> 2);
  184. }
  185. static void capabilities(int level, struct frame *frm)
  186. {
  187. uint8_t cat, len;
  188. while (frm->len > 1) {
  189. p_indent(level, frm);
  190. cat = p_get_u8(frm);
  191. len = p_get_u8(frm);
  192. if (cat == 7) {
  193. uint8_t type, codec;
  194. uint16_t tmp, freq, vndcodec = 0;
  195. uint32_t bitrate, vendor = 0;
  196. int i;
  197. type = p_get_u8(frm);
  198. codec = p_get_u8(frm);
  199. if (codec == 255) {
  200. vendor = btohl(htonl(p_get_u32(frm)));
  201. vndcodec = btohs(htons(p_get_u16(frm)));
  202. printf("%s - %s (%s)\n", cat2str(cat),
  203. codec2str(type, codec),
  204. vndcodec2str(vendor, vndcodec));
  205. } else {
  206. printf("%s - %s\n", cat2str(cat),
  207. codec2str(type, codec));
  208. }
  209. switch (codec) {
  210. case 0:
  211. tmp = p_get_u8(frm);
  212. p_indent(level + 1, frm);
  213. if (tmp & 0x80)
  214. printf("16kHz ");
  215. if (tmp & 0x40)
  216. printf("32kHz ");
  217. if (tmp & 0x20)
  218. printf("44.1kHz ");
  219. if (tmp & 0x10)
  220. printf("48kHz ");
  221. printf("\n");
  222. p_indent(level + 1, frm);
  223. if (tmp & 0x08)
  224. printf("Mono ");
  225. if (tmp & 0x04)
  226. printf("DualChannel ");
  227. if (tmp & 0x02)
  228. printf("Stereo ");
  229. if (tmp & 0x01)
  230. printf("JointStereo ");
  231. printf("\n");
  232. tmp = p_get_u8(frm);
  233. p_indent(level + 1, frm);
  234. if (tmp & 0x80)
  235. printf("4 ");
  236. if (tmp & 0x40)
  237. printf("8 ");
  238. if (tmp & 0x20)
  239. printf("12 ");
  240. if (tmp & 0x10)
  241. printf("16 ");
  242. printf("Blocks\n");
  243. p_indent(level + 1, frm);
  244. if (tmp & 0x08)
  245. printf("4 ");
  246. if (tmp & 0x04)
  247. printf("8 ");
  248. printf("Subbands\n");
  249. p_indent(level + 1, frm);
  250. if (tmp & 0x02)
  251. printf("SNR ");
  252. if (tmp & 0x01)
  253. printf("Loudness ");
  254. printf("\n");
  255. tmp = p_get_u8(frm);
  256. p_indent(level + 1, frm);
  257. printf("Bitpool Range %d-%d\n", tmp, p_get_u8(frm));
  258. break;
  259. case 1:
  260. tmp = p_get_u8(frm);
  261. p_indent(level + 1, frm);
  262. printf("Layers: ");
  263. if (tmp & 0x80)
  264. printf("1 ");
  265. if (tmp & 0x40)
  266. printf("2 ");
  267. if (tmp & 0x20)
  268. printf("3 ");
  269. printf("\n");
  270. p_indent(level + 1, frm);
  271. printf("CRC Protection: %s\n",
  272. tmp & 0x10 ? "Yes" : "No");
  273. p_indent(level + 1, frm);
  274. if (tmp & 0x08)
  275. printf("Mono ");
  276. if (tmp & 0x04)
  277. printf("DualChannel ");
  278. if (tmp & 0x02)
  279. printf("Stereo ");
  280. if (tmp & 0x01)
  281. printf("JointStereo ");
  282. printf("\n");
  283. tmp = p_get_u8(frm);
  284. p_indent(level + 1, frm);
  285. printf("Media Payload Format: RFC-2250 %s\n",
  286. tmp & 0x40 ? "RFC-3119" : "");
  287. p_indent(level + 1, frm);
  288. if (tmp & 0x20)
  289. printf("16kHz ");
  290. if (tmp & 0x10)
  291. printf("22.05kHz ");
  292. if (tmp & 0x08)
  293. printf("24kHz ");
  294. if (tmp & 0x04)
  295. printf("32kHz ");
  296. if (tmp & 0x02)
  297. printf("44.1kHz ");
  298. if (tmp & 0x01)
  299. printf("48kHz ");
  300. printf("\n");
  301. tmp = p_get_u16(frm);
  302. p_indent(level + 1, frm);
  303. printf("VBR: %s\n",
  304. tmp & 0x8000 ? "Yes" : "No");
  305. p_indent(level + 1, frm);
  306. printf("Bit Rate Indexes: ");
  307. if (tmp & 0x8000) {
  308. printf("n/a");
  309. } else {
  310. for (i = 0; i < 15; i++, tmp >>= 1)
  311. if (tmp & 0x0001)
  312. printf("%d ", i);
  313. }
  314. printf("\n");
  315. break;
  316. case 2:
  317. tmp = p_get_u8(frm);
  318. p_indent(level + 1, frm);
  319. if (tmp & 0x80)
  320. printf("MPEG-2 AAC LC ");
  321. if (tmp & 0x40)
  322. printf("MPEG-4 AAC LC ");
  323. if (tmp & 0x20)
  324. printf("MPEG-4 AAC LTP ");
  325. if (tmp & 0x10)
  326. printf("MPEG-4 AAC scalable ");
  327. printf("\n");
  328. tmp = p_get_u16(frm);
  329. freq = tmp >> 4;
  330. p_indent(level + 1, frm);
  331. if (freq & 0x0800)
  332. printf("8kHz ");
  333. if (freq & 0x0400)
  334. printf("11.025kHz ");
  335. if (freq & 0x0200)
  336. printf("12kHz ");
  337. if (freq & 0x0100)
  338. printf("16kHz ");
  339. if (freq & 0x0080)
  340. printf("22.05kHz ");
  341. if (freq & 0x0040)
  342. printf("24kHz ");
  343. if (freq & 0x0020)
  344. printf("32kHz ");
  345. if (freq & 0x0010)
  346. printf("44.1kHz ");
  347. if (freq & 0x0008)
  348. printf("48kHz ");
  349. if (freq & 0x0004)
  350. printf("64kHz ");
  351. if (freq & 0x0002)
  352. printf("88.2kHz ");
  353. if (freq & 0x0001)
  354. printf("96kHz ");
  355. printf("\n");
  356. tmp >>= 2;
  357. p_indent(level + 1, frm);
  358. if (tmp & 0x02)
  359. printf("1 ");
  360. if (tmp & 0x01)
  361. printf("2 ");
  362. printf("Channels\n");
  363. tmp = p_get_u8(frm);
  364. bitrate = ((tmp & 0x7f) << 16) | p_get_u16(frm);
  365. p_indent(level + 1, frm);
  366. printf("%ubps ", bitrate);
  367. printf("%s\n", tmp & 0x80 ? "VBR" : "");
  368. break;
  369. case 255:
  370. if (vendor == 0x0000004f &&
  371. vndcodec == 0x0001) {
  372. tmp = p_get_u8(frm);
  373. p_indent(level + 1, frm);
  374. if (tmp & 0x80)
  375. printf("16kHz ");
  376. if (tmp & 0x40)
  377. printf("32kHz ");
  378. if (tmp & 0x20)
  379. printf("44.1kHz ");
  380. if (tmp & 0x10)
  381. printf("48kHz ");
  382. printf("\n");
  383. p_indent(level + 1, frm);
  384. if (tmp & 0x02)
  385. printf("Stereo ");
  386. if (tmp & 0x01)
  387. printf("Mono ");
  388. printf("\n");
  389. break;
  390. } else {
  391. hex_dump(level + 1, frm, len - 8);
  392. frm->ptr += (len - 8);
  393. frm->len -= (len - 8);
  394. }
  395. break;
  396. default:
  397. hex_dump(level + 1, frm, len - 2);
  398. frm->ptr += (len - 2);
  399. frm->len -= (len - 2);
  400. break;
  401. }
  402. } else {
  403. printf("%s\n", cat2str(cat));
  404. hex_dump(level + 1, frm, len);
  405. frm->ptr += len;
  406. frm->len -= len;
  407. }
  408. }
  409. }
  410. static inline void discover(int level, uint8_t hdr, struct frame *frm)
  411. {
  412. uint8_t seid, type;
  413. switch (hdr & 0x03) {
  414. case 0x02:
  415. while (frm->len > 1) {
  416. p_indent(level, frm);
  417. seid = p_get_u8(frm);
  418. type = p_get_u8(frm);
  419. printf("ACP SEID %d - %s %s%s\n",
  420. seid >> 2, media2str(type >> 4),
  421. type & 0x08 ? "Sink" : "Source",
  422. seid & 0x02 ? " (InUse)" : "");
  423. }
  424. break;
  425. case 0x03:
  426. errorcode(level, frm);
  427. break;
  428. }
  429. }
  430. static inline void get_capabilities(int level, uint8_t hdr, struct frame *frm)
  431. {
  432. switch (hdr & 0x03) {
  433. case 0x00:
  434. acp_seid(level, frm);
  435. break;
  436. case 0x02:
  437. capabilities(level, frm);
  438. break;
  439. case 0x03:
  440. errorcode(level, frm);
  441. break;
  442. }
  443. }
  444. static inline void set_configuration(int level, uint8_t hdr, struct frame *frm)
  445. {
  446. uint8_t cat;
  447. switch (hdr & 0x03) {
  448. case 0x00:
  449. acp_int_seid(level, frm);
  450. capabilities(level, frm);
  451. break;
  452. case 0x03:
  453. p_indent(level, frm);
  454. cat = p_get_u8(frm);
  455. printf("%s\n", cat2str(cat));
  456. errorcode(level, frm);
  457. break;
  458. }
  459. }
  460. static inline void get_configuration(int level, uint8_t hdr, struct frame *frm)
  461. {
  462. switch (hdr & 0x03) {
  463. case 0x00:
  464. acp_seid(level, frm);
  465. break;
  466. case 0x02:
  467. capabilities(level, frm);
  468. break;
  469. case 0x03:
  470. errorcode(level, frm);
  471. break;
  472. }
  473. }
  474. static inline void reconfigure(int level, uint8_t hdr, struct frame *frm)
  475. {
  476. uint8_t cat;
  477. switch (hdr & 0x03) {
  478. case 0x00:
  479. acp_seid(level, frm);
  480. capabilities(level, frm);
  481. break;
  482. case 0x03:
  483. p_indent(level, frm);
  484. cat = p_get_u8(frm);
  485. printf("%s\n", cat2str(cat));
  486. errorcode(level, frm);
  487. break;
  488. }
  489. }
  490. static inline void open_close_stream(int level, uint8_t hdr, struct frame *frm)
  491. {
  492. switch (hdr & 0x03) {
  493. case 0x00:
  494. acp_seid(level, frm);
  495. break;
  496. case 0x03:
  497. errorcode(level, frm);
  498. break;
  499. }
  500. }
  501. static inline void start_suspend_stream(int level, uint8_t hdr, struct frame *frm)
  502. {
  503. switch (hdr & 0x03) {
  504. case 0x00:
  505. while (frm->len > 0)
  506. acp_seid(level, frm);
  507. break;
  508. case 0x03:
  509. acp_seid(level, frm);
  510. errorcode(level, frm);
  511. break;
  512. }
  513. }
  514. static inline void abort_streaming(int level, uint8_t hdr, struct frame *frm)
  515. {
  516. switch (hdr & 0x03) {
  517. case 0x00:
  518. acp_seid(level, frm);
  519. break;
  520. }
  521. }
  522. static inline void security(int level, uint8_t hdr, struct frame *frm)
  523. {
  524. switch (hdr & 0x03) {
  525. case 0x00:
  526. acp_seid(level, frm);
  527. break;
  528. case 0x02:
  529. hex_dump(level + 1, frm, frm->len);
  530. frm->ptr += frm->len;
  531. frm->len = 0;
  532. break;
  533. case 0x03:
  534. errorcode(level, frm);
  535. break;
  536. }
  537. }
  538. static inline void delay_report(int level, uint8_t hdr, struct frame *frm)
  539. {
  540. uint8_t seid;
  541. uint16_t delay;
  542. switch (hdr & 0x03) {
  543. case 0x00:
  544. p_indent(level, frm);
  545. seid = p_get_u8(frm);
  546. delay = p_get_u16(frm);
  547. printf("ACP SEID %d delay %u.%ums\n", seid >> 2,
  548. delay / 10, delay % 10);
  549. break;
  550. case 0x03:
  551. errorcode(level, frm);
  552. break;
  553. }
  554. }
  555. void avdtp_dump(int level, struct frame *frm)
  556. {
  557. uint8_t hdr, sid, nsp, type;
  558. uint16_t seqn;
  559. uint32_t time, ssrc;
  560. switch (frm->num) {
  561. case 1:
  562. p_indent(level, frm);
  563. hdr = p_get_u8(frm);
  564. nsp = (hdr & 0x0c) == 0x04 ? p_get_u8(frm) : 0;
  565. sid = hdr & 0x08 ? 0x00 : p_get_u8(frm);
  566. printf("AVDTP(p): %s %s: transaction %d nsp 0x%02x\n",
  567. hdr & 0x08 ? pt2str(hdr) : si2str(sid),
  568. mt2str(hdr), hdr >> 4, nsp);
  569. switch (sid & 0x7f) {
  570. case 0x01:
  571. discover(level + 1, hdr, frm);
  572. break;
  573. case 0x02:
  574. case 0x0c:
  575. get_capabilities(level + 1, hdr, frm);
  576. break;
  577. case 0x03:
  578. set_configuration(level + 1, hdr, frm);
  579. break;
  580. case 0x04:
  581. get_configuration(level + 1, hdr, frm);
  582. break;
  583. case 0x05:
  584. reconfigure(level + 1, hdr, frm);
  585. break;
  586. case 0x06:
  587. open_close_stream(level + 1, hdr, frm);
  588. break;
  589. case 0x07:
  590. start_suspend_stream(level + 1, hdr, frm);
  591. break;
  592. case 0x08:
  593. open_close_stream(level + 1, hdr, frm);
  594. break;
  595. case 0x09:
  596. start_suspend_stream(level + 1, hdr, frm);
  597. break;
  598. case 0x0a:
  599. abort_streaming(level + 1, hdr, frm);
  600. break;
  601. case 0x0b:
  602. security(level + 1, hdr, frm);
  603. break;
  604. case 0x0d:
  605. delay_report(level + 1, hdr, frm);
  606. break;
  607. }
  608. break;
  609. case 2:
  610. p_indent(level, frm);
  611. hdr = p_get_u8(frm);
  612. type = p_get_u8(frm);
  613. seqn = p_get_u16(frm);
  614. time = p_get_u32(frm);
  615. ssrc = p_get_u32(frm);
  616. printf("AVDTP(c): ver %d %s%scc"
  617. " %d %spt %d seqn %d time %d ssrc %d\n",
  618. hdr >> 6, hdr & 0x20 ? "pad " : "",
  619. hdr & 0x10 ? "ext " : "", hdr & 0xf,
  620. type & 0x80 ? "mark " : "", type & 0x7f,
  621. seqn, time, ssrc);
  622. break;
  623. }
  624. raw_dump(level, frm);
  625. }