a2dp_sink.c (4ccacc40ad94c9a42aed3472e2884735a918df09) | a2dp_sink.c (34b22aac0913b061ca6c0da686fd034f9e188df1) |
---|---|
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 --- 134 unchanged lines hidden (view full) --- 143 return sc.local_stream_endpoint->connection->avdtp_cid; 144} 145 146static inline uint8_t local_seid(void){ 147 if (!sc.local_stream_endpoint) return 0; 148 return sc.local_stream_endpoint->sep.seid; 149} 150 | 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 --- 134 unchanged lines hidden (view full) --- 143 return sc.local_stream_endpoint->connection->avdtp_cid; 144} 145 146static inline uint8_t local_seid(void){ 147 if (!sc.local_stream_endpoint) return 0; 148 return sc.local_stream_endpoint->sep.seid; 149} 150 |
151static inline uint8_t remote_seid(void){ 152 if (!sc.local_stream_endpoint) return 0; 153 if (!sc.local_stream_endpoint->connection) return 0; 154 return sc.local_stream_endpoint->connection->remote_seps[sc.local_stream_endpoint->remote_sep_index].seid; 155} 156 | |
157void a2dp_sink_register_packet_handler(btstack_packet_handler_t callback){ 158 // avdtp_sink_register_packet_handler(callback); 159 // return; 160 if (callback == NULL){ 161 log_error("a2dp_sink_register_packet_handler called with NULL callback"); 162 return; 163 } 164 avdtp_sink_register_packet_handler(&packet_handler); --- 64 unchanged lines hidden (view full) --- 229 230static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint8_t * event, uint16_t event_size){ 231 if (!callback) return; 232 if (event_size < 112) return; 233 event[0] = HCI_EVENT_A2DP_META; 234 event[2] = A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION; 235} 236 | 151void a2dp_sink_register_packet_handler(btstack_packet_handler_t callback){ 152 // avdtp_sink_register_packet_handler(callback); 153 // return; 154 if (callback == NULL){ 155 log_error("a2dp_sink_register_packet_handler called with NULL callback"); 156 return; 157 } 158 avdtp_sink_register_packet_handler(&packet_handler); --- 64 unchanged lines hidden (view full) --- 223 224static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint8_t * event, uint16_t event_size){ 225 if (!callback) return; 226 if (event_size < 112) return; 227 event[0] = HCI_EVENT_A2DP_META; 228 event[2] = A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION; 229} 230 |
237static 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){ 238 uint8_t event[7]; | 231static inline void a2dp_emit_stream_event(btstack_packet_handler_t callback, uint16_t a2dp_cid, uint8_t eventID, uint8_t local_seid){ 232 if (!callback) return; 233 uint8_t event[6]; |
239 int pos = 0; 240 event[pos++] = HCI_EVENT_A2DP_META; 241 event[pos++] = sizeof(event) - 2; 242 event[pos++] = eventID; 243 little_endian_store_16(event, pos, a2dp_cid); 244 pos += 2; 245 event[pos++] = local_seid; | 234 int pos = 0; 235 event[pos++] = HCI_EVENT_A2DP_META; 236 event[pos++] = sizeof(event) - 2; 237 event[pos++] = eventID; 238 little_endian_store_16(event, pos, a2dp_cid); 239 pos += 2; 240 event[pos++] = local_seid; |
246 event[pos++] = status; 247 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 248 | 241 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); |
249} 250 | 242} 243 |
244static inline void a2dp_emit_cmd_accepted(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size){ 245 if (!callback) return; 246 UNUSED(size); 247 packet[2] = A2DP_SUBEVENT_COMMAND_ACCEPTED; 248 (*callback)(HCI_EVENT_PACKET, 0, packet, size); 249} 250 251static inline void a2dp_emit_cmd_rejected(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size){ 252 if (!callback) return; 253 UNUSED(size); 254 packet[2] = A2DP_SUBEVENT_COMMAND_REJECTED; 255 (*callback)(HCI_EVENT_PACKET, 0, packet, size); 256} 257 |
|
251static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 252 UNUSED(channel); 253 UNUSED(size); | 258static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 259 UNUSED(channel); 260 UNUSED(size); |
254 bd_addr_t event_addr; | 261 bd_addr_t address; |
255 uint8_t status; 256 uint8_t signal_identifier; 257 uint16_t cid; 258 uint8_t loc_seid; | 262 uint8_t status; 263 uint8_t signal_identifier; 264 uint16_t cid; 265 uint8_t loc_seid; |
266 uint8_t rem_seid; |
|
259 | 267 |
260 switch (packet_type) { 261 case HCI_EVENT_PACKET: 262 switch (hci_event_packet_get_type(packet)) { 263 case HCI_EVENT_PIN_CODE_REQUEST: 264 // inform about pin code request 265 log_info("Pin code request - using '0000'\n"); 266 hci_event_pin_code_request_get_bd_addr(packet, event_addr); 267 hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000"); 268 break; 269 case HCI_EVENT_DISCONNECTION_COMPLETE: 270 // connection closed -> quit test app 271 app_state = A2DP_IDLE; 272 printf("\na2dp sink: HCI_EVENT_DISCONNECTION_COMPLETE ---\n"); 273 break; 274 case HCI_EVENT_AVDTP_META: 275 switch (packet[2]){ 276 case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: 277 cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet); 278 if (cid != a2dp_cid()){ 279 a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER); 280 break; 281 } 282 283 status = avdtp_subevent_signaling_connection_established_get_status(packet); 284 if (status != 0){ 285 log_info(" --- a2dp sink --- AVDTP_SUBEVENT_SIGNALING_CONNECTION could not be established, status %d ---", status); 286 a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), status); 287 break; 288 } 289 app_state = A2DP_CONNECTED; 290 log_info("a2dp sink: AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, avdtp cid 0x%02x ---", a2dp_cid()); 291 break; | 268 if (packet_type != HCI_EVENT_PACKET) return; 269 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVDTP_META) return; |
292 | 270 |
293 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION: 294 log_info("a2dp sink: received non SBC codec. not implemented"); 295 avdtp_signaling_emit_media_codec_other(a2dp_sink_context.a2dp_callback, packet, size); 296 break; 297 298 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION: 299 if (app_state < A2DP_CONNECTED) return; 300 a2dp_signaling_emit_media_codec_sbc(a2dp_sink_context.a2dp_callback, packet, size); 301 break; | 271 switch (packet[2]){ 272 case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: 273 avdtp_subevent_signaling_connection_established_get_bd_addr(packet, address); 274 if (memcmp(address, &sc.remote_addr, 6) != 0) break; |
302 | 275 |
303 case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED: 304 status = avdtp_subevent_streaming_connection_established_get_status(packet); 305 if (status != 0){ 306 app_state = A2DP_CONNECTED; 307 } else { 308 app_state = A2DP_STREAMING_OPENED; 309 } 310 a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), 0); 311 break; | 276 cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet); 277 status = avdtp_subevent_signaling_connection_established_get_status(packet); 278 if (status != 0){ 279 log_info("AVDTP_SUBEVENT_SIGNALING_CONNECTION failed status %d ---", status); 280 a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, 0, 0, status); 281 break; 282 } |
312 | 283 |
313 case AVDTP_SUBEVENT_SIGNALING_ACCEPT: 314 if (!a2dp_sink_context.a2dp_callback) return; 315 status = 0; 316 signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet); 317 cid = avdtp_subevent_signaling_accept_get_avdtp_cid(packet); 318 loc_seid = avdtp_subevent_signaling_accept_get_local_seid(packet); 319 320 switch (signal_identifier){ 321 case AVDTP_SI_START: 322 a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_STARTED, loc_seid, status); 323 break; 324 case AVDTP_SI_SUSPEND: 325 a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_SUSPENDED, loc_seid, status); 326 break; 327 case AVDTP_SI_ABORT: 328 case AVDTP_SI_CLOSE: 329 a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_RELEASED, loc_seid, status); 330 break; 331 default: 332 break; 333 } 334 break; 335 336 case AVDTP_SUBEVENT_SIGNALING_REJECT: 337 case AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT: 338 if (!a2dp_sink_context.a2dp_callback) return; 339 status = 1; 340 signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet); 341 cid = avdtp_subevent_signaling_accept_get_avdtp_cid(packet); 342 loc_seid = avdtp_subevent_signaling_accept_get_local_seid(packet); | 284 app_state = A2DP_CONNECTED; 285 log_info("AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, avdtp cid 0x%02x ---", cid); 286 break; |
343 | 287 |
344 switch (signal_identifier){ 345 case AVDTP_SI_START: 346 a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_STARTED, loc_seid, status); 347 break; 348 case AVDTP_SI_SUSPEND: 349 a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_SUSPENDED, loc_seid, status); 350 break; 351 case AVDTP_SI_ABORT: 352 case AVDTP_SI_CLOSE: 353 a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_RELEASED, loc_seid, status); 354 break; 355 default: 356 break; 357 } 358 break; 359 default: 360 app_state = A2DP_IDLE; 361 log_info("a2dp sink: not implemented"); 362 break; 363 } 364 break; | 288 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION: 289 log_info("received non SBC codec. not implemented"); 290 avdtp_signaling_emit_media_codec_other(a2dp_sink_context.a2dp_callback, packet, size); 291 break; 292 293 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION: 294 if (app_state < A2DP_CONNECTED) return; 295 a2dp_signaling_emit_media_codec_sbc(a2dp_sink_context.a2dp_callback, packet, size); 296 break; 297 298 case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED: 299 status = avdtp_subevent_streaming_connection_established_get_status(packet); 300 cid = avdtp_subevent_streaming_connection_established_get_avdtp_cid(packet); 301 loc_seid = avdtp_subevent_streaming_connection_established_get_local_seid(packet); 302 rem_seid = avdtp_subevent_streaming_connection_established_get_remote_seid(packet); 303 304 if (status != 0){ 305 a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, loc_seid, rem_seid, status); 306 break; 307 } 308 309 if (cid != a2dp_cid()){ 310 a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, loc_seid, rem_seid, ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER); 311 break; 312 } 313 314 if (loc_seid != local_seid()){ 315 a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, loc_seid, rem_seid, ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER); 316 break; 317 } 318 app_state = A2DP_STREAMING_OPENED; 319 a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, cid, loc_seid, rem_seid, 0); 320 break; 321 322 case AVDTP_SUBEVENT_SIGNALING_ACCEPT: 323 signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet); 324 cid = avdtp_subevent_signaling_accept_get_avdtp_cid(packet); 325 loc_seid = avdtp_subevent_signaling_accept_get_local_seid(packet); 326 327 switch (signal_identifier){ 328 case AVDTP_SI_START: 329 a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_STARTED, loc_seid); 330 break; 331 case AVDTP_SI_SUSPEND: 332 a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_SUSPENDED, loc_seid); 333 break; 334 case AVDTP_SI_ABORT: 335 case AVDTP_SI_CLOSE: 336 a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_RELEASED, loc_seid); 337 break; |
365 default: | 338 default: |
339 a2dp_emit_cmd_accepted(a2dp_sink_context.a2dp_callback, packet, size); |
|
366 break; 367 } 368 break; | 340 break; 341 } 342 break; |
369 default: 370 // other packet type | 343 344 case AVDTP_SUBEVENT_SIGNALING_REJECT: 345 case AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT: 346 signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet); 347 cid = avdtp_subevent_signaling_accept_get_avdtp_cid(packet); 348 loc_seid = avdtp_subevent_signaling_accept_get_local_seid(packet); 349 a2dp_emit_cmd_rejected(a2dp_sink_context.a2dp_callback, packet, size); |
371 break; | 350 break; |
351 case AVDTP_SUBEVENT_STREAMING_CONNECTION_RELEASED: 352 cid = avdtp_subevent_streaming_connection_released_get_avdtp_cid(packet); 353 loc_seid = avdtp_subevent_streaming_connection_released_get_local_seid(packet); 354 app_state = A2DP_IDLE; 355 a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_RELEASED, loc_seid); 356 break; 357 case AVDTP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 358 app_state = A2DP_IDLE; 359 break; 360 default: 361 app_state = A2DP_IDLE; 362 log_info("not implemented"); 363 break; |
|
372 } | 364 } |
365 |
|
373} 374 | 366} 367 |