3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2015 Andrzej Kaczmarek <andrzej.kaczmarek@codecoup.pl>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library 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 GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 #include "lib/bluetooth.h"
34 #include "src/shared/util.h"
42 #define AVDTP_MSG_TYPE_COMMAND 0x00
43 #define AVDTP_MSG_TYPE_GENERAL_REJECT 0x01
44 #define AVDTP_MSG_TYPE_RESPONSE_ACCEPT 0x02
45 #define AVDTP_MSG_TYPE_RESPONSE_REJECT 0x03
47 /* Signal Identifiers */
48 #define AVDTP_DISCOVER 0x01
49 #define AVDTP_GET_CAPABILITIES 0x02
50 #define AVDTP_SET_CONFIGURATION 0x03
51 #define AVDTP_GET_CONFIGURATION 0x04
52 #define AVDTP_RECONFIGURE 0x05
53 #define AVDTP_OPEN 0x06
54 #define AVDTP_START 0x07
55 #define AVDTP_CLOSE 0x08
56 #define AVDTP_SUSPEND 0x09
57 #define AVDTP_ABORT 0x0a
58 #define AVDTP_SECURITY_CONTROL 0x0b
59 #define AVDTP_GET_ALL_CAPABILITIES 0x0c
60 #define AVDTP_DELAYREPORT 0x0d
62 /* Service Categories */
63 #define AVDTP_MEDIA_TRANSPORT 0x01
64 #define AVDTP_REPORTING 0x02
65 #define AVDTP_RECOVERY 0x03
66 #define AVDTP_CONTENT_PROTECTION 0x04
67 #define AVDTP_HEADER_COMPRESSION 0x05
68 #define AVDTP_MULTIPLEXING 0x06
69 #define AVDTP_MEDIA_CODEC 0x07
70 #define AVDTP_DELAY_REPORTING 0x08
75 struct l2cap_frame l2cap_frame;
78 static const char *msgtype2str(uint8_t msgtype)
84 return "General Reject";
86 return "Response Accept";
88 return "Response Reject";
94 static const char *sigid2str(uint8_t sigid)
99 case AVDTP_GET_CAPABILITIES:
100 return "Get Capabilities";
101 case AVDTP_SET_CONFIGURATION:
102 return "Set Configuration";
103 case AVDTP_GET_CONFIGURATION:
104 return "Get Configuration";
105 case AVDTP_RECONFIGURE:
106 return "Reconfigure";
117 case AVDTP_SECURITY_CONTROL:
118 return "Security Control";
119 case AVDTP_GET_ALL_CAPABILITIES:
120 return "Get All Capabilities";
121 case AVDTP_DELAYREPORT:
122 return "Delay Report";
128 static const char *error2str(uint8_t error)
132 return "BAD_HEADER_FORMAT";
136 return "BAD_ACP_SEID";
140 return "SEP_NOT_IN_USER";
142 return "BAD_SERV_CATEGORY";
144 return "BAD_PAYLOAD_FORMAT";
146 return "NOT_SUPPORTED_COMMAND";
148 return "INVALID_CAPABILITIES";
150 return "BAD_RECOVERY_TYPE";
152 return "BAD_MEDIA_TRANSPORT_FORMAT";
154 return "BAD_RECOVERY_FORMAT";
156 return "BAD_ROHC_FORMAT";
158 return "BAD_CP_FORMAT";
160 return "BAD_MULTIPLEXING_FORMAT";
162 return "UNSUPPORTED_CONFIGURATION";
170 static const char *mediatype2str(uint8_t media_type)
172 switch (media_type) {
184 static const char *servicecat2str(uint8_t service_cat)
186 switch (service_cat) {
187 case AVDTP_MEDIA_TRANSPORT:
188 return "Media Transport";
189 case AVDTP_REPORTING:
193 case AVDTP_CONTENT_PROTECTION:
194 return "Content Protection";
195 case AVDTP_HEADER_COMPRESSION:
196 return "Header Compression";
197 case AVDTP_MULTIPLEXING:
198 return "Multiplexing";
199 case AVDTP_MEDIA_CODEC:
200 return "Media Codec";
201 case AVDTP_DELAY_REPORTING:
202 return "Delay Reporting";
208 static bool avdtp_reject_common(struct avdtp_frame *avdtp_frame)
210 struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
213 if (!l2cap_frame_get_u8(frame, &error))
216 print_field("Error code: %s (0x%02x)", error2str(error), error);
221 static bool decode_capabilities(struct avdtp_frame *avdtp_frame)
223 struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
227 while (l2cap_frame_get_u8(frame, &service_cat)) {
228 print_field("Service Category: %s (0x%02x)",
229 servicecat2str(service_cat), service_cat);
231 if (!l2cap_frame_get_u8(frame, &losc))
234 if (frame->size < losc)
237 /* TODO: decode service capabilities */
239 packet_hexdump(frame->data, losc);
241 l2cap_frame_pull(frame, frame, losc);
247 static bool avdtp_discover(struct avdtp_frame *avdtp_frame)
249 struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
250 uint8_t type = avdtp_frame->hdr & 0x03;
255 case AVDTP_MSG_TYPE_COMMAND:
257 case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
258 while (l2cap_frame_get_u8(frame, &seid)) {
259 print_field("ACP SEID: %d", seid >> 2);
261 if (!l2cap_frame_get_u8(frame, &info))
264 print_field("%*cMedia Type: %s (0x%02x)", 2, ' ',
265 mediatype2str(info >> 4), info >> 4);
266 print_field("%*cSEP Type: %s (0x%02x)", 2, ' ',
267 info & 0x04 ? "SNK" : "SRC",
269 print_field("%*cIn use: %s", 2, ' ',
270 seid & 0x02 ? "Yes" : "No");
273 case AVDTP_MSG_TYPE_RESPONSE_REJECT:
274 return avdtp_reject_common(avdtp_frame);
280 static bool avdtp_get_capabilities(struct avdtp_frame *avdtp_frame)
282 struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
283 uint8_t type = avdtp_frame->hdr & 0x03;
287 case AVDTP_MSG_TYPE_COMMAND:
288 if (!l2cap_frame_get_u8(frame, &seid))
291 print_field("ACP SEID: %d", seid >> 2);
294 case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
295 return decode_capabilities(avdtp_frame);
296 case AVDTP_MSG_TYPE_RESPONSE_REJECT:
297 return avdtp_reject_common(avdtp_frame);
303 static bool avdtp_set_configuration(struct avdtp_frame *avdtp_frame)
305 struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
306 uint8_t type = avdtp_frame->hdr & 0x03;
307 uint8_t acp_seid, int_seid;
311 case AVDTP_MSG_TYPE_COMMAND:
312 if (!l2cap_frame_get_u8(frame, &acp_seid))
315 print_field("ACP SEID: %d", acp_seid >> 2);
317 if (!l2cap_frame_get_u8(frame, &int_seid))
320 print_field("INT SEID: %d", int_seid >> 2);
322 return decode_capabilities(avdtp_frame);
323 case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
325 case AVDTP_MSG_TYPE_RESPONSE_REJECT:
326 if (!l2cap_frame_get_u8(frame, &service_cat))
329 print_field("Service Category: %s (0x%02x)",
330 servicecat2str(service_cat), service_cat);
332 return avdtp_reject_common(avdtp_frame);
338 static bool avdtp_get_configuration(struct avdtp_frame *avdtp_frame)
340 struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
341 uint8_t type = avdtp_frame->hdr & 0x03;
345 case AVDTP_MSG_TYPE_COMMAND:
346 if (!l2cap_frame_get_u8(frame, &seid))
349 print_field("ACP SEID: %d", seid >> 2);
352 case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
353 return decode_capabilities(avdtp_frame);
354 case AVDTP_MSG_TYPE_RESPONSE_REJECT:
355 return avdtp_reject_common(avdtp_frame);
361 static bool avdtp_reconfigure(struct avdtp_frame *avdtp_frame)
363 struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
364 uint8_t type = avdtp_frame->hdr & 0x03;
369 case AVDTP_MSG_TYPE_COMMAND:
370 if (!l2cap_frame_get_u8(frame, &seid))
373 print_field("ACP SEID: %d", seid >> 2);
375 return decode_capabilities(avdtp_frame);
376 case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
378 case AVDTP_MSG_TYPE_RESPONSE_REJECT:
379 if (!l2cap_frame_get_u8(frame, &service_cat))
382 print_field("Service Category: %s (0x%02x)",
383 servicecat2str(service_cat), service_cat);
385 return avdtp_reject_common(avdtp_frame);
391 static bool avdtp_open(struct avdtp_frame *avdtp_frame)
393 struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
394 uint8_t type = avdtp_frame->hdr & 0x03;
398 case AVDTP_MSG_TYPE_COMMAND:
399 if (!l2cap_frame_get_u8(frame, &seid))
402 print_field("ACP SEID: %d", seid >> 2);
405 case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
407 case AVDTP_MSG_TYPE_RESPONSE_REJECT:
408 return avdtp_reject_common(avdtp_frame);
414 static bool avdtp_start(struct avdtp_frame *avdtp_frame)
416 struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
417 uint8_t type = avdtp_frame->hdr & 0x03;
421 case AVDTP_MSG_TYPE_COMMAND:
422 if (!l2cap_frame_get_u8(frame, &seid))
425 print_field("ACP SEID: %d", seid >> 2);
427 while (l2cap_frame_get_u8(frame, &seid))
428 print_field("ACP SEID: %d", seid >> 2);
431 case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
433 case AVDTP_MSG_TYPE_RESPONSE_REJECT:
434 if (!l2cap_frame_get_u8(frame, &seid))
437 print_field("ACP SEID: %d", seid >> 2);
439 return avdtp_reject_common(avdtp_frame);
445 static bool avdtp_close(struct avdtp_frame *avdtp_frame)
447 struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
448 uint8_t type = avdtp_frame->hdr & 0x03;
452 case AVDTP_MSG_TYPE_COMMAND:
453 if (!l2cap_frame_get_u8(frame, &seid))
456 print_field("ACP SEID: %d", seid >> 2);
459 case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
461 case AVDTP_MSG_TYPE_RESPONSE_REJECT:
462 return avdtp_reject_common(avdtp_frame);
468 static bool avdtp_signalling_packet(struct avdtp_frame *avdtp_frame)
470 struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
471 const char *pdu_color;
477 pdu_color = COLOR_MAGENTA;
479 pdu_color = COLOR_BLUE;
481 if (!l2cap_frame_get_u8(frame, &hdr))
484 avdtp_frame->hdr = hdr;
486 /* Continue Packet || End Packet */
487 if (((hdr & 0x0c) == 0x08) || ((hdr & 0x0c) == 0x0c)) {
488 /* TODO: handle fragmentation */
489 packet_hexdump(frame->data, frame->size);
494 if ((hdr & 0x0c) == 0x04) {
495 if (!l2cap_frame_get_u8(frame, &nosp))
499 if (!l2cap_frame_get_u8(frame, &sig_id))
504 avdtp_frame->sig_id = sig_id;
506 print_indent(6, pdu_color, "AVDTP: ", sigid2str(sig_id), COLOR_OFF,
507 " (0x%02x) %s (0x%02x) type 0x%02x label %d nosp %d",
508 sig_id, msgtype2str(hdr & 0x03), hdr & 0x03,
509 hdr & 0x0c, hdr >> 4, nosp);
512 if ((hdr & 0x0c) == 0x04) {
513 /* TODO: handle fragmentation */
514 packet_hexdump(frame->data, frame->size);
519 if ((hdr & 0x03) == 0x03)
524 return avdtp_discover(avdtp_frame);
525 case AVDTP_GET_CAPABILITIES:
526 return avdtp_get_capabilities(avdtp_frame);
527 case AVDTP_SET_CONFIGURATION:
528 return avdtp_set_configuration(avdtp_frame);
529 case AVDTP_GET_CONFIGURATION:
530 return avdtp_get_configuration(avdtp_frame);
531 case AVDTP_RECONFIGURE:
532 return avdtp_reconfigure(avdtp_frame);
534 return avdtp_open(avdtp_frame);
536 return avdtp_start(avdtp_frame);
538 return avdtp_close(avdtp_frame);
541 packet_hexdump(frame->data, frame->size);
546 void avdtp_packet(const struct l2cap_frame *frame)
548 struct avdtp_frame avdtp_frame;
551 l2cap_frame_pull(&avdtp_frame.l2cap_frame, frame, 0);
553 switch (frame->seq_num) {
555 ret = avdtp_signalling_packet(&avdtp_frame);
558 packet_hexdump(frame->data, frame->size);
563 print_text(COLOR_ERROR, "PDU malformed");
564 packet_hexdump(frame->data, frame->size);