avdtp_util.c (ea6072aff7664340978c5dd4457bb44e23303e5b) | avdtp_util.c (f6f3c9037bb5af01c27f4ed83398f8a68d35a69b) |
---|---|
1/* 2 * Copyright (C) 2016 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright --- 321 unchanged lines hidden (view full) --- 330 if (cap_len != 0){ 331 log_info(" ERROR: REJECT CATEGORY, BAD_LENGTH\n"); 332 connection->reject_service_category = category; 333 connection->error_code = BAD_LENGTH; 334 return 1; 335 } 336 break; 337 case AVDTP_RECOVERY: | 1/* 2 * Copyright (C) 2016 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright --- 321 unchanged lines hidden (view full) --- 330 if (cap_len != 0){ 331 log_info(" ERROR: REJECT CATEGORY, BAD_LENGTH\n"); 332 connection->reject_service_category = category; 333 connection->error_code = BAD_LENGTH; 334 return 1; 335 } 336 break; 337 case AVDTP_RECOVERY: |
338 if (cap_len < 3){ | 338 if (cap_len != 3){ |
339 log_info(" ERROR: REJECT CATEGORY, BAD_MEDIA_TRANSPORT\n"); 340 connection->reject_service_category = category; 341 connection->error_code = BAD_RECOVERY_FORMAT; 342 return 1; 343 } 344 break; 345 case AVDTP_CONTENT_PROTECTION: 346 if (cap_len < 2){ 347 log_info(" ERROR: REJECT CATEGORY, BAD_CP_FORMAT\n"); 348 connection->reject_service_category = category; 349 connection->error_code = BAD_CP_FORMAT; 350 return 1; 351 } 352 break; 353 case AVDTP_HEADER_COMPRESSION: | 339 log_info(" ERROR: REJECT CATEGORY, BAD_MEDIA_TRANSPORT\n"); 340 connection->reject_service_category = category; 341 connection->error_code = BAD_RECOVERY_FORMAT; 342 return 1; 343 } 344 break; 345 case AVDTP_CONTENT_PROTECTION: 346 if (cap_len < 2){ 347 log_info(" ERROR: REJECT CATEGORY, BAD_CP_FORMAT\n"); 348 connection->reject_service_category = category; 349 connection->error_code = BAD_CP_FORMAT; 350 return 1; 351 } 352 break; 353 case AVDTP_HEADER_COMPRESSION: |
354 // TODO: find error code for bad header compression 355 if (cap_len != 1){ 356 log_info(" ERROR: REJECT CATEGORY, BAD_HEADER_COMPRESSION\n"); 357 connection->reject_service_category = category; 358 connection->error_code = BAD_RECOVERY_FORMAT; 359 return 1; 360 } |
|
354 break; 355 case AVDTP_MULTIPLEXING: 356 break; 357 case AVDTP_MEDIA_CODEC: 358 break; 359 default: 360 break; 361 } 362 return 0; 363} 364 365uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdtp_capabilities_t * caps, uint8_t * packet, uint16_t size){ | 361 break; 362 case AVDTP_MULTIPLEXING: 363 break; 364 case AVDTP_MEDIA_CODEC: 365 break; 366 default: 367 break; 368 } 369 return 0; 370} 371 372uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdtp_capabilities_t * caps, uint8_t * packet, uint16_t size){ |
366 if (size == 0) return 0; | |
367 | 373 |
368 uint16_t registered_service_categories = 0; 369 int pos = 0; | |
370 int i; | 374 int i; |
371 avdtp_service_category_t category = (avdtp_service_category_t)packet[pos++]; 372 uint8_t cap_len = packet[pos++]; 373 if (cap_len > size - pos){ 374 connection->reject_service_category = category; 375 connection->error_code = BAD_LENGTH; 376 return 0; 377 } 378 379 if (avdtp_unpack_service_capabilities_has_errors(connection, category, cap_len)) return 0; 380 381 int processed_cap_len = 0; 382 int rfa = 0; 383 384 while (pos < size){ 385 rfa = 0; 386 processed_cap_len = pos; | 375 376 uint16_t registered_service_categories = 0; 377 uint16_t to_process = size; 378 379 while (to_process >= 2){ 380 381 avdtp_service_category_t category = (avdtp_service_category_t) packet[0]; 382 uint8_t cap_len = packet[1]; 383 packet += 2; 384 to_process -= 2; 385 386 if (cap_len > to_process){ 387 connection->reject_service_category = category; 388 connection->error_code = BAD_LENGTH; 389 return 0; 390 } 391 392 if (avdtp_unpack_service_capabilities_has_errors(connection, category, cap_len)) return 0; 393 394 int category_valid = 1; 395 396 uint8_t * data = packet; 397 uint16_t pos = 0; 398 |
387 switch(category){ 388 case AVDTP_RECOVERY: | 399 switch(category){ 400 case AVDTP_RECOVERY: |
389 caps->recovery.recovery_type = packet[pos++]; 390 caps->recovery.maximum_recovery_window_size = packet[pos++]; 391 caps->recovery.maximum_number_media_packets = packet[pos++]; | 401 caps->recovery.recovery_type = data[pos++]; 402 caps->recovery.maximum_recovery_window_size = data[pos++]; 403 caps->recovery.maximum_number_media_packets = data[pos++]; |
392 break; 393 case AVDTP_CONTENT_PROTECTION: | 404 break; 405 case AVDTP_CONTENT_PROTECTION: |
394 caps->content_protection.cp_type = big_endian_read_16(packet, pos); 395 pos+=2; 396 | 406 caps->content_protection.cp_type = big_endian_read_16(data, 0); |
397 caps->content_protection.cp_type_value_len = cap_len - 2; | 407 caps->content_protection.cp_type_value_len = cap_len - 2; |
398 pos += caps->content_protection.cp_type_value_len; 399 | |
400 // connection->reject_service_category = category; 401 // connection->error_code = UNSUPPORTED_CONFIGURATION; 402 // support for content protection goes here 403 break; | 408 // connection->reject_service_category = category; 409 // connection->error_code = UNSUPPORTED_CONFIGURATION; 410 // support for content protection goes here 411 break; |
404 | |
405 case AVDTP_HEADER_COMPRESSION: | 412 case AVDTP_HEADER_COMPRESSION: |
406 caps->header_compression.back_ch = packet[pos] >> 7; 407 caps->header_compression.media = packet[pos] >> 6; 408 caps->header_compression.recovery = packet[pos] >> 5; 409 pos++; | 413 caps->header_compression.back_ch = (data[0] >> 7) & 1; 414 caps->header_compression.media = (data[0] >> 6) & 1; 415 caps->header_compression.recovery = (data[0] >> 5) & 1; |
410 break; 411 case AVDTP_MULTIPLEXING: | 416 break; 417 case AVDTP_MULTIPLEXING: |
412 caps->multiplexing_mode.fragmentation = packet[pos++] >> 7; | 418 caps->multiplexing_mode.fragmentation = (data[pos++] >> 7) & 1; |
413 // read [tsid, tcid] for media, reporting. recovery respectively 414 caps->multiplexing_mode.transport_identifiers_num = 3; 415 for (i=0; i<caps->multiplexing_mode.transport_identifiers_num; i++){ | 419 // read [tsid, tcid] for media, reporting. recovery respectively 420 caps->multiplexing_mode.transport_identifiers_num = 3; 421 for (i=0; i<caps->multiplexing_mode.transport_identifiers_num; i++){ |
416 caps->multiplexing_mode.transport_session_identifiers[i] = packet[pos++] >> 7; 417 caps->multiplexing_mode.tcid[i] = packet[pos++] >> 7; | 422 caps->multiplexing_mode.transport_session_identifiers[i] = (data[pos++] >> 7) & 1; 423 caps->multiplexing_mode.tcid[i] = (data[pos++] >> 7) & 1; |
418 } 419 break; 420 case AVDTP_MEDIA_CODEC: | 424 } 425 break; 426 case AVDTP_MEDIA_CODEC: |
421 caps->media_codec.media_type = (avdtp_media_type_t)(packet[pos++] >> 4); 422 caps->media_codec.media_codec_type = (avdtp_media_codec_type_t)(packet[pos++]); | 427 caps->media_codec.media_type = (avdtp_media_type_t)(data[pos++] >> 4); 428 caps->media_codec.media_codec_type = (avdtp_media_codec_type_t)(data[pos++]); |
423 caps->media_codec.media_codec_information_len = cap_len - 2; | 429 caps->media_codec.media_codec_information_len = cap_len - 2; |
424 caps->media_codec.media_codec_information = &packet[pos]; 425 pos += caps->media_codec.media_codec_information_len; | 430 caps->media_codec.media_codec_information = &data[pos++]; |
426 break; 427 case AVDTP_MEDIA_TRANSPORT: 428 case AVDTP_REPORTING: | 431 break; 432 case AVDTP_MEDIA_TRANSPORT: 433 case AVDTP_REPORTING: |
429 case AVDTP_DELAY_REPORTING: 430 pos += cap_len; | 434 case AVDTP_DELAY_REPORTING: |
431 break; 432 default: | 435 break; 436 default: |
433 pos += cap_len; 434 rfa = 1; | 437 category_valid = 0; |
435 break; 436 } | 438 break; 439 } |
437 processed_cap_len = pos - processed_cap_len; 438 // printf("processed category %d, cap_len %d, processed_cap_len %d, rfa %d\n", category, cap_len, processed_cap_len, rfa); | |
439 | 440 |
440 if (cap_len == processed_cap_len){ 441 // printf("pos %d, size %d \n", rfa, size - 2); | 441 if (category_valid) { 442 registered_service_categories = store_bit16(registered_service_categories, category, 1); 443 } |
442 | 444 |
443 if (!rfa) { 444 registered_service_categories = store_bit16(registered_service_categories, category, 1); 445 } 446 if (pos < size-2){ 447 //int old_pos = pos; 448 category = (avdtp_service_category_t)packet[pos++]; 449 cap_len = packet[pos++]; 450 if (avdtp_unpack_service_capabilities_has_errors(connection, category, cap_len)){ 451 log_error("avdtp_unpack_service_capabilities_has_errors"); 452 return 0; 453 } 454 } 455 } | 445 packet += cap_len; 446 to_process -= cap_len; |
456 } | 447 } |
448 |
|
457 return registered_service_categories; 458} 459 460void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uint8_t transaction_label, uint16_t registered_service_categories, avdtp_capabilities_t capabilities, uint8_t identifier){ 461 if (signaling_packet->offset) return; 462 uint8_t pack_all_capabilities = 1; 463 signaling_packet->message_type = AVDTP_RESPONSE_ACCEPT_MSG; 464 int i; --- 174 unchanged lines hidden (view full) --- 639 event[pos++] = HCI_EVENT_AVDTP_META; 640 event[pos++] = sizeof(event) - 2; 641 event[pos++] = AVDTP_SUBEVENT_SIGNALING_SEP_DICOVERY_DONE; 642 little_endian_store_16(event, pos, avdtp_cid); 643 pos += 2; 644 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 645} 646 | 449 return registered_service_categories; 450} 451 452void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uint8_t transaction_label, uint16_t registered_service_categories, avdtp_capabilities_t capabilities, uint8_t identifier){ 453 if (signaling_packet->offset) return; 454 uint8_t pack_all_capabilities = 1; 455 signaling_packet->message_type = AVDTP_RESPONSE_ACCEPT_MSG; 456 int i; --- 174 unchanged lines hidden (view full) --- 631 event[pos++] = HCI_EVENT_AVDTP_META; 632 event[pos++] = sizeof(event) - 2; 633 event[pos++] = AVDTP_SUBEVENT_SIGNALING_SEP_DICOVERY_DONE; 634 little_endian_store_16(event, pos, avdtp_cid); 635 pos += 2; 636 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 637} 638 |
647 | |
648void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, avdtp_signal_identifier_t identifier){ 649 if (!callback) return; 650 uint8_t event[7]; 651 int pos = 0; 652 event[pos++] = HCI_EVENT_AVDTP_META; 653 event[pos++] = sizeof(event) - 2; 654 event[pos++] = AVDTP_SUBEVENT_SIGNALING_ACCEPT; 655 little_endian_store_16(event, pos, avdtp_cid); --- 424 unchanged lines hidden --- | 639void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, avdtp_signal_identifier_t identifier){ 640 if (!callback) return; 641 uint8_t event[7]; 642 int pos = 0; 643 event[pos++] = HCI_EVENT_AVDTP_META; 644 event[pos++] = sizeof(event) - 2; 645 event[pos++] = AVDTP_SUBEVENT_SIGNALING_ACCEPT; 646 little_endian_store_16(event, pos, avdtp_cid); --- 424 unchanged lines hidden --- |