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