• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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