Upgrade bluez5_37 :Merge the code from private
[platform/upstream/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 *vndcodec2str(uint32_t vendor, uint16_t vndcodec)
154 {
155         if (vendor == 0x0000004f && vndcodec == 0x0001)
156                 return "aptX";
157         else if (vendor == 0x0000012d && vndcodec == 0x00aa)
158                 return "LDAC";
159         return "Unknown";
160 }
161
162 static char *cat2str(uint8_t cat)
163 {
164         switch (cat) {
165         case 1:
166                 return "Media Transport";
167         case 2:
168                 return "Reporting";
169         case 3:
170                 return "Recovery";
171         case 4:
172                 return "Content Protection";
173         case 5:
174                 return "Header Compression";
175         case 6:
176                 return "Multiplexing";
177         case 7:
178                 return "Media Codec";
179         case 8:
180                 return "Delay Reporting";
181         default:
182                 return "Reserved";
183         }
184 }
185
186 static void errorcode(int level, struct frame *frm)
187 {
188         uint8_t code;
189
190         p_indent(level, frm);
191         code = p_get_u8(frm);
192         printf("Error code %d\n", code);
193 }
194
195 static void acp_seid(int level, struct frame *frm)
196 {
197         uint8_t seid;
198
199         p_indent(level, frm);
200         seid = p_get_u8(frm);
201         printf("ACP SEID %d\n", seid >> 2);
202 }
203
204 static void acp_int_seid(int level, struct frame *frm)
205 {
206         uint8_t acp_seid, int_seid;
207
208         p_indent(level, frm);
209         acp_seid = p_get_u8(frm);
210         int_seid = p_get_u8(frm);
211         printf("ACP SEID %d - INT SEID %d\n", acp_seid >> 2, int_seid >> 2);
212 }
213
214 static void capabilities(int level, struct frame *frm)
215 {
216         uint8_t cat, len;
217
218         while (frm->len > 1) {
219                 p_indent(level, frm);
220                 cat = p_get_u8(frm);
221                 len = p_get_u8(frm);
222
223                 if (cat == 7) {
224                         uint8_t type, codec;
225                         uint16_t tmp, freq, vndcodec = 0;
226                         uint32_t bitrate, vendor = 0;
227                         int i;
228
229                         type  = p_get_u8(frm);
230                         codec = p_get_u8(frm);
231
232                         if (codec == 255) {
233                                 vendor = btohl(htonl(p_get_u32(frm)));
234                                 vndcodec = btohs(htons(p_get_u16(frm)));
235
236                                 printf("%s - %s (%s)\n", cat2str(cat),
237                                                 codec2str(type, codec),
238                                                 vndcodec2str(vendor, vndcodec));
239                         } else {
240                                 printf("%s - %s\n", cat2str(cat),
241                                                         codec2str(type, codec));
242                         }
243
244                         switch (codec) {
245                         case 0:
246                                 tmp = p_get_u8(frm);
247                                 p_indent(level + 1, frm);
248                                 if (tmp & 0x80)
249                                         printf("16kHz ");
250                                 if (tmp & 0x40)
251                                         printf("32kHz ");
252                                 if (tmp & 0x20)
253                                         printf("44.1kHz ");
254                                 if (tmp & 0x10)
255                                         printf("48kHz ");
256                                 printf("\n");
257                                 p_indent(level + 1, frm);
258                                 if (tmp & 0x08)
259                                         printf("Mono ");
260                                 if (tmp & 0x04)
261                                         printf("DualChannel ");
262                                 if (tmp & 0x02)
263                                         printf("Stereo ");
264                                 if (tmp & 0x01)
265                                         printf("JointStereo ");
266                                 printf("\n");
267                                 tmp = p_get_u8(frm);
268                                 p_indent(level + 1, frm);
269                                 if (tmp & 0x80)
270                                         printf("4 ");
271                                 if (tmp & 0x40)
272                                         printf("8 ");
273                                 if (tmp & 0x20)
274                                         printf("12 ");
275                                 if (tmp & 0x10)
276                                         printf("16 ");
277                                 printf("Blocks\n");
278                                 p_indent(level + 1, frm);
279                                 if (tmp & 0x08)
280                                         printf("4 ");
281                                 if (tmp & 0x04)
282                                         printf("8 ");
283                                 printf("Subbands\n");
284                                 p_indent(level + 1, frm);
285                                 if (tmp & 0x02)
286                                         printf("SNR ");
287                                 if (tmp & 0x01)
288                                         printf("Loudness ");
289                                 printf("\n");
290                                 tmp = p_get_u8(frm);
291                                 p_indent(level + 1, frm);
292                                 printf("Bitpool Range %d-%d\n", tmp, p_get_u8(frm));
293                                 break;
294                         case 1:
295                                 tmp = p_get_u8(frm);
296                                 p_indent(level + 1, frm);
297                                 printf("Layers: ");
298                                 if (tmp & 0x80)
299                                         printf("1 ");
300                                 if (tmp & 0x40)
301                                         printf("2 ");
302                                 if (tmp & 0x20)
303                                         printf("3 ");
304                                 printf("\n");
305                                 p_indent(level + 1, frm);
306                                 printf("CRC Protection: %s\n",
307                                                 tmp & 0x10 ? "Yes" : "No");
308                                 p_indent(level + 1, frm);
309                                 if (tmp & 0x08)
310                                         printf("Mono ");
311                                 if (tmp & 0x04)
312                                         printf("DualChannel ");
313                                 if (tmp & 0x02)
314                                         printf("Stereo ");
315                                 if (tmp & 0x01)
316                                         printf("JointStereo ");
317                                 printf("\n");
318                                 tmp = p_get_u8(frm);
319                                 p_indent(level + 1, frm);
320                                 printf("Media Payload Format: RFC-2250 %s\n",
321                                                 tmp & 0x40 ? "RFC-3119" : "");
322                                 p_indent(level + 1, frm);
323                                 if (tmp & 0x20)
324                                         printf("16kHz ");
325                                 if (tmp & 0x10)
326                                         printf("22.05kHz ");
327                                 if (tmp & 0x08)
328                                         printf("24kHz ");
329                                 if (tmp & 0x04)
330                                         printf("32kHz ");
331                                 if (tmp & 0x02)
332                                         printf("44.1kHz ");
333                                 if (tmp & 0x01)
334                                         printf("48kHz ");
335                                 printf("\n");
336                                 tmp = p_get_u16(frm);
337                                 p_indent(level + 1, frm);
338                                 printf("VBR: %s\n",
339                                                 tmp & 0x8000 ? "Yes" : "No");
340                                 p_indent(level + 1, frm);
341                                 printf("Bit Rate Indexes: ");
342                                 if (tmp & 0x8000) {
343                                         printf("n/a");
344                                 } else {
345                                         for (i = 0; i < 15; i++, tmp >>= 1)
346                                                 if (tmp & 0x0001)
347                                                         printf("%d ", i);
348                                 }
349                                 printf("\n");
350                                 break;
351                         case 2:
352                                 tmp = p_get_u8(frm);
353                                 p_indent(level + 1, frm);
354                                 if (tmp & 0x80)
355                                         printf("MPEG-2 AAC LC ");
356                                 if (tmp & 0x40)
357                                         printf("MPEG-4 AAC LC ");
358                                 if (tmp & 0x20)
359                                         printf("MPEG-4 AAC LTP ");
360                                 if (tmp & 0x10)
361                                         printf("MPEG-4 AAC scalable ");
362                                 printf("\n");
363                                 tmp = p_get_u16(frm);
364                                 freq = tmp >> 4;
365                                 p_indent(level + 1, frm);
366                                 if (freq & 0x0800)
367                                         printf("8kHz ");
368                                 if (freq & 0x0400)
369                                         printf("11.025kHz ");
370                                 if (freq & 0x0200)
371                                         printf("12kHz ");
372                                 if (freq & 0x0100)
373                                         printf("16kHz ");
374                                 if (freq & 0x0080)
375                                         printf("22.05kHz ");
376                                 if (freq & 0x0040)
377                                         printf("24kHz ");
378                                 if (freq & 0x0020)
379                                         printf("32kHz ");
380                                 if (freq & 0x0010)
381                                         printf("44.1kHz ");
382                                 if (freq & 0x0008)
383                                         printf("48kHz ");
384                                 if (freq & 0x0004)
385                                         printf("64kHz ");
386                                 if (freq & 0x0002)
387                                         printf("88.2kHz ");
388                                 if (freq & 0x0001)
389                                         printf("96kHz ");
390                                 printf("\n");
391                                 tmp >>= 2;
392                                 p_indent(level + 1, frm);
393                                 if (tmp & 0x02)
394                                         printf("1 ");
395                                 if (tmp & 0x01)
396                                         printf("2 ");
397                                 printf("Channels\n");
398                                 tmp = p_get_u8(frm);
399                                 bitrate = ((tmp & 0x7f) << 16) | p_get_u16(frm);
400                                 p_indent(level + 1, frm);
401                                 printf("%ubps ", bitrate);
402                                 printf("%s\n", tmp & 0x80 ? "VBR" : "");
403                                 break;
404                         case 255:
405                                 if (vendor == 0x0000004f &&
406                                                         vndcodec == 0x0001) {
407                                         tmp = p_get_u8(frm);
408                                         p_indent(level + 1, frm);
409                                         if (tmp & 0x80)
410                                                 printf("16kHz ");
411                                         if (tmp & 0x40)
412                                                 printf("32kHz ");
413                                         if (tmp & 0x20)
414                                                 printf("44.1kHz ");
415                                         if (tmp & 0x10)
416                                                 printf("48kHz ");
417                                         printf("\n");
418                                         p_indent(level + 1, frm);
419                                         if (tmp & 0x02)
420                                                 printf("Stereo ");
421                                         if (tmp & 0x01)
422                                                 printf("Mono ");
423                                         printf("\n");
424                                         break;
425                                 } else {
426                                         hex_dump(level + 1, frm, len - 8);
427                                         frm->ptr += (len - 8);
428                                         frm->len -= (len - 8);
429                                 }
430                                 break;
431                         default:
432                                 hex_dump(level + 1, frm, len - 2);
433                                 frm->ptr += (len - 2);
434                                 frm->len -= (len - 2);
435                                 break;
436                         }
437                 } else {
438                         printf("%s\n", cat2str(cat));
439                         hex_dump(level + 1, frm, len);
440
441                         frm->ptr += len;
442                         frm->len -= len;
443                 }
444         }
445 }
446
447 static inline void discover(int level, uint8_t hdr, struct frame *frm)
448 {
449         uint8_t seid, type;
450
451         switch (hdr & 0x03) {
452         case 0x02:
453                 while (frm->len > 1) {
454                         p_indent(level, frm);
455                         seid = p_get_u8(frm);
456                         type = p_get_u8(frm);
457                         printf("ACP SEID %d - %s %s%s\n",
458                                 seid >> 2, media2str(type >> 4),
459                                 type & 0x08 ? "Sink" : "Source",
460                                 seid & 0x02 ? " (InUse)" : "");
461                 }
462                 break;
463         case 0x03:
464                 errorcode(level, frm);
465                 break;
466         }
467 }
468
469 static inline void get_capabilities(int level, uint8_t hdr, struct frame *frm)
470 {
471         switch (hdr & 0x03) {
472         case 0x00:
473                 acp_seid(level, frm);
474                 break;
475         case 0x02:
476                 capabilities(level, frm);
477                 break;
478         case 0x03:
479                 errorcode(level, frm);
480                 break;
481         }
482 }
483
484 static inline void set_configuration(int level, uint8_t hdr, struct frame *frm)
485 {
486         uint8_t cat;
487
488         switch (hdr & 0x03) {
489         case 0x00:
490                 acp_int_seid(level, frm);
491                 capabilities(level, frm);
492                 break;
493         case 0x03:
494                 p_indent(level, frm);
495                 cat = p_get_u8(frm);
496                 printf("%s\n", cat2str(cat));
497                 errorcode(level, frm);
498                 break;
499         }
500 }
501
502 static inline void get_configuration(int level, uint8_t hdr, struct frame *frm)
503 {
504         switch (hdr & 0x03) {
505         case 0x00:
506                 acp_seid(level, frm);
507         case 0x02:
508                 capabilities(level, frm);
509                 break;
510         case 0x03:
511                 errorcode(level, frm);
512                 break;
513         }
514 }
515
516 static inline void reconfigure(int level, uint8_t hdr, struct frame *frm)
517 {
518         uint8_t cat;
519
520         switch (hdr & 0x03) {
521         case 0x00:
522                 acp_seid(level, frm);
523                 capabilities(level, frm);
524                 break;
525         case 0x03:
526                 p_indent(level, frm);
527                 cat = p_get_u8(frm);
528                 printf("%s\n", cat2str(cat));
529                 errorcode(level, frm);
530                 break;
531         }
532 }
533
534 static inline void open_close_stream(int level, uint8_t hdr, struct frame *frm)
535 {
536         switch (hdr & 0x03) {
537         case 0x00:
538                 acp_seid(level, frm);
539                 break;
540         case 0x03:
541                 errorcode(level, frm);
542                 break;
543         }
544 }
545
546 static inline void start_suspend_stream(int level, uint8_t hdr, struct frame *frm)
547 {
548         switch (hdr & 0x03) {
549         case 0x00:
550                 while (frm->len > 0)
551                         acp_seid(level, frm);
552                 break;
553         case 0x03:
554                 acp_seid(level, frm);
555                 errorcode(level, frm);
556                 break;
557         }
558 }
559
560 static inline void abort_streaming(int level, uint8_t hdr, struct frame *frm)
561 {
562         switch (hdr & 0x03) {
563         case 0x00:
564                 acp_seid(level, frm);
565                 break;
566         }
567 }
568
569 static inline void security(int level, uint8_t hdr, struct frame *frm)
570 {
571         switch (hdr & 0x03) {
572         case 0x00:
573                 acp_seid(level, frm);
574         case 0x02:
575                 hex_dump(level + 1, frm, frm->len);
576                 frm->ptr += frm->len;
577                 frm->len = 0;
578                 break;
579         case 0x03:
580                 errorcode(level, frm);
581                 break;
582         }
583 }
584
585 static inline void delay_report(int level, uint8_t hdr, struct frame *frm)
586 {
587         uint8_t seid;
588         uint16_t delay;
589
590         switch (hdr & 0x03) {
591         case 0x00:
592                 p_indent(level, frm);
593                 seid = p_get_u8(frm);
594                 delay = p_get_u16(frm);
595                 printf("ACP SEID %d delay %u.%ums\n", seid >> 2,
596                                                 delay / 10, delay % 10);
597                 break;
598         case 0x03:
599                 errorcode(level, frm);
600                 break;
601         }
602 }
603
604 void avdtp_dump(int level, struct frame *frm)
605 {
606         uint8_t hdr, sid, nsp, type;
607         uint16_t seqn;
608         uint32_t time, ssrc;
609
610         switch (frm->num) {
611         case 1:
612                 p_indent(level, frm);
613                 hdr = p_get_u8(frm);
614
615                 nsp = (hdr & 0x0c) == 0x04 ? p_get_u8(frm) : 0;
616                 sid = hdr & 0x08 ? 0x00 : p_get_u8(frm);
617
618                 printf("AVDTP(s): %s %s: transaction %d nsp 0x%02x\n",
619                         hdr & 0x08 ? pt2str(hdr) : si2str(sid),
620                         mt2str(hdr), hdr >> 4, nsp);
621
622                 switch (sid & 0x7f) {
623                 case 0x01:
624                         discover(level + 1, hdr, frm);
625                         break;
626                 case 0x02:
627                 case 0x0c:
628                         get_capabilities(level + 1, hdr, frm);
629                         break;
630                 case 0x03:
631                         set_configuration(level + 1, hdr, frm);
632                         break;
633                 case 0x04:
634                         get_configuration(level + 1, hdr, frm);
635                         break;
636                 case 0x05:
637                         reconfigure(level + 1, hdr, frm);
638                         break;
639                 case 0x06:
640                         open_close_stream(level + 1, hdr, frm);
641                         break;
642                 case 0x07:
643                         start_suspend_stream(level + 1, hdr, frm);
644                         break;
645                 case 0x08:
646                         open_close_stream(level + 1, hdr, frm);
647                         break;
648                 case 0x09:
649                         start_suspend_stream(level + 1, hdr, frm);
650                         break;
651                 case 0x0a:
652                         abort_streaming(level + 1, hdr, frm);
653                         break;
654                 case 0x0b:
655                         security(level + 1, hdr, frm);
656                         break;
657                 case 0x0d:
658                         delay_report(level + 1, hdr, frm);
659                         break;
660                 }
661
662                 break;
663
664         case 2:
665                 p_indent(level, frm);
666                 hdr  = p_get_u8(frm);
667                 type = p_get_u8(frm);
668                 seqn = p_get_u16(frm);
669                 time = p_get_u32(frm);
670                 ssrc = p_get_u32(frm);
671
672                 printf("AVDTP(m): ver %d %s%scc %d %spt %d seqn %d time %d ssrc %d\n",
673                         hdr >> 6, hdr & 0x20 ? "pad " : "", hdr & 0x10 ? "ext " : "",
674                         hdr & 0xf, type & 0x80 ? "mark " : "", type & 0x7f, seqn, time, ssrc);
675                 break;
676         }
677
678         raw_dump(level, frm);
679 }