These two days saw the content of the A2DP and HFP agreements in CSR, mainly to see how to use the two protocols on CSR8670.
I. A2DP AGREEMENT
A2DP (Advanced Audio Distribution Profile) protocol, which is a high-level Bluetooth audio Transmission Model Protocol, is mainly used for Bluetooth audio transmission, the following is a simple record of how the A2DP protocol is used on CSR8670.
- Call Connectionwritescanenable (Hci_scan_enable_page) to allow the Bluetooth device to scan and page;
- Call A2dpinit () to initialize the A2DP library;
- Write the Handlea2dpmessage () function to process the A2DP message.
Note 1: Where the Audioconnect () function is called Kalimba DSP processing function, so the project directory has a corresponding Kalimba program, and should be in the main program's. mak file to add the program's compilation options. Like what:
########################################################################################################### A2DP DECODER versions############################################################################################### ######## copy in SBC decoder Image/sbc_decoder/sbc_decoder.kap: $ (mkdir) image/sbc_decoder$ (CopyFile). \.. \kalimba\apps\a2dp_sink\image\sbc_decoder\sbc_decoder.kap [Email protected]image.fs:image/sbc_decoder/sbc_ decoder.kap# copy in A2dp_low_latency_1mic Decoderimage/a2dp_low_latency_1mic/a2dp_low_latency_1mic.kap: $ (mkdir) image/a2dp_low_latency_1mic$ (CopyFile): \.. \kalimba\apps\a2dp_low_latency_1mic\image\a2dp_low_latency_1mic\a2dp_low_latency_1mic.kap [email protected] Image.fs:image/a2dp_low_latency_1mic/a2dp_low_latency_1mic.kap
Note 2:audioconnect () to invoke Audiolibraryinit () before using to initialize the audio library.
Partial processing code:
static void Handlea2dpmessage (Task task, MessageId ID, message message) {Sink Sink; audio_plugin_set_volume_a2dp_msg_t Volumeinitaudio; A2dp_codec_settings * codec_settings; audio_mode_t MODE = audio_mode_connected; A2dppluginconnectparams A2dp_audio_connect_params; Audiopluginfeatures Pluginfeatures; Main_debug ("A2dpmessage Received: [%x]\n", id)); Switch (ID) {case a2dp_init_cfm:main_debug ("a2dp_init_cfm: \ n")); if ((a2dp_init_cfm_t*) message)->status = = a2dp_success) {main_debug ("A2DP INIT success: \ n ")); } break; Case A2dp_signalling_connect_ind:main_debug (("A2dp_signalling_connect_ind: \ n")); A2dpsignallingconnectresponse (((a2dp_signalling_connect_ind_t *) message)->device_id,true); Break Case A2dp_signalling_connect_cfm:main_debug (("a2dp_signalling_connect_cfm: \ n")); A2dPmediaopenrequest ((a2dp_signalling_connect_cfm_t*) message)->device_id, 0,null); Break Case A2dp_media_open_ind:main_debug (("A2dp_media_open_ind: \ n")); A2dpmediaopenresponse (((a2dp_media_open_cfm_t*) message)->device_id, TRUE); Break Case A2dp_media_open_cfm:main_debug (("a2dp_media_open_cfm: \ n")); if ((a2dp_media_open_cfm_t*) message)->status = = a2dp_success) {main_debug ("A2dp_media_o pen_cfm suceess: \ n ")); } else {main_debug ("a2dp_media_open_cfm FAIL: \ n")); } break; Case A2dp_media_start_ind:main_debug (("A2dp_media_start_ind: \ n")); A2dpmediastartresponse ((a2dp_media_start_ind_t*) message)->device_id, ((a2dp_media_start_ind_t*) message)- >stream_id, TRUE); Break Case A2dp_media_start_cfm:main_debug ("A2Dp_media_start_cfm: \ n ")); if ((a2dp_media_start_cfm_t*) message)->status = = a2dp_success) {main_debug ("a2dp_media_s tart_cfm sucess: \ n ")); Sink = A2dpmediagetsink (((a2dp_media_start_cfm_t*) message)->device_id, ((a2dp_media_start_cfm_t*) message), STREAM_ID); if (sink) {codec_settings = A2dpcodecgetsettings (((a2dp_media_start_cfm_t*) message)-& GT;DEVICE_ID, ((a2dp_media_start_cfm_t*) message)->stream_id); if (codec_settings) {a2dp_audio_connect_params.packet_size = CODEC_SETTINGS-&G T;codecdata.packet_size; /* Packet size retrieved from A2DP library */a2dp_audio_connect_params.content_protection = code c_settings->codecdata.content_protection; /* Content protection retrieved from A2DP library */A2dp_audio_connect_params.clock_mismatch =0xff59; /*clock mismatch rate for this device */A2dp_audio_connect_params.currenteq =0x0000; A2dp_audio_connect_params.enhancements =0x0000; A2dp_audio_connect_params.silence_threshold =0x0000; A2dp_audio_connect_params.silence_trigger_time =0x0000; A2dp_audio_connect_params.speaker_pio =0x0000; theSink.a2dp_audio_mode_params.music_mode_processing = A2dp_music_processing_full_set_eq_bank0; TheSink.a2dp_audio_mode_params.external_mic_settings = external_mic_not_fitted; TheSink.a2dp_audio_mode_params.mic_mute = Send_path_unmute; theSink.a2dp_audio_mode_params.external_volume_enabled = 0; TheSink.a2dp_audio_mode_params.master_routing_mode = 1; TheSink.a2dp_audio_mode_params.slave_routing_mode = 2; theSink.a2dp_audio_mode_params.unused = 0; TheSink.a2dp_audio_mode_params.music_mode_enhancements = 0x0040; /* We need to set A2DP volume info as the audio was in mute state after connection */Volumeinitaudio.volume_type = Digital_only; Volumeinitaudio.codec_task = Thesink.codectask; Volumeinitaudio.system_gain = 15; Volumeinitaudio.trim_gain_left = 0; volumeinitaudio.trim_gain_right= 0; Volumeinitaudio.mute_active = FALSE; Pluginfeatures.audio_output_type = Output_interface_type_none; /* Connect the audio via the audio plugin */Audioconnect ((Taskdata *) &csr_sbc_decoder_plugin, Sink, Audio_sink_av, Thesink.codectask, Volumeinitaudio.tones_gain, Codec_settings->rate, Pluginfeatures, Mode, Audio_route_internal, ( audio_power_t) Power_batt_level3, &a2dp_audio_connect_params, &thesink.task); AUDIOSETVOLUMEA2DP (&volumeinitaudio); Audiosetmode (mode, &thesink.a2dp_audio_mode_params); }}} break; Default:main_debug ("unrecognised A2DP Message: [%x]\n", id)); Break }}
Note: The parameters are temporary and should be configured on the Pskey of the CSR when it is actually developed.
Two. HFP Agreement
HFP (Hands-free Profile) protocol, mainly used to deal with the Bluetooth voice connection protocol, usually used to achieve the answer, hang up, reject, voice dialing and other functions. Its implementation method is similar to the A2DP protocol, directly.
Partial processing code:
static void Handlehfpmessage (Task task, MessageId ID, message message) {Audiopluginfeatures features; Sep_data_type Seps[1]; Typed_bdaddr ag_addr; Sink Sink; Sync_pkt_type packet_types; Hfp_audio_params Audio_params; bool Disable_wbs_override = FALSE; Pio_config_type* Pio; UInt16 Ps_ret_len = 0; Main_debug ("Hfpmessage Received: [%x]\n", id)); Switch (ID) {case hfp_init_cfm:main_debug ("hfp_init_cfm\n")); Seps[0].sep_config = Codeclist[0].config; Seps[0].in_use = FALSE; A2dpinit (&thesink.task, A2dp_init_role_sink, NULL, 1, SEPs, 60); Connectionwriteclassofdevice (Audio_major_serv_class | Av_major_device_class | Av_minor_headset); if ((hfp_init_cfm_t*) message)->status = = hfp_success) {Main_debug (("hfp_success\n")); } else Panic (); BreAk Case Hfp_slc_connect_ind:main_debug (("Hfp_slc_connect_ind [%x]\n", ((hfp_slc_connect_ind_t *) message)->ACC epted)); Break Case Hfp_slc_connect_cfm:main_debug (("hfp_slc_connect_cfm [%x]\n", ((hfp_slc_connect_cfm_t *) message)->sta TUS)); Break Case Hfp_ring_ind:main_debug (("hfp_ring_ind\n")); Features.audio_output_type = Output_interface_type_none; Audioplaytone (Good_tone, TRUE, Thesink.codectask, 0x15, features); Break Case Hfp_slc_link_loss_ind:main_debug (("hfp_slc_link_loss_ind\n")); if ((hfp_slc_link_loss_ind_t*) message)->status = = hfp_link_loss_recovery) {main_debug ("HF p_link_loss_recovery \ n ")); } else if ((hfp_slc_link_loss_ind_t*) message)->status = = Hfp_link_loss_none) { Main_debug (("Hfp_link_loss_none \ n")); } Hfplinkgetslcsink (((hfp_slc_link_loss_ind_t*) message)->priority, &sink); SINKGETBDADDR (sink, &ag_addr); A2dpsignallingconnectrequest ((BDADDR *) &ag_addr.addr); Break Case Hfp_service_ind:main_debug (("Hfp_service_ind [%x]\n", ((hfp_service_ind_t*) message)->service)); Break Case Hfp_signal_ind:main_debug (("Hs:hfp_signal_ind [%d]\n", ((hfp_signal_ind_t*) message)->signal)); break; Case Hfp_roam_ind:main_debug (("Hs:hfp_roam_ind [%d]\n", ((hfp_roam_ind_t*) message)->roam)); Break Case Hfp_battchg_ind:main_debug (("Hs:hfp_battchg_ind [%d]\n", ((hfp_battchg_ind_t*) message)->battchg )) ; Break Case Hfp_audio_connect_ind:main_debug (("hfp_audio_connect_ind\n")); Packet_types = Sync_all_sco; Disable_wbs_override = TRUE; Audio_params.bandwidth = 0x1f40; Audio_params.max_latency = 0xc; audio_params.voice_settings = 0; Audio_params.retx_effort = sync_retx_link_quality; Hfpaudioconnectresponse ((hfp_audio_connect_ind_t *) message)->priority, TRUE, Packet_types, &audio_params, TRUE); break; Case Hfp_audio_connect_cfm:main_debug (("hfp_audio_connect_cfm\n")); if ((hfp_audio_connect_cfm_t *) message)->status = = hfp_success) {Hfplinkgetslcsink (((hfp_a udio_connect_ind_t*) message)->priority, &sink); Features.audio_output_type = Output_interface_type_none; Pio = malloc (sizeof (Pio_config_type)); memset (PIO, 0, sizeof (pio_config_type)); Ps_ret_len = Psretrieve (+ Pio, sizeof (Pio_config_type)); Main_debug (("PS return len:[%x]", Ps_ret_len)); Thesink.digital = malloc (sizeof (common_mic_params)); (thesink.digital)->mic_a.digital = 0; (thesink.digital)->mic_a.pre_amp = 1; (thesink.digital)->mic_a.drive_pio = 1; (thesink.digital)->mic_a.pio = 0; (thesink.digital)->mic_a.bias = 1; (thesink.digital)->mic_a.unused = 0; (thesink.digital)->mic_a.gain = 5; (thesink.digital)->mic_b.digital = 0; (thesink.digital)->mic_b.pre_amp = 1; (thesink.digital)->mic_b.drive_pio = 1; (thesink.digital)->mic_b.pio = 1; (thesink.digital)->mic_b.bias = 1; (thesink.digital)->mic_b.unused = 0; (thesink.digital)->mic_b.gain = 5; (thesink.digital)->line_a.digital = 0; (thesink.digital)->line_a.pre_amp = 0; (Thesink.digital)->line_a.drive_pio = 0; (thesink.digital)->line_a.pio = 0; (thesink.digital)->line_a.bias = 0; (thesink.digital)->line_a.unused = 0; (thesink.digital)->line_a.gain = 15; (thesink.digital)->line_b.digital = 0; (thesink.digital)->line_b.pre_amp = 0; (thesink.digital)->line_b.drive_pio = 0; (thesink.digital)->line_b.pio = 0; (thesink.digital)->line_b.bias = 0; (thesink.digital)->line_b.unused = 0; (thesink.digital)->line_b.gain = 15; TheSink.plugin_params.digital = Thesink.digital; TheSink.dsp_data.key.key = 0x0063; TheSink.dsp_data.key.len = 48; TheSink.dsp_data.key.cur_len = 0; TheSink.dsp_data.key.cache = TheSink.dsp_data.cache; Pblockinit (&thesink.dsp_data.key); /* Connect audio using the audio plugin selected above */AUDIOC Onnect (cvchs1micwbs,/*cvchs1mic*/sink, Sync_link_esco,/*syn c_link_esco*/Thesink.codectask, 20, 0x00001f40, features, audio_mode_connected, Audio_route_internal, (audio_power_t) Power_batt_level3, &thesink.plugin_params, NULL); } audiosetvolume (Thesink.codectask); theSink.a2dp_audio_mode_params.music_mode_processing = A2dp_music_processing_full_set_eq_bank0; TheSink.a2dp_audio_mode_params.external_mic_settings = 1; TheSink.a2dp_audio_mode_params.mic_muTe = 1; theSink.a2dp_audio_mode_params.external_volume_enabled = 0; TheSink.a2dp_audio_mode_params.master_routing_mode = 1; TheSink.a2dp_audio_mode_params.slave_routing_mode = 2; theSink.a2dp_audio_mode_params.unused = 0; theSink.a2dp_audio_mode_params.music_mode_enhancements = 0; /* Mute Control */Audiosetmode (audio_mode_connected, &thesink.a2dp_audio_mode_params); Break Default:main_debug ("unrecognised HFP Message: [%x]\n", id)); Break }}
Note: The parameters are temporary and should be configured on the Pskey of the CSR when it is actually developed.
Use of A2DP and HFP