a2dp sink: forward stream establish, start, pause, release

This commit is contained in:
Milanka Ringwald 2017-07-07 16:42:37 +02:00
parent 0ea2847f67
commit f1042e9d0d
5 changed files with 455 additions and 226 deletions

View File

@ -176,21 +176,14 @@ static const char * device_addr_string = "54:E4:3A:26:A2:39";
// bt dongle: -u 02-02 static bd_addr_t remote = {0x00, 0x02, 0x72, 0xDC, 0x31, 0xC1};
static uint16_t avdtp_cid = 0;
static uint16_t a2dp_cid = 0;
static uint8_t sdp_avdtp_sink_service_buffer[150];
static avdtp_sep_t sep;
static adtvp_media_codec_information_sbc_t sbc_capability;
static avdtp_media_codec_configuration_sbc_t sbc_configuration;
static avdtp_stream_endpoint_t * local_stream_endpoint;
static uint8_t local_seid = 0;
#ifdef HAVE_BTSTACK_STDIN
static uint16_t remote_configuration_bitmap;
static avdtp_capabilities_t remote_configuration;
#endif
typedef enum {
AVDTP_APPLICATION_IDLE,
AVDTP_APPLICATION_CONNECTED,
@ -559,18 +552,8 @@ static void handle_l2cap_media_data_packet(avdtp_stream_endpoint_t * stream_endp
#endif
}
static void dump_sbc_capability(adtvp_media_codec_information_sbc_t media_codec_sbc){
printf("Received media codec capability:\n");
printf(" - sampling_frequency: 0x%02x\n", media_codec_sbc.sampling_frequency_bitmap);
printf(" - channel_mode: 0x%02x\n", media_codec_sbc.channel_mode_bitmap);
printf(" - block_length: 0x%02x\n", media_codec_sbc.block_length_bitmap);
printf(" - subbands: 0x%02x\n", media_codec_sbc.subbands_bitmap);
printf(" - allocation_method: 0x%02x\n", media_codec_sbc.allocation_method_bitmap);
printf(" - bitpool_value [%d, %d] \n", media_codec_sbc.min_bitpool_value, media_codec_sbc.max_bitpool_value);
}
static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t configuration){
printf("Received media codec configuration:\n");
printf(" -- a2dp sink demo: Received media codec configuration:\n");
printf(" - num_channels: %d\n", configuration.num_channels);
printf(" - sampling_frequency: %d\n", configuration.sampling_frequency);
printf(" - channel_mode: %d\n", configuration.channel_mode);
@ -578,6 +561,7 @@ static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t configu
printf(" - subbands: %d\n", configuration.subbands);
printf(" - allocation_method: %d\n", configuration.allocation_method);
printf(" - bitpool_value [%d, %d] \n", configuration.min_bitpool_value, configuration.max_bitpool_value);
printf("\n");
}
static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
@ -709,69 +693,31 @@ static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t
}
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel);
UNUSED(size);
uint8_t status;
bd_addr_t event_addr;
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(packet)) {
case HCI_EVENT_PIN_CODE_REQUEST:
// inform about pin code request
printf("Pin code request - using '0000'\n");
hci_event_pin_code_request_get_bd_addr(packet, event_addr);
hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
// connection closed -> quit test app
app_state = AVDTP_APPLICATION_IDLE;
printf("\n --- avdtp_test: HCI_EVENT_DISCONNECTION_COMPLETE ---\n");
media_processing_close();
break;
case HCI_EVENT_AVDTP_META:
case HCI_EVENT_A2DP_META:
switch (packet[2]){
case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
app_state = AVDTP_APPLICATION_CONNECTED;
avdtp_cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet);
printf("\n --- avdtp_test: AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, cid 0x%02x ---\n", avdtp_cid);
case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION:
printf(" received non SBC codec. not implemented\n");
break;
case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND:
if (app_state < AVDTP_APPLICATION_CONNECTED) return;
sep.seid = avdtp_subevent_signaling_sep_found_get_seid(packet);
sep.in_use = avdtp_subevent_signaling_sep_found_get_in_use(packet);
sep.media_type = avdtp_subevent_signaling_sep_found_get_media_type(packet);
sep.type = avdtp_subevent_signaling_sep_found_get_sep_type(packet);
printf("Found sep: seid %u, in_use %d, media type %d, sep type %d (1-SNK)\n", sep.seid, sep.in_use, sep.media_type, sep.type);
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY:
if (app_state < AVDTP_APPLICATION_CONNECTED) return;
sbc_capability.sampling_frequency_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet);
sbc_capability.channel_mode_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet);
sbc_capability.block_length_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet);
sbc_capability.subbands_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(packet);
sbc_capability.allocation_method_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(packet);
sbc_capability.min_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet);
sbc_capability.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet);
dump_sbc_capability(sbc_capability);
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
if (app_state < AVDTP_APPLICATION_CONNECTED) return;
sbc_configuration.reconfigure = avdtp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet);
sbc_configuration.num_channels = avdtp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet);
sbc_configuration.sampling_frequency = avdtp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
sbc_configuration.channel_mode = avdtp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet);
sbc_configuration.block_length = avdtp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet);
sbc_configuration.subbands = avdtp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet);
sbc_configuration.allocation_method = avdtp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet);
sbc_configuration.min_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet);
sbc_configuration.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet);
sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet);
sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet);
sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet);
sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet);
sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet);
sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet);
sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length;
dump_sbc_configuration(sbc_configuration);
// // TODO: use actual config
// btstack_sbc_encoder_init(&local_stream_endpoint->sbc_encoder_state, SBC_MODE_STANDARD, 16, 8, 2, 44100, 53);
if (sbc_configuration.reconfigure){
media_processing_close();
@ -781,14 +727,55 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
}
break;
}
case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED:
case A2DP_SUBEVENT_STREAM_ESTABLISHED:
status = a2dp_subevent_stream_established_get_status(packet);
if (status != 0){
printf(" -- a2dp sink demo: streaming connection cannot be established, status 0x%02X\n", status);
app_state = AVDTP_APPLICATION_IDLE;
break;
}
// TODO: check it it the correct a2dp cid
a2dp_cid = a2dp_subevent_stream_established_get_a2dp_cid(packet);
printf(" -- a2dp sink demo: streaming connection is established, a2dp cid 0x%02X\n", status);
app_state = AVDTP_APPLICATION_STREAMING;
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY:
printf(" received non SBC codec. not implemented\n");
case A2DP_SUBEVENT_STREAM_STARTED:
status = a2dp_subevent_stream_started_get_status(packet);
if (status != 0){
printf(" -- a2dp sink demo: stream cannot be started, status 0x%02X\n", status);
app_state = AVDTP_APPLICATION_IDLE;
break;
}
// TODO: check it it the correct a2dp cid
a2dp_cid = a2dp_subevent_stream_started_get_a2dp_cid(packet);
printf(" -- a2dp sink demo: streaming, a2dp cid 0x%02X\n", status);
break;
case AVDTP_SUBEVENT_SIGNALING_ACCEPT:
case A2DP_SUBEVENT_STREAM_SUSPENDED:
status = a2dp_subevent_stream_suspended_get_status(packet);
if (status != 0){
printf(" -- a2dp sink demo: stream cannot be paused, status 0x%02X\n", status);
break;
}
// TODO: check it it the correct a2dp cid
a2dp_cid = a2dp_subevent_stream_started_get_a2dp_cid(packet);
printf(" -- a2dp sink demo: stream paused, a2dp cid 0x%02X\n", status);
break;
case A2DP_SUBEVENT_STREAM_RELEASED:
status = a2dp_subevent_stream_released_get_status(packet);
if (status != 0){
printf(" -- a2dp sink demo: stream cannot be released, status 0x%02X\n", status);
break;
}
// TODO: check it it the correct a2dp cid
a2dp_cid = a2dp_subevent_stream_released_get_a2dp_cid(packet);
app_state = AVDTP_APPLICATION_IDLE;
printf(" -- a2dp sink demo: stream released, a2dp cid 0x%02X\n", status);
media_processing_close();
break;
default:
printf(" not implemented\n");
break;
@ -814,19 +801,6 @@ static void show_usage(void){
printf("c - AVRCP create connection to addr %s\n", device_addr_string);
printf("C - AVRCP disconnect\n");
printf("\n--- Bluetooth AVDTP SINK Commands %s ---\n", bd_addr_to_str(iut_address));
printf("d - discover stream endpoints\n");
printf("g - get capabilities\n");
printf("a - get all capabilities\n");
printf("s - set configuration\n");
printf("f - get configuration\n");
printf("R - reconfigure stream with %d\n", sep.seid);
printf("o - open stream with seid %d\n", sep.seid);
printf("m - start stream with %d\n", sep.seid);
printf("A - abort stream with %d\n", sep.seid);
printf("S - stop stream with %d\n", sep.seid);
printf("P - suspend stream with %d\n", sep.seid);
printf("\n--- Bluetooth AVRCP Commands %s ---\n", bd_addr_to_str(iut_address));
printf("O - get play status\n");
printf("j - get now playing info\n");
@ -869,22 +843,16 @@ static uint8_t media_sbc_codec_configuration[] = {
2, 53
};
static uint8_t media_sbc_codec_reconfiguration[] = {
(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_SNR,
2, 53
};
static void stdin_process(char cmd){
sep.seid = 1;
switch (cmd){
case 'b':
printf("Creating L2CAP Connection to %s, BLUETOOTH_PROTOCOL_AVDTP\n", device_addr_string);
avdtp_sink_connect(device_addr);
printf("Creating L2CAP Connection to %s, PSM_AVDTP\n", bd_addr_to_str(device_addr));
a2dp_sink_establish_stream(device_addr, local_seid);
break;
case 'B':
printf("Disconnect\n");
avdtp_sink_disconnect(avdtp_cid);
avdtp_sink_disconnect(a2dp_cid);
break;
case 'c':
printf(" - Create AVRCP connection to addr %s.\n", bd_addr_to_str(device_addr));
@ -896,50 +864,6 @@ static void stdin_process(char cmd){
avrcp_disconnect(avrcp_cid);
break;
case 'd':
avdtp_sink_discover_stream_endpoints(avdtp_cid);
break;
case 'g':
avdtp_sink_get_capabilities(avdtp_cid, sep.seid);
break;
case 'a':
avdtp_sink_get_all_capabilities(avdtp_cid, sep.seid);
break;
case 'f':
avdtp_sink_get_configuration(avdtp_cid, sep.seid);
break;
case 's':
remote_configuration_bitmap = store_bit16(remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
remote_configuration.media_codec.media_type = AVDTP_AUDIO;
remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
remote_configuration.media_codec.media_codec_information_len = sizeof(media_sbc_codec_configuration);
remote_configuration.media_codec.media_codec_information = media_sbc_codec_configuration;
avdtp_sink_set_configuration(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid, remote_configuration_bitmap, remote_configuration);
break;
case 'R':
remote_configuration_bitmap = store_bit16(remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
remote_configuration.media_codec.media_type = AVDTP_AUDIO;
remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
remote_configuration.media_codec.media_codec_information_len = sizeof(media_sbc_codec_reconfiguration);
remote_configuration.media_codec.media_codec_information = media_sbc_codec_reconfiguration;
avdtp_sink_reconfigure(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid, remote_configuration_bitmap, remote_configuration);
break;
case 'o':
avdtp_sink_open_stream(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid);
break;
case 'm':
avdtp_sink_start_stream(local_stream_endpoint->sep.seid);
break;
case 'A':
avdtp_sink_abort_stream(local_stream_endpoint->sep.seid);
break;
case 'S':
avdtp_sink_stop_stream(local_stream_endpoint->sep.seid);
break;
case 'P':
avdtp_sink_suspend(local_stream_endpoint->sep.seid);
break;
case '\n':
case '\r':
break;

View File

@ -1262,12 +1262,11 @@ typedef uint8_t sm_key_t[16];
/** AVDTP Subevent */
/**
* @format 12111
* @format 1211
* @param subevent_code
* @param avdtp_cid
* @param int_seid
* @param local_seid
* @param signal_identifier
* @param status 0 == OK
*/
#define AVDTP_SUBEVENT_SIGNALING_ACCEPT 0x01
@ -1421,11 +1420,44 @@ typedef uint8_t sm_key_t[16];
/**
* @format 121 Sent only by A2DP source.
* @param subevent_code
* @param avdtp_cid
* @param a2dp_cid
* @param local_seid
*/
#define A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW 0x01
/**
* @format 12111121111111
* @param subevent_code
* @param a2dp_cid
* @param int_seid
* @param acp_seid
* @param reconfigure
* @param media_type
* @param sampling_frequency
* @param channel_mode
* @param num_channels
* @param block_length
* @param subbands
* @param allocation_method
* @param min_bitpool_value
* @param max_bitpool_value
*/
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION 0x02
/**
* @format 1211112LV
* @param subevent_code
* @param a2dp_cid
* @param int_seid
* @param acp_seid
* @param reconfigure
* @param media_type
* @param media_codec_type
* @param media_codec_information_len
* @param media_codec_information
*/
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION 0x03
/**
* @format 12111 Stream is opened byt not started.
* @param subevent_code
@ -1434,31 +1466,34 @@ typedef uint8_t sm_key_t[16];
* @param remote_seid
* @param status
*/
#define A2DP_SUBEVENT_STREAM_ESTABLISHED 0x02
#define A2DP_SUBEVENT_STREAM_ESTABLISHED 0x04
/**
* @format 121 Indicates that media transfer is started.
* @format 1211 Indicates that media transfer is started.
* @param subevent_code
* @param a2dp_cid
* @param local_seid
* @param status
*/
#define A2DP_SUBEVENT_STREAM_STARTED 0x03
#define A2DP_SUBEVENT_STREAM_STARTED 0x05
/**
* @format 121 Stream is paused.
* @format 1211 Stream is paused.
* @param subevent_code
* @param a2dp_cid
* @param local_seid
* @param status
*/
#define A2DP_SUBEVENT_STREAM_SUSPENDED 0x04
#define A2DP_SUBEVENT_STREAM_SUSPENDED 0x06
/**
* @format 121 Stream is released.
* @format 1211 Stream is released.
* @param subevent_code
* @param avdtp_cid
* @param a2dp_cid
* @param local_seid
* @param status
*/
#define A2DP_SUBEVENT_STREAM_RELEASED 0x05
#define A2DP_SUBEVENT_STREAM_RELEASED 0x07

View File

@ -3989,12 +3989,12 @@ static inline uint16_t avdtp_subevent_signaling_accept_get_avdtp_cid(const uint8
return little_endian_read_16(event, 3);
}
/**
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_ACCEPT
* @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_ACCEPT
* @param event packet
* @return int_seid
* @return local_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_accept_get_int_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_accept_get_local_seid(const uint8_t * event){
return event[5];
}
/**
@ -4006,15 +4006,6 @@ static inline uint8_t avdtp_subevent_signaling_accept_get_int_seid(const uint8_t
static inline uint8_t avdtp_subevent_signaling_accept_get_signal_identifier(const uint8_t * event){
return event[6];
}
/**
* @brief Get field status from event AVDTP_SUBEVENT_SIGNALING_ACCEPT
* @param event packet
* @return status
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_accept_get_status(const uint8_t * event){
return event[7];
}
/**
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_REJECT
@ -4587,12 +4578,12 @@ static inline uint16_t avdtp_subevent_streaming_can_send_media_packet_now_get_se
}
/**
* @brief Get field avdtp_cid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW
* @param event packet
* @return avdtp_cid
* @return a2dp_cid
* @note: btstack_type 2
*/
static inline uint16_t a2dp_subevent_streaming_can_send_media_packet_now_get_avdtp_cid(const uint8_t * event){
static inline uint16_t a2dp_subevent_streaming_can_send_media_packet_now_get_a2dp_cid(const uint8_t * event){
return little_endian_read_16(event, 3);
}
/**
@ -4605,6 +4596,197 @@ static inline uint8_t a2dp_subevent_streaming_can_send_media_packet_now_get_loca
return event[5];
}
/**
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return a2dp_cid
* @note: btstack_type 2
*/
static inline uint16_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_a2dp_cid(const uint8_t * event){
return little_endian_read_16(event, 3);
}
/**
* @brief Get field int_seid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return int_seid
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_int_seid(const uint8_t * event){
return event[5];
}
/**
* @brief Get field acp_seid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return acp_seid
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_acp_seid(const uint8_t * event){
return event[6];
}
/**
* @brief Get field reconfigure from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return reconfigure
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(const uint8_t * event){
return event[7];
}
/**
* @brief Get field media_type from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return media_type
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_media_type(const uint8_t * event){
return event[8];
}
/**
* @brief Get field sampling_frequency from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return sampling_frequency
* @note: btstack_type 2
*/
static inline uint16_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(const uint8_t * event){
return little_endian_read_16(event, 9);
}
/**
* @brief Get field channel_mode from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return channel_mode
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(const uint8_t * event){
return event[11];
}
/**
* @brief Get field num_channels from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return num_channels
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(const uint8_t * event){
return event[12];
}
/**
* @brief Get field block_length from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return block_length
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(const uint8_t * event){
return event[13];
}
/**
* @brief Get field subbands from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return subbands
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(const uint8_t * event){
return event[14];
}
/**
* @brief Get field allocation_method from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return allocation_method
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(const uint8_t * event){
return event[15];
}
/**
* @brief Get field min_bitpool_value from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return min_bitpool_value
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(const uint8_t * event){
return event[16];
}
/**
* @brief Get field max_bitpool_value from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return max_bitpool_value
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(const uint8_t * event){
return event[17];
}
/**
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @param event packet
* @return a2dp_cid
* @note: btstack_type 2
*/
static inline uint16_t a2dp_subevent_signaling_media_codec_other_configuration_get_a2dp_cid(const uint8_t * event){
return little_endian_read_16(event, 3);
}
/**
* @brief Get field int_seid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @param event packet
* @return int_seid
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_other_configuration_get_int_seid(const uint8_t * event){
return event[5];
}
/**
* @brief Get field acp_seid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @param event packet
* @return acp_seid
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_other_configuration_get_acp_seid(const uint8_t * event){
return event[6];
}
/**
* @brief Get field reconfigure from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @param event packet
* @return reconfigure
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_other_configuration_get_reconfigure(const uint8_t * event){
return event[7];
}
/**
* @brief Get field media_type from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @param event packet
* @return media_type
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_signaling_media_codec_other_configuration_get_media_type(const uint8_t * event){
return event[8];
}
/**
* @brief Get field media_codec_type from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @param event packet
* @return media_codec_type
* @note: btstack_type 2
*/
static inline uint16_t a2dp_subevent_signaling_media_codec_other_configuration_get_media_codec_type(const uint8_t * event){
return little_endian_read_16(event, 9);
}
/**
* @brief Get field media_codec_information_len from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @param event packet
* @return media_codec_information_len
* @note: btstack_type L
*/
static inline int a2dp_subevent_signaling_media_codec_other_configuration_get_media_codec_information_len(const uint8_t * event){
return little_endian_read_16(event, 11);
}
/**
* @brief Get field media_codec_information from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @param event packet
* @return media_codec_information
* @note: btstack_type V
*/
static inline const uint8_t * a2dp_subevent_signaling_media_codec_other_configuration_get_media_codec_information(const uint8_t * event){
return &event[13];
}
/**
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_ESTABLISHED
* @param event packet
@ -4660,6 +4842,15 @@ static inline uint16_t a2dp_subevent_stream_started_get_a2dp_cid(const uint8_t *
static inline uint8_t a2dp_subevent_stream_started_get_local_seid(const uint8_t * event){
return event[5];
}
/**
* @brief Get field status from event A2DP_SUBEVENT_STREAM_STARTED
* @param event packet
* @return status
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_stream_started_get_status(const uint8_t * event){
return event[6];
}
/**
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_SUSPENDED
@ -4679,14 +4870,23 @@ static inline uint16_t a2dp_subevent_stream_suspended_get_a2dp_cid(const uint8_t
static inline uint8_t a2dp_subevent_stream_suspended_get_local_seid(const uint8_t * event){
return event[5];
}
/**
* @brief Get field status from event A2DP_SUBEVENT_STREAM_SUSPENDED
* @param event packet
* @return status
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_stream_suspended_get_status(const uint8_t * event){
return event[6];
}
/**
* @brief Get field avdtp_cid from event A2DP_SUBEVENT_STREAM_RELEASED
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_RELEASED
* @param event packet
* @return avdtp_cid
* @return a2dp_cid
* @note: btstack_type 2
*/
static inline uint16_t a2dp_subevent_stream_released_get_avdtp_cid(const uint8_t * event){
static inline uint16_t a2dp_subevent_stream_released_get_a2dp_cid(const uint8_t * event){
return little_endian_read_16(event, 3);
}
/**
@ -4698,6 +4898,15 @@ static inline uint16_t a2dp_subevent_stream_released_get_avdtp_cid(const uint8_t
static inline uint8_t a2dp_subevent_stream_released_get_local_seid(const uint8_t * event){
return event[5];
}
/**
* @brief Get field status from event A2DP_SUBEVENT_STREAM_RELEASED
* @param event packet
* @return status
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_stream_released_get_status(const uint8_t * event){
return event[6];
}
/**
* @brief Get field status from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED

View File

@ -140,8 +140,8 @@ void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_han
}
void a2dp_sink_register_packet_handler(btstack_packet_handler_t callback){
avdtp_sink_register_packet_handler(callback);
return;
// avdtp_sink_register_packet_handler(callback);
// return;
if (callback == NULL){
log_error("a2dp_sink_register_packet_handler called with NULL callback");
return;
@ -189,15 +189,53 @@ void a2dp_sink_disconnect(uint16_t a2dp_cid){
avdtp_disconnect(a2dp_cid, &a2dp_sink_context);
}
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
static void a2dp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint8_t * event, uint16_t event_size){
if (!callback) return;
if (event_size < 8) return;
event[0] = HCI_EVENT_A2DP_META;
event[2] = A2DP_SUBEVENT_STREAM_ESTABLISHED;
(*callback)(HCI_EVENT_PACKET, 0, event, event_size);
}
static inline void a2dp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint8_t * event, uint16_t event_size){
if (!callback) return;
if (event_size < 18) return;
event[0] = HCI_EVENT_A2DP_META;
event[2] = A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION;
(*callback)(HCI_EVENT_PACKET, 0, event, event_size);
}
static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint8_t * event, uint16_t event_size){
if (!callback) return;
if (event_size < 112) return;
event[0] = HCI_EVENT_A2DP_META;
event[2] = A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION;
}
static inline void a2dp_emit_stream_event(btstack_packet_handler_t callback, uint16_t a2dp_cid, uint8_t eventID, uint8_t local_seid, uint8_t status){
uint8_t event[7];
int pos = 0;
event[pos++] = HCI_EVENT_A2DP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = eventID;
little_endian_store_16(event, pos, a2dp_cid);
pos += 2;
event[pos++] = local_seid;
event[pos++] = status;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel);
UNUSED(size);
bd_addr_t event_addr;
uint8_t status;
uint8_t signal_identifier;
uint16_t cid;
uint8_t local_seid;
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(packet)) {
case HCI_EVENT_PIN_CODE_REQUEST:
@ -209,68 +247,92 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
case HCI_EVENT_DISCONNECTION_COMPLETE:
// connection closed -> quit test app
app_state = A2DP_IDLE;
printf("\n --- avdtp_test: HCI_EVENT_DISCONNECTION_COMPLETE ---\n");
printf("\n --- a2dp sink: HCI_EVENT_DISCONNECTION_COMPLETE ---\n");
break;
case HCI_EVENT_AVDTP_META:
switch (packet[2]){
case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
status = avdtp_subevent_signaling_connection_established_get_status(packet);
if (status != 0){
log_info(" --- a2dp sink --- AVDTP_SUBEVENT_SIGNALING_CONNECTION could not be established, status %d ---", status);
break;
}
app_state = A2DP_CONNECTED;
avdtp_cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet);
printf("\n --- avdtp_test: AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, cid 0x%02x ---\n", avdtp_cid);
log_info(" --- a2dp sink --- AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, avdtp cid 0x%02x ---", avdtp_cid);
break;
case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND:
if (app_state < A2DP_CONNECTED) return;
// sep.seid = avdtp_subevent_signaling_sep_found_get_seid(packet);
// sep.in_use = avdtp_subevent_signaling_sep_found_get_in_use(packet);
// sep.media_type = avdtp_subevent_signaling_sep_found_get_media_type(packet);
// sep.type = avdtp_subevent_signaling_sep_found_get_sep_type(packet);
// printf("Found sep: seid %u, in_use %d, media type %d, sep type %d (1-SNK)\n", sep.seid, sep.in_use, sep.media_type, sep.type);
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY:
if (app_state < A2DP_CONNECTED) return;
// sbc_capability.sampling_frequency_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet);
// sbc_capability.channel_mode_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet);
// sbc_capability.block_length_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet);
// sbc_capability.subbands_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(packet);
// sbc_capability.allocation_method_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(packet);
// sbc_capability.min_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet);
// sbc_capability.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet);
// dump_sbc_capability(sbc_capability);
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
if (app_state < A2DP_CONNECTED) return;
// sbc_configuration.reconfigure = avdtp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet);
// sbc_configuration.num_channels = avdtp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet);
// sbc_configuration.sampling_frequency = avdtp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
// sbc_configuration.channel_mode = avdtp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet);
// sbc_configuration.block_length = avdtp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet);
// sbc_configuration.subbands = avdtp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet);
// sbc_configuration.allocation_method = avdtp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet);
// sbc_configuration.min_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet);
// sbc_configuration.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
// sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length;
// dump_sbc_configuration(sbc_configuration);
// // // TODO: use actual config
// btstack_sbc_encoder_init(&local_stream_endpoint->sbc_encoder_state, SBC_MODE_STANDARD, 16, 8, 2, 44100, 53);
// if (sbc_configuration.reconfigure){
// media_processing_close();
// media_processing_init(sbc_configuration);
// } else {
// media_processing_init(sbc_configuration);
// }
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION:
log_info(" --- a2dp sink --- received non SBC codec. not implemented");
avdtp_signaling_emit_media_codec_other(a2dp_sink_context.a2dp_callback, packet, size);
break;
}
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:
if (app_state < A2DP_CONNECTED) return;
a2dp_signaling_emit_media_codec_sbc(a2dp_sink_context.a2dp_callback, packet, size);
break;
case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED:
app_state = A2DP_STREAMING_OPENED;
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY:
printf(" received non SBC codec. not implemented\n");
status = avdtp_subevent_streaming_connection_established_get_status(packet);
if (status != 0){
app_state = A2DP_CONNECTED;
} else {
app_state = A2DP_STREAMING_OPENED;
}
a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, packet, size);
break;
case AVDTP_SUBEVENT_SIGNALING_ACCEPT:
if (!a2dp_sink_context.a2dp_callback) return;
status = 0;
signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet);
cid = avdtp_subevent_signaling_accept_get_avdtp_cid(packet);
local_seid = avdtp_subevent_signaling_accept_get_local_seid(packet);
printf(" --- a2dp sink --- Accepted %d, a2dp sink cid 0x%2x, local seid %d\n", signal_identifier, cid, local_seid);
switch (signal_identifier){
case AVDTP_SI_START:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_STARTED, local_seid, status);
break;
case AVDTP_SI_SUSPEND:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_SUSPENDED, local_seid, status);
break;
case AVDTP_SI_ABORT:
case AVDTP_SI_CLOSE:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_RELEASED, local_seid, status);
break;
default:
break;
}
break;
case AVDTP_SUBEVENT_SIGNALING_REJECT:
case AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT:
if (!a2dp_sink_context.a2dp_callback) return;
status = 1;
signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet);
cid = avdtp_subevent_signaling_accept_get_avdtp_cid(packet);
local_seid = avdtp_subevent_signaling_accept_get_local_seid(packet);
printf(" --- a2dp sink --- Rejected %d, a2dp sink cid 0x%2x, local seid %d\n", signal_identifier, cid, local_seid);
switch (signal_identifier){
case AVDTP_SI_START:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_STARTED, local_seid, status);
break;
case AVDTP_SI_SUSPEND:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_SUSPENDED, local_seid, status);
break;
case AVDTP_SI_ABORT:
case AVDTP_SI_CLOSE:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_RELEASED, local_seid, status);
break;
default:
break;
}
break;
default:
printf(" not implemented\n");
app_state = A2DP_IDLE;
log_info(" --- a2dp sink --- not implemented");
break;
}
break;

View File

@ -269,7 +269,6 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
case AVDTP_SUBEVENT_SIGNALING_ACCEPT:
signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet);
status = avdtp_subevent_signaling_accept_get_status(packet);
log_info(" --- a2dp source --- Accepted %d", signal_identifier);
switch (app_state){