1 /*
2 *
3 * BlueZ - Bluetooth protocol stack for Linux
4 *
5 * Copyright (C) 2004-2007 Marcel Holtmann <marcel@holtmann.org>
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include <sys/types.h>
35 #include <netinet/in.h>
36
37 #include "parser.h"
38
si2str(uint8_t si)39 static char *si2str(uint8_t si)
40 {
41 switch (si & 0x7f) {
42 case 0x01:
43 return "Discover";
44 case 0x02:
45 return "Capabilities";
46 case 0x03:
47 return "Set config";
48 case 0x04:
49 return "Get config";
50 case 0x05:
51 return "Reconfigure";
52 case 0x06:
53 return "Open";
54 case 0x07:
55 return "Start";
56 case 0x08:
57 return "Close";
58 case 0x09:
59 return "Suspend";
60 case 0x0a:
61 return "Abort";
62 case 0x0b:
63 return "Security";
64 default:
65 return "Unknown";
66 }
67 }
68
pt2str(uint8_t hdr)69 static char *pt2str(uint8_t hdr)
70 {
71 switch (hdr & 0x0c) {
72 case 0x00:
73 return "Single";
74 case 0x04:
75 return "Start";
76 case 0x08:
77 return "Cont";
78 case 0x0c:
79 return "End";
80 default:
81 return "Unk";
82 }
83 }
84
mt2str(uint8_t hdr)85 static char *mt2str(uint8_t hdr)
86 {
87 switch (hdr & 0x03) {
88 case 0x00:
89 return "cmd";
90 case 0x02:
91 return "rsp";
92 case 0x03:
93 return "rej";
94 default:
95 return "rfd";
96 }
97 }
98
media2str(uint8_t type)99 static char *media2str(uint8_t type)
100 {
101 switch (type) {
102 case 0:
103 return "Audio";
104 case 1:
105 return "Video";
106 case 2:
107 return "Multimedia";
108 default:
109 return "Reserved";
110 }
111 }
112
codec2str(uint8_t type,uint8_t codec)113 static char *codec2str(uint8_t type, uint8_t codec)
114 {
115 switch (type) {
116 case 0:
117 switch (codec) {
118 case 0:
119 return "SBC";
120 case 1:
121 return "MPEG-1,2 Audio";
122 case 2:
123 return "MPEG-2,4 AAC";
124 case 4:
125 return "ATRAC family";
126 case 255:
127 return "non-A2DP";
128 default:
129 return "Reserved";
130 }
131 break;
132 case 1:
133 switch (codec) {
134 case 1:
135 return "H.263 baseline";
136 case 2:
137 return "MPEG-4 Visual Simple Profile";
138 case 3:
139 return "H.263 profile 3";
140 case 4:
141 return "H.263 profile 8";
142 case 255:
143 return "Non-VDP";
144 default:
145 return "Reserved";
146 }
147 break;
148 }
149 return "Unknown";
150 }
151
cat2str(uint8_t cat)152 static char *cat2str(uint8_t cat)
153 {
154 switch (cat) {
155 case 1:
156 return "Media Transport";
157 case 2:
158 return "Reporting";
159 case 3:
160 return "Recovery";
161 case 4:
162 return "Content Protection";
163 case 5:
164 return "Header Compression";
165 case 6:
166 return "Multiplexing";
167 case 7:
168 return "Media Codec";
169 default:
170 return "Reserved";
171 }
172 }
173
errorcode(int level,struct frame * frm)174 static void errorcode(int level, struct frame *frm)
175 {
176 uint8_t code;
177
178 p_indent(level, frm);
179 code = get_u8(frm);
180 printf("Error code %d\n", code);
181 }
182
acp_seid(int level,struct frame * frm)183 static void acp_seid(int level, struct frame *frm)
184 {
185 uint8_t seid;
186
187 p_indent(level, frm);
188 seid = get_u8(frm);
189 printf("ACP SEID %d\n", seid >> 2);
190 }
191
acp_int_seid(int level,struct frame * frm)192 static void acp_int_seid(int level, struct frame *frm)
193 {
194 uint8_t acp_seid, int_seid;
195
196 p_indent(level, frm);
197 acp_seid = get_u8(frm);
198 int_seid = get_u8(frm);
199 printf("ACP SEID %d - INT SEID %d\n", acp_seid >> 2, int_seid >> 2);
200 }
201
capabilities(int level,struct frame * frm)202 static void capabilities(int level, struct frame *frm)
203 {
204 uint8_t cat, len;
205
206 while (frm->len > 1) {
207 p_indent(level, frm);
208 cat = get_u8(frm);
209 len = get_u8(frm);
210
211 if (cat == 7) {
212 uint8_t type, codec, tmp;
213
214 type = get_u8(frm);
215 codec = get_u8(frm);
216
217 printf("%s - %s\n", cat2str(cat), codec2str(type, codec));
218
219 switch (codec) {
220 case 0:
221 tmp = get_u8(frm);
222 p_indent(level + 1, frm);
223 if (tmp & 0x80)
224 printf("16kHz ");
225 if (tmp & 0x40)
226 printf("32kHz ");
227 if (tmp & 0x20)
228 printf("44.1kHz ");
229 if (tmp & 0x10)
230 printf("48kHz ");
231 printf("\n");
232 p_indent(level + 1, frm);
233 if (tmp & 0x08)
234 printf("Mono ");
235 if (tmp & 0x04)
236 printf("DualChannel ");
237 if (tmp & 0x02)
238 printf("Stereo ");
239 if (tmp & 0x01)
240 printf("JointStereo ");
241 printf("\n");
242 tmp = get_u8(frm);
243 p_indent(level + 1, frm);
244 if (tmp & 0x80)
245 printf("4 ");
246 if (tmp & 0x40)
247 printf("8 ");
248 if (tmp & 0x20)
249 printf("12 ");
250 if (tmp & 0x10)
251 printf("16 ");
252 printf("Blocks\n");
253 p_indent(level + 1, frm);
254 if (tmp & 0x08)
255 printf("4 ");
256 if (tmp & 0x04)
257 printf("8 ");
258 printf("Subbands\n");
259 p_indent(level + 1, frm);
260 if (tmp & 0x02)
261 printf("SNR ");
262 if (tmp & 0x01)
263 printf("Loudness ");
264 printf("\n");
265 tmp = get_u8(frm);
266 p_indent(level + 1, frm);
267 printf("Bitpool Range %d-%d\n", tmp, get_u8(frm));
268 break;
269 default:
270 hex_dump(level + 1, frm, len - 2);
271 frm->ptr += (len - 2);
272 frm->len -= (len - 2);
273 break;
274 }
275 } else {
276 printf("%s\n", cat2str(cat));
277 hex_dump(level + 1, frm, len);
278
279 frm->ptr += len;
280 frm->len -= len;
281 }
282 }
283 }
284
discover(int level,uint8_t hdr,struct frame * frm)285 static inline void discover(int level, uint8_t hdr, struct frame *frm)
286 {
287 uint8_t seid, type;
288
289 switch (hdr & 0x03) {
290 case 0x02:
291 while (frm->len > 1) {
292 p_indent(level, frm);
293 seid = get_u8(frm);
294 type = get_u8(frm);
295 printf("ACP SEID %d - %s %s%s\n",
296 seid >> 2, media2str(type >> 4),
297 type & 0x08 ? "Sink" : "Source",
298 seid & 0x02 ? " (InUse)" : "");
299 }
300 break;
301 case 0x03:
302 errorcode(level, frm);
303 break;
304 }
305 }
306
get_capabilities(int level,uint8_t hdr,struct frame * frm)307 static inline void get_capabilities(int level, uint8_t hdr, struct frame *frm)
308 {
309 switch (hdr & 0x03) {
310 case 0x00:
311 acp_seid(level, frm);
312 break;
313 case 0x02:
314 capabilities(level, frm);
315 break;
316 case 0x03:
317 errorcode(level, frm);
318 break;
319 }
320 }
321
set_configuration(int level,uint8_t hdr,struct frame * frm)322 static inline void set_configuration(int level, uint8_t hdr, struct frame *frm)
323 {
324 uint8_t cat;
325
326 switch (hdr & 0x03) {
327 case 0x00:
328 acp_int_seid(level, frm);
329 capabilities(level, frm);
330 break;
331 case 0x03:
332 p_indent(level, frm);
333 cat = get_u8(frm);
334 printf("%s\n", cat2str(cat));
335 errorcode(level, frm);
336 break;
337 }
338 }
339
get_configuration(int level,uint8_t hdr,struct frame * frm)340 static inline void get_configuration(int level, uint8_t hdr, struct frame *frm)
341 {
342 switch (hdr & 0x03) {
343 case 0x00:
344 acp_seid(level, frm);
345 case 0x02:
346 capabilities(level, frm);
347 break;
348 case 0x03:
349 errorcode(level, frm);
350 break;
351 }
352 }
353
reconfigure(int level,uint8_t hdr,struct frame * frm)354 static inline void reconfigure(int level, uint8_t hdr, struct frame *frm)
355 {
356 uint8_t cat;
357
358 switch (hdr & 0x03) {
359 case 0x00:
360 acp_seid(level, frm);
361 capabilities(level, frm);
362 break;
363 case 0x03:
364 p_indent(level, frm);
365 cat = get_u8(frm);
366 printf("%s\n", cat2str(cat));
367 errorcode(level, frm);
368 break;
369 }
370 }
371
open_close_stream(int level,uint8_t hdr,struct frame * frm)372 static inline void open_close_stream(int level, uint8_t hdr, struct frame *frm)
373 {
374 switch (hdr & 0x03) {
375 case 0x00:
376 acp_seid(level, frm);
377 break;
378 case 0x03:
379 errorcode(level, frm);
380 break;
381 }
382 }
383
start_suspend_stream(int level,uint8_t hdr,struct frame * frm)384 static inline void start_suspend_stream(int level, uint8_t hdr, struct frame *frm)
385 {
386 switch (hdr & 0x03) {
387 case 0x00:
388 while (frm->len > 0)
389 acp_seid(level, frm);
390 break;
391 case 0x03:
392 acp_seid(level, frm);
393 errorcode(level, frm);
394 break;
395 }
396 }
397
abort_streaming(int level,uint8_t hdr,struct frame * frm)398 static inline void abort_streaming(int level, uint8_t hdr, struct frame *frm)
399 {
400 switch (hdr & 0x03) {
401 case 0x00:
402 acp_seid(level, frm);
403 break;
404 }
405 }
406
security(int level,uint8_t hdr,struct frame * frm)407 static inline void security(int level, uint8_t hdr, struct frame *frm)
408 {
409 switch (hdr & 0x03) {
410 case 0x00:
411 acp_seid(level, frm);
412 case 0x02:
413 hex_dump(level + 1, frm, frm->len);
414 frm->ptr += frm->len;
415 frm->len = 0;
416 break;
417 case 0x03:
418 errorcode(level, frm);
419 break;
420 }
421 }
422
avdtp_dump(int level,struct frame * frm)423 void avdtp_dump(int level, struct frame *frm)
424 {
425 uint8_t hdr, sid, nsp, type;
426 uint16_t seqn;
427 uint32_t time, ssrc;
428
429 switch (frm->num) {
430 case 1:
431 p_indent(level, frm);
432 hdr = get_u8(frm);
433
434 nsp = (hdr & 0x0c) == 0x04 ? get_u8(frm) : 0;
435 sid = hdr & 0x08 ? 0x00 : get_u8(frm);
436
437 printf("AVDTP(s): %s %s: transaction %d\n",
438 hdr & 0x08 ? pt2str(hdr) : si2str(sid), mt2str(hdr), hdr >> 4);
439
440 switch (sid & 0x7f) {
441 case 0x01:
442 discover(level + 1, hdr, frm);
443 break;
444 case 0x02:
445 get_capabilities(level + 1, hdr, frm);
446 break;
447 case 0x03:
448 set_configuration(level + 1, hdr, frm);
449 break;
450 case 0x04:
451 get_configuration(level + 1, hdr, frm);
452 break;
453 case 0x05:
454 reconfigure(level + 1, hdr, frm);
455 break;
456 case 0x06:
457 open_close_stream(level + 1, hdr, frm);
458 break;
459 case 0x07:
460 start_suspend_stream(level + 1, hdr, frm);
461 break;
462 case 0x08:
463 open_close_stream(level + 1, hdr, frm);
464 break;
465 case 0x09:
466 start_suspend_stream(level + 1, hdr, frm);
467 break;
468 case 0x0a:
469 abort_streaming(level + 1, hdr, frm);
470 break;
471 case 0x0b:
472 security(level + 1, hdr, frm);
473 break;
474 }
475
476 break;
477
478 case 2:
479 p_indent(level, frm);
480 hdr = get_u8(frm);
481 type = get_u8(frm);
482 seqn = get_u16(frm);
483 time = get_u32(frm);
484 ssrc = get_u32(frm);
485
486 printf("AVDTP(m): ver %d %s%scc %d %spt %d seqn %d time %d ssrc %d\n",
487 hdr >> 6, hdr & 0x20 ? "pad " : "", hdr & 0x10 ? "ext " : "",
488 hdr & 0xf, type & 0x80 ? "mark " : "", type & 0x7f, seqn, time, ssrc);
489 break;
490 }
491
492 raw_dump(level, frm);
493 }
494