4 * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
33 #include "tizen-audio-internal.h"
34 #include "tizen-audio-impl.h"
36 #define vbc_thread_new pthread_create
37 #define VBPIPE_DEVICE "/dev/spipe_w6"
38 #define VBPIPE_VOIP_DEVICE "/dev/spipe_w4"
39 #define VBC_CMD_TAG "VBC"
44 /* current mode and volume gain parameters.*/
46 VBC_CMD_RESP_MODE = 2,
49 VBC_CMD_RESP_GAIN = 4,
51 /* whether switch vb control to dsp parameters.*/
52 VBC_CMD_SWITCH_CTRL = 5,
53 VBC_CMD_RESP_SWITCH = 6,
55 /* whether mute or not.*/
57 VBC_CMD_RESP_MUTE = 8,
59 /* open/close device parameters.*/
60 VBC_CMD_DEVICE_CTRL = 9,
61 VBC_CMD_RESP_DEVICE = 10,
63 VBC_CMD_PCM_OPEN = 11,
64 VBC_CMD_RESP_OPEN =12,
66 VBC_CMD_PCM_CLOSE = 13,
67 VBC_CMD_RESP_CLOSE = 14,
69 VBC_CMD_SET_SAMPLERATE = 15,
70 VBC_CMD_RESP_SAMPLERATE = 16,
75 const static char* vbc_cmd_str_arry[VBC_CMD_MAX] = {"NONE", "SET_MODE", "RESP_MODE", "SET_GAIN", "RESP_GAIN", "SWITCH_CTL", "RESP_SWITCH",
76 "SET_MUTE", "RESP_MUTE", "DEVICE_CTL", "RESP_DEVICE", "PCM_OPEN", "RESP_OPEN", "PCM_CLOSE", "RESP_CLOSE", "SET_SAMPL", "RESP_SAMPL"};
79 unsigned int sim_card; /*sim card number*/
82 typedef struct _vbc_parameters_head {
84 unsigned int cmd_type;
85 unsigned int paras_size;
86 } vbc_parameters_head;
88 typedef struct vbc_control_params {
91 } vbc_control_params_t;
94 unsigned short is_open; /* if is_open is true, open device; else close device.*/
95 unsigned short is_headphone;
96 unsigned int is_downlink_mute;
97 unsigned int is_uplink_mute;
100 typedef struct samplerate_ctrl {
101 unsigned int samplerate; /* change samplerate.*/
105 unsigned int is_switch; /* switch vbc contrl to dsp.*/
108 static int __read_nonblock(int fd, void *buf, int bytes)
111 int bytes_to_read = bytes;
113 if ((fd > 0) && (buf != NULL)) {
115 ret = read(fd, buf, bytes);
120 } else if ((!((errno == EAGAIN) || (errno == EINTR))) || (0 == ret)) {
126 if (bytes == bytes_to_read)
129 return (bytes_to_read - bytes);
132 static int __write_nonblock(int fd, void *buf, int bytes)
135 int bytes_to_write = bytes;
137 if ((fd > 0) && (buf != NULL)) {
139 ret = write(fd, buf, bytes);
144 } else if ((!((errno == EAGAIN) || (errno == EINTR))) || (0 == ret)) {
150 if (bytes == bytes_to_write)
153 return (bytes_to_write - bytes);
157 static int __vbc_write_response(int fd, unsigned int cmd, uint32_t paras_size)
160 vbc_parameters_head write_head;
162 memset(&write_head, 0, sizeof(vbc_parameters_head));
163 memcpy(&write_head.tag[0], VBC_CMD_TAG, 3);
164 write_head.cmd_type = cmd + 1;
165 write_head.paras_size = paras_size;
167 ret = __write_nonblock(fd, (void*)&write_head, sizeof(vbc_parameters_head));
169 AUDIO_LOG_ERROR("write failed");
171 AUDIO_LOG_DEBUG("write success for VBC_CMD_[%s]", vbc_cmd_str_arry[cmd]);
176 int _audio_modem_is_call_connected(audio_hal_s *ah)
178 int val = -1; /* Mixer values 0 - cp [3g] ,1 - cp [2g] ,2 - ap */
180 _mixer_control_get_value(ah, MIXER_VBC_SWITCH, &val);
181 AUDIO_LOG_INFO("modem is connected for call = %d", (val == VBC_TD_CHANNELID));
183 return (val == VBC_TD_CHANNELID) ? 1 : 0;
186 static void __i2s_pin_mux_sel(audio_hal_s *ah, int type)
188 audio_return_e ret = AUDIO_RET_OK;
189 audio_modem_t *modem;
192 AUDIO_LOG_ERROR("ah is null");
196 AUDIO_LOG_INFO("type is %d",type);
197 modem = ah->modem.cp;
200 if(ah->device.active_out & AUDIO_DEVICE_OUT_BT_SCO) {
201 if(modem->i2s_bt.is_ext) {
202 if(modem->i2s_bt.is_switch) {
203 ret = _mixer_control_set_value(ah,
204 PIN_SWITCH_IIS0_SYS_SEL, PIN_SWITCH_IIS0_CP0_ID);
207 if(modem->i2s_bt.is_switch) {
209 _mixer_control_get_value (ah, PIN_SWITCH_IIS0_SYS_SEL, &value);
210 if(value == PIN_SWITCH_IIS0_CP0_ID) {
211 ret = _mixer_control_set_value(ah,
212 PIN_SWITCH_IIS0_SYS_SEL, PIN_SWITCH_IIS0_AP_ID);
215 if(ah->device.active_out & AUDIO_DEVICE_OUT_BT_SCO) {
216 if(modem->i2s_bt.is_switch) {
217 ret = _mixer_control_set_value(ah,
218 PIN_SWITCH_BT_IIS_SYS_SEL, PIN_SWITCH_BT_IIS_CP0_IIS0_ID);
223 } else if (type == 1) {
224 if(ah->device.active_out & AUDIO_DEVICE_OUT_BT_SCO) {
225 if(modem->i2s_bt.is_ext) {
226 if(modem->i2s_bt.is_switch) {
227 ret = _mixer_control_set_value(ah,
228 PIN_SWITCH_IIS0_SYS_SEL, PIN_SWITCH_IIS0_CP1_ID);
231 if(modem->i2s_bt.is_switch) {
233 _mixer_control_get_value (ah, PIN_SWITCH_IIS0_SYS_SEL, &value);
234 if(value == PIN_SWITCH_IIS0_CP1_ID) {
235 ret = _mixer_control_set_value(ah,
236 PIN_SWITCH_IIS0_SYS_SEL, PIN_SWITCH_IIS0_CP2_ID);
239 if(ah->device.active_out & AUDIO_DEVICE_OUT_BT_SCO) {
240 if(modem->i2s_bt.is_switch) {
241 ret = _mixer_control_set_value(ah,
242 PIN_SWITCH_BT_IIS_SYS_SEL, PIN_SWITCH_BT_IIS_CP1_IIS0_ID);
248 AUDIO_LOG_ERROR("invalid type");
252 AUDIO_LOG_ERROR("error(0x%x)", ret);
257 static void *__vbc_control_voice_thread_run(void *args)
259 audio_return_e audio_ret = AUDIO_RET_OK;
260 vbc_parameters_head read_head;
261 vbc_parameters_head write_head;
262 int exit_thread = 0; /* make exit variable global if required to gracefully exit */
264 vbc_control_params_t *params = (vbc_control_params_t*)args;
265 if (params == NULL) {
266 return (void*)AUDIO_ERR_PARAMETER;
268 audio_hal_s *ah = params->ah;
270 struct timeval timeout = {5,0};
272 memset(&read_head, 0, sizeof(vbc_parameters_head));
273 memset(&write_head, 0, sizeof(vbc_parameters_head));
275 memcpy(&write_head.tag[0], VBC_CMD_TAG, 3);
276 write_head.cmd_type = VBC_CMD_NONE;
277 write_head.paras_size = 0;
279 AUDIO_LOG_INFO("[voice] vbc control VOICE thread run");
282 /* open vbpipe device for vb parameter interface between ap and cp */
283 vbpipe_fd = open(VBPIPE_DEVICE, O_RDWR);
287 AUDIO_LOG_ERROR("[voice] vbpipe open failed: %s", strerror(errno));
288 return (void*)AUDIO_ERR_IOCTL;
290 ah->modem.vbc.vbpipe_fd = vbpipe_fd;
292 if (fcntl(vbpipe_fd, F_SETFL, O_NONBLOCK) < 0) {
293 AUDIO_LOG_DEBUG("[voice] vbpipe_fd(%d) fcntl error.", vbpipe_fd);
296 AUDIO_LOG_INFO("[voice] %s opened. vbc start loop", VBPIPE_DEVICE);
299 while (!exit_thread) {
304 /* read command received from cp */
306 FD_SET(vbpipe_fd, &fds_read);
308 ret = select(vbpipe_fd+1, &fds_read, NULL, NULL, &timeout);
310 ALOGE("voice:select error %d", errno);
315 ret = __read_nonblock(vbpipe_fd, &read_head, sizeof(vbc_parameters_head));
321 AUDIO_LOG_DEBUG("[voice] Received %d bytes. data: %s, cmd_type: %d", ret, read_head.tag, read_head.cmd_type);
323 if (!memcmp(&read_head.tag[0], VBC_CMD_TAG, 3)) {
324 switch (read_head.cmd_type) {
325 case VBC_CMD_PCM_OPEN: {
326 open_pcm_t open_pcm_params;
327 uint32_t paras_size = ((ah->modem.cp->i2s_bt.is_switch << 8) | (ah->modem.cp->i2s_bt.index << 0)
328 | (ah->modem.cp->i2s_extspk.is_switch << 9) | (ah->modem.cp->i2s_extspk.index << 4));
330 AUDIO_LOG_INFO("[voice] Received VBC_CMD_PCM_OPEN");
332 ah->modem.is_connected = 1;
333 if ((audio_ret = _audio_update_route_voicecall(ah, ah->device.init_call_devices, ah->device.num_of_call_devices))) {
334 AUDIO_LOG_WARN("set voicecall route return 0x%x", audio_ret);
335 if (audio_ret == AUDIO_ERR_INVALID_STATE) {
336 /* send signal and wait for the ucm setting,
337 * it might an incoming call scenario */
338 _audio_comm_send_message(ah, SIGNAL_ROUTING_FOR_VOICE_CALL, 1);
339 COND_TIMEDWAIT(ah->device.device_cond, ah->device.device_lock, "device_cond", TIMEOUT_SEC);
340 MUTEX_UNLOCK(ah->device.device_lock, "device_lock");
344 memset(&open_pcm_params, 0, sizeof(open_pcm_t));
345 ret = __read_nonblock(vbpipe_fd, &open_pcm_params, sizeof(open_pcm_t));
347 AUDIO_LOG_ERROR("read failed");
349 ah->modem.sim_id = open_pcm_params.sim_card;
351 if (ah->device.active_out & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_BT_SCO)) {
352 if (ah->modem.cp_type == CP_TG)
353 __i2s_pin_mux_sel(ah, 1);
354 else if(ah->modem.cp_type == CP_W)
355 __i2s_pin_mux_sel(ah, 0);
358 AUDIO_LOG_DEBUG("[voice] Send response for VBC_CMD_PCM_OPEN");
359 __vbc_write_response(vbpipe_fd, VBC_CMD_PCM_OPEN, paras_size);
363 case VBC_CMD_PCM_CLOSE: {
364 AUDIO_LOG_INFO("[voice] Received VBC_CMD_PCM_CLOSE");
366 ah->modem.samplerate = 0;
367 ah->modem.is_connected = 0;
369 /* send signal and wait for the reset ucm */
370 _audio_comm_send_message(ah, SIGNAL_ROUTING_FOR_VOICE_CALL, 0);
371 COND_TIMEDWAIT(ah->device.device_cond, ah->device.device_lock, "device_cond", TIMEOUT_SEC);
372 MUTEX_UNLOCK(ah->device.device_lock, "device_lock");
374 _mixer_control_set_value(ah, MIXER_VBC_SWITCH, VBC_ARM_CHANNELID);
376 AUDIO_LOG_DEBUG("[voice] Send response for VBC_CMD_PCM_CLOSE");
377 __vbc_write_response(vbpipe_fd, VBC_CMD_PCM_CLOSE, 0);
381 case VBC_CMD_RESP_CLOSE: {
382 AUDIO_LOG_INFO("[voice] Received VBC_CMD_RESP_CLOSE & send response");
383 ret = __vbc_write_response(vbpipe_fd, VBC_CMD_PCM_CLOSE, 0);
387 case VBC_CMD_SET_MODE: {
389 memset(dummy, 0, sizeof(dummy));
390 AUDIO_LOG_INFO("[voice] Received VBC_CMD_SET_MODE");
392 if (ah->device.active_out & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_BT_SCO)) {
393 if (ah->modem.cp_type == CP_TG)
394 __i2s_pin_mux_sel(ah, 1);
395 else if(ah->modem.cp_type == CP_W)
396 __i2s_pin_mux_sel(ah, 0);
398 /* To do: set mode params : __vbc_set_mode_params(ah, vbpipe_fd); */
400 __read_nonblock(vbpipe_fd, dummy, sizeof(dummy));
401 AUDIO_LOG_DEBUG("[voice] Send response for VBC_CMD_SET_MODE");
402 __vbc_write_response(vbpipe_fd, VBC_CMD_SET_MODE, 0);
405 case VBC_CMD_SET_GAIN: {
406 AUDIO_LOG_INFO("[voice] Received VBC_CMD_SET_GAIN");
408 /* To do: set gain params : __vbc_set_gain_params(ah, vbpipe_fd); */
410 AUDIO_LOG_DEBUG("[voice] Send response for VBC_CMD_SET_GAIN");
411 __vbc_write_response(vbpipe_fd, VBC_CMD_SET_GAIN, 0);
414 case VBC_CMD_SWITCH_CTRL: {
415 switch_ctrl_t switch_ctrl_params;
417 AUDIO_LOG_INFO("[voice] Received VBC_CMD_SWITCH_CTRL");
419 memset(&switch_ctrl_params,0,sizeof(switch_ctrl_t));
420 ret = __read_nonblock(vbpipe_fd, &switch_ctrl_params, sizeof(switch_ctrl_t));
422 AUDIO_LOG_ERROR("read failed");
424 AUDIO_LOG_INFO("is_switch:%d", switch_ctrl_params.is_switch);
426 _mixer_control_set_value(ah, MIXER_VBC_SWITCH, VBC_TD_CHANNELID);
428 AUDIO_LOG_DEBUG("[voice] Send response for VBC_CMD_SET_GAIN");
429 __vbc_write_response(vbpipe_fd, VBC_CMD_SWITCH_CTRL, 0);
432 case VBC_CMD_SET_MUTE: {
433 AUDIO_LOG_INFO("[voice] Received VBC_CMD_SET_MUTE");
436 case VBC_CMD_DEVICE_CTRL: {
438 memset(dummy, 0, sizeof(dummy));
439 AUDIO_LOG_INFO("[voice] Received VBC_CMD_DEVICE_CTRL");
441 /* To do: set device ctrl params :__vbc_set_device_ctrl_params(ah, vbpipe_fd); */
442 __read_nonblock(vbpipe_fd, dummy, sizeof(dummy));
444 AUDIO_LOG_DEBUG("[voice] Send response for VBC_CMD_DEVICE_CTRL");
445 __vbc_write_response(vbpipe_fd, VBC_CMD_DEVICE_CTRL, 0);
449 case VBC_CMD_SET_SAMPLERATE: {
450 AUDIO_LOG_INFO("[voice] Received VBC_CMD_SET_SAMPLERATE");
452 AUDIO_LOG_DEBUG("[voice] Send response for VBC_CMD_SET_SAMPLERATE");
453 __vbc_write_response(vbpipe_fd, VBC_CMD_SET_SAMPLERATE, 0);
457 AUDIO_LOG_WARN("[voice] Unknown command received : %d", read_head.cmd_type);
467 AUDIO_LOG_INFO("Exit vbc VOICE thread");
472 static void *__vbc_control_voip_thread_run(void *args)
474 open_pcm_t open_pcm_params;
475 vbc_parameters_head read_head;
476 vbc_parameters_head write_head;
477 int exit_thread = 0; /* make exit variable global if required to gracefully exit */
479 vbc_control_params_t *params = (vbc_control_params_t*)args;
480 if (params == NULL) {
481 return (void*)AUDIO_ERR_PARAMETER;
483 audio_hal_s *ah = params->ah;
486 struct timeval timeout = {5,0};
488 memset(&read_head, 0, sizeof(vbc_parameters_head));
489 memset(&write_head, 0, sizeof(vbc_parameters_head));
491 memcpy(&write_head.tag[0], VBC_CMD_TAG, 3);
492 write_head.cmd_type = VBC_CMD_NONE;
493 write_head.paras_size = 0;
495 AUDIO_LOG_INFO("[voip] vbc control VOIP thread run");
498 /* open vbpipe device for vb parameter interface between ap and cp */
499 vbpipe_fd = open(VBPIPE_VOIP_DEVICE, O_RDWR);
503 AUDIO_LOG_ERROR("[voip] vbpipe open failed: %s", strerror(errno));
506 ah->modem.vbc.vbpipe_voip_fd = vbpipe_fd;
508 if (fcntl(vbpipe_fd, F_SETFL, O_NONBLOCK) < 0) {
509 AUDIO_LOG_DEBUG("[voip] vbpipe_fd(%d) fcntl error.", vbpipe_fd);
512 AUDIO_LOG_INFO("[voip] %s opened. vbc start loop", VBPIPE_VOIP_DEVICE);
515 while (!exit_thread) {
520 /* read command received from cp */
523 FD_SET(vbpipe_fd, &fds_read);
525 ret = select(vbpipe_fd+1, &fds_read, NULL, NULL, &timeout);
527 ALOGE("[voip] select error %d", errno);
531 ret = __read_nonblock(vbpipe_fd, &read_head, sizeof(vbc_parameters_head));
536 AUDIO_LOG_DEBUG("[voip] Received %d bytes. data: %s, cmd_type: %d", ret, read_head.tag, read_head.cmd_type);
538 if (!memcmp(&read_head.tag[0], VBC_CMD_TAG, 3)) {
539 switch (read_head.cmd_type) {
540 case VBC_CMD_PCM_OPEN: {
541 uint32_t paras_size = ((ah->modem.cp->i2s_bt.is_switch << 8) | (ah->modem.cp->i2s_bt.index << 0)
542 | (ah->modem.cp->i2s_extspk.is_switch << 9) | (ah->modem.cp->i2s_extspk.index << 4));
544 AUDIO_LOG_INFO("[voip] Received VBC_CMD_PCM_OPEN");
546 memset(&open_pcm_params, 0, sizeof(open_pcm_t));
547 ret = __read_nonblock(vbpipe_fd, &open_pcm_params, sizeof(open_pcm_t));
549 AUDIO_LOG_ERROR("read failed");
551 AUDIO_LOG_DEBUG("[voip] Send response for VBC_CMD_PCM_OPEN");
552 __vbc_write_response(vbpipe_fd, VBC_CMD_PCM_OPEN, paras_size);
555 case VBC_CMD_PCM_CLOSE: {
556 AUDIO_LOG_INFO("[voip] Received VBC_CMD_PCM_CLOSE & send response");
558 __vbc_write_response(vbpipe_fd, VBC_CMD_PCM_CLOSE, 0);
562 case VBC_CMD_RESP_CLOSE: {
563 AUDIO_LOG_INFO("[voip] Received VBC_CMD_RESP_CLOSE & send response");
565 ret = __vbc_write_response(vbpipe_fd, VBC_CMD_PCM_CLOSE, 0);
568 case VBC_CMD_SET_MODE: {
569 AUDIO_LOG_INFO("[voip] Received VBC_CMD_SET_MODE");
571 if (ah->device.active_out & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_BT_SCO)) {
572 if (ah->modem.cp_type == CP_TG)
573 __i2s_pin_mux_sel(ah, 1);
574 else if(ah->modem.cp_type == CP_W)
575 __i2s_pin_mux_sel(ah, 0);
577 /* To do: set mode params : __vbc_set_mode_params(ah, vbpipe_fd); */
578 AUDIO_LOG_DEBUG("[voip] Send response for VBC_CMD_SET_MODE");
579 __vbc_write_response(vbpipe_fd, VBC_CMD_SET_MODE, 0);
582 case VBC_CMD_SET_GAIN: {
583 AUDIO_LOG_INFO("[voip] Received VBC_CMD_SET_GAIN");
585 /* To do: set gain params : __vbc_set_gain_params(ah, vbpipe_fd); */
586 AUDIO_LOG_DEBUG("[voip] Send response for VBC_CMD_SET_GAIN");
587 __vbc_write_response(vbpipe_fd, VBC_CMD_SET_GAIN, 0);
590 case VBC_CMD_SWITCH_CTRL: {
591 switch_ctrl_t switch_ctrl_params;
593 AUDIO_LOG_INFO("[voip] Received VBC_CMD_SWITCH_CTRL");
595 memset(&switch_ctrl_params, 0, sizeof(switch_ctrl_t));
596 ret = __read_nonblock(vbpipe_fd, &switch_ctrl_params, sizeof(switch_ctrl_t));
598 AUDIO_LOG_ERROR("read failed");
600 AUDIO_LOG_INFO("is_switch:%d", switch_ctrl_params.is_switch);
602 _mixer_control_set_value(ah, MIXER_VBC_SWITCH, VBC_TD_CHANNELID);
604 AUDIO_LOG_DEBUG("[voip] Send response for VBC_CMD_SWITCH_CTRL");
605 __vbc_write_response(vbpipe_fd, VBC_CMD_SWITCH_CTRL, 0);
608 case VBC_CMD_SET_MUTE: {
609 AUDIO_LOG_INFO("[voip] Received VBC_CMD_SET_MUTE & send response");
610 __vbc_write_response(vbpipe_fd, VBC_CMD_SET_MUTE, 0);
613 case VBC_CMD_DEVICE_CTRL: {
614 AUDIO_LOG_INFO("[voip] Received VBC_CMD_DEVICE_CTRL");
615 __vbc_write_response(vbpipe_fd, VBC_CMD_DEVICE_CTRL, 0);
618 case VBC_CMD_SET_SAMPLERATE: {
619 AUDIO_LOG_INFO("[voip] Received VBC_CMD_SET_SAMPLERATE");
621 AUDIO_LOG_DEBUG("[voip] Send response for VBC_CMD_SET_SAMPLERATE");
622 __vbc_write_response(vbpipe_fd, VBC_CMD_SET_SAMPLERATE, 0);
626 AUDIO_LOG_WARN("Unknown command received : %d", read_head.cmd_type);
635 AUDIO_LOG_INFO("Exit vbc VOIP thread");
640 static audio_return_e __vbc_control_open(audio_hal_s *ah)
642 vbc_control_params_t *params = (vbc_control_params_t*)malloc(sizeof(vbc_control_params_t));
643 audio_return_e ret = AUDIO_RET_OK;
644 audio_return_e ret2 = AUDIO_RET_OK;
646 if (params == NULL) {
647 AUDIO_LOG_ERROR("vbc control param allocation failed");
648 return AUDIO_ERR_RESOURCE;
652 AUDIO_LOG_INFO("vbc control thread create");
653 ret = vbc_thread_new(&ah->modem.vbc.voice_thread_handle, NULL, __vbc_control_voice_thread_run, (void*)params);
655 AUDIO_LOG_ERROR("vbc control thread create failed");
656 ret = AUDIO_ERR_RESOURCE;
660 ret2 = vbc_thread_new(&ah->modem.vbc.voip_thread_handle, NULL, __vbc_control_voip_thread_run, (void*)params);
662 AUDIO_LOG_ERROR("vbc control VOIP thread create failed");
663 ret2 = AUDIO_ERR_RESOURCE;
670 void __vbc_control_close(audio_hal_s *ah)
673 /* TODO. Make sure we always receive CLOSE command from modem and then close pcm device */
674 ah->modem.vbc.exit_vbc_thread = 1;
675 close(ah->modem.vbc.vbpipe_fd);
677 ret = pthread_cancel(ah->modem.vbc.voice_thread_handle);
678 AUDIO_LOG_INFO("cancel voice thread : %d", ret);
679 ret = pthread_cancel(ah->modem.vbc.voip_thread_handle);
680 AUDIO_LOG_INFO("cancel voip thread : %d", ret);
682 ret = pthread_join(ah->modem.vbc.voice_thread_handle, NULL);
683 AUDIO_LOG_INFO("join voice thread : %d", ret);
684 ret = pthread_join(ah->modem.vbc.voip_thread_handle, NULL);
685 AUDIO_LOG_INFO("join voip thread : %d", ret);
690 static void __audio_modem_create(audio_modem_t *modem, const char *num)
692 if (!atoi((char *)num)) {
693 AUDIO_LOG_ERROR("Unnormal modem num!");
697 modem->num = atoi((char *)num);
698 /* check if we need to allocate space for modem profile */
699 if (!modem->vbc_ctrl_pipe_info) {
700 modem->vbc_ctrl_pipe_info = malloc(modem->num * sizeof(vbc_ctrl_pipe_para_t));
701 if (modem->vbc_ctrl_pipe_info == NULL) {
702 AUDIO_LOG_ERROR("Unable to allocate modem profiles");
706 /* initialise the new profile */
707 memset((void*)modem->vbc_ctrl_pipe_info, 0x00, modem->num * sizeof(vbc_ctrl_pipe_para_t));
710 AUDIO_LOG_DEBUG("peter: modem num is %d", modem->num);
714 static void __audio_modem_start_tag(void *data, const XML_Char *tag_name,
715 const XML_Char **attr)
717 audio_modem_t *modem = (audio_modem_t *)data;
720 if (strcmp(tag_name, "audio") == 0) {
721 if (strcmp(attr[0], "device") == 0) {
722 AUDIO_LOG_INFO("The device name is %s", attr[1]);
724 AUDIO_LOG_ERROR("Unnamed audio!");
726 } else if (strcmp(tag_name, "modem") == 0) {
727 /* Obtain the modem num */
728 if (strcmp(attr[0], "num") == 0) {
729 AUDIO_LOG_DEBUG("The modem num is '%s'", attr[1]);
730 __audio_modem_create(modem, attr[1]);
732 AUDIO_LOG_ERROR("no modem num!");
734 } else if (strcmp(tag_name, "cp") == 0) {
735 static int modem_index = 0;
736 vbc_ctrl_pipe_para_t *para = &modem->vbc_ctrl_pipe_info[modem_index];
738 if (modem->vbc_ctrl_pipe_info) {
739 /* Obtain the modem name \pipe\vbc filed */
740 if (strcmp(attr[0], "name") != 0) {
741 AUDIO_LOG_ERROR("Unnamed modem!");
744 if (strcmp(attr[2], "pipe") != 0) {
745 AUDIO_LOG_ERROR("'%s' No pipe filed!", attr[0]);
748 if (strcmp(attr[4], "vbchannel") != 0) {
749 AUDIO_LOG_ERROR("'%s' No vbc filed!", attr[0]);
752 AUDIO_LOG_DEBUG("cp name is '%s', pipe is '%s',vbc is '%s'", attr[1], attr[3],attr[5]);
753 if(strcmp(attr[1], "w") == 0)
755 para->cp_type = CP_W;
757 else if(strcmp(attr[1], "t") == 0)
759 para->cp_type = CP_TG;
761 memcpy((void*)para->s_vbc_ctrl_pipe_name,(void*)attr[3],strlen((char *)attr[3]));
762 para->channel_id = atoi((char *)attr[5]);
766 AUDIO_LOG_ERROR("error profile!");
768 } else if (strcmp(tag_name, "i2s_for_btcall") == 0) {
769 if (strcmp(attr[0], "index") == 0) {
770 AUDIO_LOG_DEBUG("The iis_for_btcall index is '%s'", attr[1]);
771 modem->i2s_bt.index = atoi((char *)attr[1]);
773 AUDIO_LOG_ERROR("no iis_ctl index for bt call!");
776 if (strcmp(attr[2], "switch") == 0) {
777 AUDIO_LOG_DEBUG("The iis_for_btcall switch is '%s'", attr[3]);
778 if(strcmp(attr[3],"1") == 0)
779 modem->i2s_bt.is_switch = true;
780 else if(strcmp(attr[3],"0") == 0)
781 modem->i2s_bt.is_switch = false;
783 AUDIO_LOG_ERROR("no iis_ctl switch for bt call!");
785 if (strcmp(attr[4], "dst") == 0) {
786 AUDIO_LOG_DEBUG("The iis_for_btcall dst is '%s'", attr[5]);
787 if (strcmp(attr[5], "internal") == 0)
788 modem->i2s_bt.is_ext = 0;
789 else if (strcmp(attr[5], "external") == 0)
790 modem->i2s_bt.is_ext = 1;
792 AUDIO_LOG_ERROR("no dst path for bt call!");
794 } else if (strcmp(tag_name, "i2s_for_extspeaker") == 0) {
795 if (strcmp(attr[0], "index") == 0) {
796 AUDIO_LOG_DEBUG("The i2s_for_extspeaker index is '%s'", attr[1]);
797 modem->i2s_extspk.index = atoi((char *)attr[1]);
799 AUDIO_LOG_ERROR("no iis_ctl index for extspk call!");
801 if (strcmp(attr[2], "switch") == 0) {
802 AUDIO_LOG_DEBUG("The iis_for_btcall switch is '%s'", attr[3]);
803 if(strcmp(attr[3],"1") == 0)
804 modem->i2s_extspk.is_switch = true;
805 else if(strcmp(attr[3],"0") == 0)
806 modem->i2s_extspk.is_switch = false;
808 AUDIO_LOG_ERROR("no iis_ctl switch for extspk call!");
810 if (strcmp(attr[4], "dst") == 0) {
811 if (strcmp(attr[5], "external") == 0)
812 modem->i2s_extspk.is_ext = 1;
813 else if(strcmp(attr[5], "internal") == 0)
814 modem->i2s_extspk.is_ext = 0;
816 AUDIO_LOG_DEBUG("The i2s_for_extspeaker dst is '%d'", modem->i2s_extspk.is_ext);
819 AUDIO_LOG_ERROR("no dst path for bt call!");
821 } else if (strcmp(tag_name, "debug") == 0) { //parse debug info
822 if (strcmp(attr[0], "enable") == 0) {
823 if (strcmp(attr[1], "0") == 0) {
824 modem->debug_info.enable = 0;
826 modem->debug_info.enable = 1;
829 AUDIO_LOG_ERROR("no adaptable type for debug!");
832 } else if (strcmp(tag_name, "debuginfo") == 0) { //parse debug info
833 if (strcmp(attr[0], "sleepdeltatimegate") == 0) {
834 AUDIO_LOG_DEBUG("The sleepdeltatimegate is '%s'", attr[1]);
835 modem->debug_info.sleeptime_gate=atoi((char *)attr[1]);
836 } else if (strcmp(attr[0], "pcmwritetimegate") == 0) {
837 AUDIO_LOG_DEBUG("The pcmwritetimegate is '%s'", attr[1]);
838 modem->debug_info.pcmwritetime_gate=atoi((char *)attr[1]);
839 } else if (strcmp(attr[0], "lastthiswritetimegate") == 0) {
840 AUDIO_LOG_DEBUG("The lastthiswritetimegate is '%s'", attr[1]);
841 modem->debug_info.lastthis_outwritetime_gate=atoi((char *)attr[1]);
843 AUDIO_LOG_ERROR("no adaptable info for debuginfo!");
851 static void __audio_modem_end_tag(void *data, const XML_Char *tag_name)
856 static audio_modem_t * __audio_modem_parse (void)
862 audio_modem_t *modem = NULL;
864 modem = calloc(1, sizeof(audio_modem_t));
869 memset(modem, 0, sizeof(audio_modem_t));
871 modem->vbc_ctrl_pipe_info = NULL;
873 file = fopen(AUDIO_XML_PATH, "r");
875 AUDIO_LOG_ERROR("Failed to open %s", AUDIO_XML_PATH);
879 parser = XML_ParserCreate(NULL);
881 AUDIO_LOG_ERROR("Failed to create XML parser");
882 goto err_parser_create;
885 XML_SetUserData(parser, modem);
886 XML_SetElementHandler(parser, __audio_modem_start_tag, __audio_modem_end_tag);
889 buf = XML_GetBuffer(parser, BUF_SIZE);
893 bytes_read = fread(buf, 1, BUF_SIZE, file);
897 if (XML_ParseBuffer(parser, bytes_read, bytes_read == 0) == XML_STATUS_ERROR) {
898 AUDIO_LOG_ERROR("Error in codec PGA xml (%s)", AUDIO_XML_PATH);
905 XML_ParserFree(parser);
910 XML_ParserFree(parser);
920 audio_return_e _audio_modem_init(audio_hal_s *ah)
922 audio_return_e audio_ret = AUDIO_RET_OK;
924 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
926 ah->modem.vbc.vbpipe_count = 0;
928 /* Initialize vbc interface */
929 if ((audio_ret = __vbc_control_open(ah))) {
930 AUDIO_LOG_ERROR("__vbc_control_open failed");
933 ah->modem.vbc.voice_pcm_handle_p = NULL;
934 ah->modem.vbc.voice_pcm_handle_c = NULL;
935 ah->modem.samplerate = 0;
936 ah->modem.cp = __audio_modem_parse();
937 if (ah->modem.cp == NULL) {
938 AUDIO_LOG_ERROR("modem parse failed");
942 /* FIXME : Use cp type of first modem explicitly */
943 ah->modem.cp_type = ah->modem.cp->vbc_ctrl_pipe_info[0].cp_type;
945 /* This ctrl need to be set "0" always - SPRD */
946 _mixer_control_set_value(ah, PIN_SWITCH_BT_IIS_CON_SWITCH, 0);
952 audio_return_e _audio_modem_deinit(audio_hal_s *ah)
954 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
956 /* Close vbc interface */
957 __vbc_control_close(ah);