• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2004-2011  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 	case 0x0c:
65 		return "All Capabilities";
66 	case 0x0d:
67 		return "Delay Report";
68 	default:
69 		return "Unknown";
70 	}
71 }
72 
pt2str(uint8_t hdr)73 static char *pt2str(uint8_t hdr)
74 {
75 	switch (hdr & 0x0c) {
76 	case 0x00:
77 		return "Single";
78 	case 0x04:
79 		return "Start";
80 	case 0x08:
81 		return "Cont";
82 	case 0x0c:
83 		return "End";
84 	default:
85 		return "Unk";
86 	}
87 }
88 
mt2str(uint8_t hdr)89 static char *mt2str(uint8_t hdr)
90 {
91 	switch (hdr & 0x03) {
92 	case 0x00:
93 		return "cmd";
94 	case 0x02:
95 		return "rsp";
96 	case 0x03:
97 		return "rej";
98 	default:
99 		return "rfd";
100 	}
101 }
102 
media2str(uint8_t type)103 static char *media2str(uint8_t type)
104 {
105 	switch (type) {
106 	case 0:
107 		return "Audio";
108 	case 1:
109 		return "Video";
110 	case 2:
111 		return "Multimedia";
112 	default:
113 		return "Reserved";
114 	}
115 }
116 
codec2str(uint8_t type,uint8_t codec)117 static char *codec2str(uint8_t type, uint8_t codec)
118 {
119 	switch (type) {
120 	case 0:
121 		switch (codec) {
122 		case 0:
123 			return "SBC";
124 		case 1:
125 			return "MPEG-1,2 Audio";
126 		case 2:
127 			return "MPEG-2,4 AAC";
128 		case 4:
129 			return "ATRAC family";
130 		case 255:
131 			return "non-A2DP";
132 		default:
133 			return "Reserved";
134 		}
135 		break;
136 	case 1:
137 		switch (codec) {
138 		case 1:
139 			return "H.263 baseline";
140 		case 2:
141 			return "MPEG-4 Visual Simple Profile";
142 		case 3:
143 			return "H.263 profile 3";
144 		case 4:
145 			return "H.263 profile 8";
146 		case 255:
147 			return "Non-VDP";
148 		default:
149 			return "Reserved";
150 		}
151 		break;
152 	}
153 	return "Unknown";
154 }
155 
cat2str(uint8_t cat)156 static char *cat2str(uint8_t cat)
157 {
158 	switch (cat) {
159 	case 1:
160 		return "Media Transport";
161 	case 2:
162 		return "Reporting";
163 	case 3:
164 		return "Recovery";
165 	case 4:
166 		return "Content Protection";
167 	case 5:
168 		return "Header Compression";
169 	case 6:
170 		return "Multiplexing";
171 	case 7:
172 		return "Media Codec";
173 	case 8:
174 		return "Delay Reporting";
175 	default:
176 		return "Reserved";
177 	}
178 }
179 
errorcode(int level,struct frame * frm)180 static void errorcode(int level, struct frame *frm)
181 {
182 	uint8_t code;
183 
184 	p_indent(level, frm);
185 	code = get_u8(frm);
186 	printf("Error code %d\n", code);
187 }
188 
acp_seid(int level,struct frame * frm)189 static void acp_seid(int level, struct frame *frm)
190 {
191 	uint8_t seid;
192 
193 	p_indent(level, frm);
194 	seid = get_u8(frm);
195 	printf("ACP SEID %d\n", seid >> 2);
196 }
197 
acp_int_seid(int level,struct frame * frm)198 static void acp_int_seid(int level, struct frame *frm)
199 {
200 	uint8_t acp_seid, int_seid;
201 
202 	p_indent(level, frm);
203 	acp_seid = get_u8(frm);
204 	int_seid = get_u8(frm);
205 	printf("ACP SEID %d - INT SEID %d\n", acp_seid >> 2, int_seid >> 2);
206 }
207 
capabilities(int level,struct frame * frm)208 static void capabilities(int level, struct frame *frm)
209 {
210 	uint8_t cat, len;
211 
212 	while (frm->len > 1) {
213 		p_indent(level, frm);
214 		cat = get_u8(frm);
215 		len = get_u8(frm);
216 
217 		if (cat == 7) {
218 			uint8_t type, codec, tmp;
219 
220 			type  = get_u8(frm);
221 			codec = get_u8(frm);
222 
223 			printf("%s - %s\n", cat2str(cat), codec2str(type, codec));
224 
225 			switch (codec) {
226 			case 0:
227 				tmp = get_u8(frm);
228 				p_indent(level + 1, frm);
229 				if (tmp & 0x80)
230 					printf("16kHz ");
231 				if (tmp & 0x40)
232 					printf("32kHz ");
233 				if (tmp & 0x20)
234 					printf("44.1kHz ");
235 				if (tmp & 0x10)
236 					printf("48kHz ");
237 				printf("\n");
238 				p_indent(level + 1, frm);
239 				if (tmp & 0x08)
240 					printf("Mono ");
241 				if (tmp & 0x04)
242 					printf("DualChannel ");
243 				if (tmp & 0x02)
244 					printf("Stereo ");
245 				if (tmp & 0x01)
246 					printf("JointStereo ");
247 				printf("\n");
248 				tmp = get_u8(frm);
249 				p_indent(level + 1, frm);
250 				if (tmp & 0x80)
251 					printf("4 ");
252 				if (tmp & 0x40)
253 					printf("8 ");
254 				if (tmp & 0x20)
255 					printf("12 ");
256 				if (tmp & 0x10)
257 					printf("16 ");
258 				printf("Blocks\n");
259 				p_indent(level + 1, frm);
260 				if (tmp & 0x08)
261 					printf("4 ");
262 				if (tmp & 0x04)
263 					printf("8 ");
264 				printf("Subbands\n");
265 				p_indent(level + 1, frm);
266 				if (tmp & 0x02)
267 					printf("SNR ");
268 				if (tmp & 0x01)
269 					printf("Loudness ");
270 				printf("\n");
271 				tmp = get_u8(frm);
272 				p_indent(level + 1, frm);
273 				printf("Bitpool Range %d-%d\n", tmp, get_u8(frm));
274 				break;
275 			default:
276 				hex_dump(level + 1, frm, len - 2);
277 				frm->ptr += (len - 2);
278 				frm->len -= (len - 2);
279 				break;
280 			}
281 		} else {
282 			printf("%s\n", cat2str(cat));
283 			hex_dump(level + 1, frm, len);
284 
285 			frm->ptr += len;
286 			frm->len -= len;
287 		}
288 	}
289 }
290 
discover(int level,uint8_t hdr,struct frame * frm)291 static inline void discover(int level, uint8_t hdr, struct frame *frm)
292 {
293 	uint8_t seid, type;
294 
295 	switch (hdr & 0x03) {
296 	case 0x02:
297 		while (frm->len > 1) {
298 			p_indent(level, frm);
299 			seid = get_u8(frm);
300 			type = get_u8(frm);
301 			printf("ACP SEID %d - %s %s%s\n",
302 				seid >> 2, media2str(type >> 4),
303 				type & 0x08 ? "Sink" : "Source",
304 				seid & 0x02 ? " (InUse)" : "");
305 		}
306 		break;
307 	case 0x03:
308 		errorcode(level, frm);
309 		break;
310 	}
311 }
312 
get_capabilities(int level,uint8_t hdr,struct frame * frm)313 static inline void get_capabilities(int level, uint8_t hdr, struct frame *frm)
314 {
315 	switch (hdr & 0x03) {
316 	case 0x00:
317 		acp_seid(level, frm);
318 		break;
319 	case 0x02:
320 		capabilities(level, frm);
321 		break;
322 	case 0x03:
323 		errorcode(level, frm);
324 		break;
325 	}
326 }
327 
set_configuration(int level,uint8_t hdr,struct frame * frm)328 static inline void set_configuration(int level, uint8_t hdr, struct frame *frm)
329 {
330 	uint8_t cat;
331 
332 	switch (hdr & 0x03) {
333 	case 0x00:
334 		acp_int_seid(level, frm);
335 		capabilities(level, frm);
336 		break;
337 	case 0x03:
338 		p_indent(level, frm);
339 		cat = get_u8(frm);
340 		printf("%s\n", cat2str(cat));
341 		errorcode(level, frm);
342 		break;
343 	}
344 }
345 
get_configuration(int level,uint8_t hdr,struct frame * frm)346 static inline void get_configuration(int level, uint8_t hdr, struct frame *frm)
347 {
348 	switch (hdr & 0x03) {
349 	case 0x00:
350 		acp_seid(level, frm);
351 	case 0x02:
352 		capabilities(level, frm);
353 		break;
354 	case 0x03:
355 		errorcode(level, frm);
356 		break;
357 	}
358 }
359 
reconfigure(int level,uint8_t hdr,struct frame * frm)360 static inline void reconfigure(int level, uint8_t hdr, struct frame *frm)
361 {
362 	uint8_t cat;
363 
364 	switch (hdr & 0x03) {
365 	case 0x00:
366 		acp_seid(level, frm);
367 		capabilities(level, frm);
368 		break;
369 	case 0x03:
370 		p_indent(level, frm);
371 		cat = get_u8(frm);
372 		printf("%s\n", cat2str(cat));
373 		errorcode(level, frm);
374 		break;
375 	}
376 }
377 
open_close_stream(int level,uint8_t hdr,struct frame * frm)378 static inline void open_close_stream(int level, uint8_t hdr, struct frame *frm)
379 {
380 	switch (hdr & 0x03) {
381 	case 0x00:
382 		acp_seid(level, frm);
383 		break;
384 	case 0x03:
385 		errorcode(level, frm);
386 		break;
387 	}
388 }
389 
start_suspend_stream(int level,uint8_t hdr,struct frame * frm)390 static inline void start_suspend_stream(int level, uint8_t hdr, struct frame *frm)
391 {
392 	switch (hdr & 0x03) {
393 	case 0x00:
394 		while (frm->len > 0)
395 			acp_seid(level, frm);
396 		break;
397 	case 0x03:
398 		acp_seid(level, frm);
399 		errorcode(level, frm);
400 		break;
401 	}
402 }
403 
abort_streaming(int level,uint8_t hdr,struct frame * frm)404 static inline void abort_streaming(int level, uint8_t hdr, struct frame *frm)
405 {
406 	switch (hdr & 0x03) {
407 	case 0x00:
408 		acp_seid(level, frm);
409 		break;
410 	}
411 }
412 
security(int level,uint8_t hdr,struct frame * frm)413 static inline void security(int level, uint8_t hdr, struct frame *frm)
414 {
415 	switch (hdr & 0x03) {
416 	case 0x00:
417 		acp_seid(level, frm);
418 	case 0x02:
419 		hex_dump(level + 1, frm, frm->len);
420 		frm->ptr += frm->len;
421 		frm->len = 0;
422 		break;
423 	case 0x03:
424 		errorcode(level, frm);
425 		break;
426 	}
427 }
428 
delay_report(int level,uint8_t hdr,struct frame * frm)429 static inline void delay_report(int level, uint8_t hdr, struct frame *frm)
430 {
431 	uint8_t seid;
432 	uint16_t delay;
433 
434 	switch (hdr & 0x03) {
435 	case 0x00:
436 		p_indent(level, frm);
437 		seid = get_u8(frm);
438 		delay = get_u16(frm);
439 		printf("ACP SEID %d delay %u.%ums\n", seid >> 2,
440 						delay / 10, delay % 10);
441 		break;
442 	case 0x03:
443 		errorcode(level, frm);
444 		break;
445 	}
446 }
447 
avdtp_dump(int level,struct frame * frm)448 void avdtp_dump(int level, struct frame *frm)
449 {
450 	uint8_t hdr, sid, nsp, type;
451 	uint16_t seqn;
452 	uint32_t time, ssrc;
453 
454 	switch (frm->num) {
455 	case 1:
456 		p_indent(level, frm);
457 		hdr = get_u8(frm);
458 
459 		nsp = (hdr & 0x0c) == 0x04 ? get_u8(frm) : 0;
460 		sid = hdr & 0x08 ? 0x00 : get_u8(frm);
461 
462 		printf("AVDTP(s): %s %s: transaction %d\n",
463 			hdr & 0x08 ? pt2str(hdr) : si2str(sid), mt2str(hdr), hdr >> 4);
464 
465 		switch (sid & 0x7f) {
466 		case 0x01:
467 			discover(level + 1, hdr, frm);
468 			break;
469 		case 0x02:
470 		case 0x0c:
471 			get_capabilities(level + 1, hdr, frm);
472 			break;
473 		case 0x03:
474 			set_configuration(level + 1, hdr, frm);
475 			break;
476 		case 0x04:
477 			get_configuration(level + 1, hdr, frm);
478 			break;
479 		case 0x05:
480 			reconfigure(level + 1, hdr, frm);
481 			break;
482 		case 0x06:
483 			open_close_stream(level + 1, hdr, frm);
484 			break;
485 		case 0x07:
486 			start_suspend_stream(level + 1, hdr, frm);
487 			break;
488 		case 0x08:
489 			open_close_stream(level + 1, hdr, frm);
490 			break;
491 		case 0x09:
492 			start_suspend_stream(level + 1, hdr, frm);
493 			break;
494 		case 0x0a:
495 			abort_streaming(level + 1, hdr, frm);
496 			break;
497 		case 0x0b:
498 			security(level + 1, hdr, frm);
499 			break;
500 		case 0x0d:
501 			delay_report(level + 1, hdr, frm);
502 			break;
503 		}
504 
505 		break;
506 
507 	case 2:
508 		p_indent(level, frm);
509 		hdr  = get_u8(frm);
510 		type = get_u8(frm);
511 		seqn = get_u16(frm);
512 		time = get_u32(frm);
513 		ssrc = get_u32(frm);
514 
515 		printf("AVDTP(m): ver %d %s%scc %d %spt %d seqn %d time %d ssrc %d\n",
516 			hdr >> 6, hdr & 0x20 ? "pad " : "", hdr & 0x10 ? "ext " : "",
517 			hdr & 0xf, type & 0x80 ? "mark " : "", type & 0x7f, seqn, time, ssrc);
518 		break;
519 	}
520 
521 	raw_dump(level, frm);
522 }
523