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