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_t *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_t *ah, int type)
188 audio_return_t 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_t 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_t *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_t *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_t __vbc_control_open(audio_hal_t *ah)
642 vbc_control_params_t *params = (vbc_control_params_t*)malloc(sizeof(vbc_control_params_t));
643 audio_return_t ret = AUDIO_RET_OK;
644 audio_return_t 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_t *ah)
672 /* TODO. Make sure we always receive CLOSE command from modem and then close pcm device */
673 ah->modem.vbc.exit_vbc_thread = 1;
674 close(ah->modem.vbc.vbpipe_fd);
676 pthread_cancel(ah->modem.vbc.voice_thread_handle);
677 pthread_cancel(ah->modem.vbc.voip_thread_handle);
682 static void __audio_modem_create(audio_modem_t *modem, const char *num)
684 if (!atoi((char *)num)) {
685 AUDIO_LOG_ERROR("Unnormal modem num!");
689 modem->num = atoi((char *)num);
690 /* check if we need to allocate space for modem profile */
691 if (!modem->vbc_ctrl_pipe_info) {
692 modem->vbc_ctrl_pipe_info = malloc(modem->num * sizeof(vbc_ctrl_pipe_para_t));
693 if (modem->vbc_ctrl_pipe_info == NULL) {
694 AUDIO_LOG_ERROR("Unable to allocate modem profiles");
698 /* initialise the new profile */
699 memset((void*)modem->vbc_ctrl_pipe_info, 0x00, modem->num * sizeof(vbc_ctrl_pipe_para_t));
702 AUDIO_LOG_DEBUG("peter: modem num is %d", modem->num);
706 static void __audio_modem_start_tag(void *data, const XML_Char *tag_name,
707 const XML_Char **attr)
709 audio_modem_t *modem = (audio_modem_t *)data;
712 if (strcmp(tag_name, "audio") == 0) {
713 if (strcmp(attr[0], "device") == 0) {
714 AUDIO_LOG_INFO("The device name is %s", attr[1]);
716 AUDIO_LOG_ERROR("Unnamed audio!");
718 } else if (strcmp(tag_name, "modem") == 0) {
719 /* Obtain the modem num */
720 if (strcmp(attr[0], "num") == 0) {
721 AUDIO_LOG_DEBUG("The modem num is '%s'", attr[1]);
722 __audio_modem_create(modem, attr[1]);
724 AUDIO_LOG_ERROR("no modem num!");
726 } else if (strcmp(tag_name, "cp") == 0) {
727 static int modem_index = 0;
728 vbc_ctrl_pipe_para_t *para = &modem->vbc_ctrl_pipe_info[modem_index];
730 if (modem->vbc_ctrl_pipe_info) {
731 /* Obtain the modem name \pipe\vbc filed */
732 if (strcmp(attr[0], "name") != 0) {
733 AUDIO_LOG_ERROR("Unnamed modem!");
736 if (strcmp(attr[2], "pipe") != 0) {
737 AUDIO_LOG_ERROR("'%s' No pipe filed!", attr[0]);
740 if (strcmp(attr[4], "vbchannel") != 0) {
741 AUDIO_LOG_ERROR("'%s' No vbc filed!", attr[0]);
744 AUDIO_LOG_DEBUG("cp name is '%s', pipe is '%s',vbc is '%s'", attr[1], attr[3],attr[5]);
745 if(strcmp(attr[1], "w") == 0)
747 para->cp_type = CP_W;
749 else if(strcmp(attr[1], "t") == 0)
751 para->cp_type = CP_TG;
753 memcpy((void*)para->s_vbc_ctrl_pipe_name,(void*)attr[3],strlen((char *)attr[3]));
754 para->channel_id = atoi((char *)attr[5]);
758 AUDIO_LOG_ERROR("error profile!");
760 } else if (strcmp(tag_name, "i2s_for_btcall") == 0) {
761 if (strcmp(attr[0], "index") == 0) {
762 AUDIO_LOG_DEBUG("The iis_for_btcall index is '%s'", attr[1]);
763 modem->i2s_bt.index = atoi((char *)attr[1]);
765 AUDIO_LOG_ERROR("no iis_ctl index for bt call!");
768 if (strcmp(attr[2], "switch") == 0) {
769 AUDIO_LOG_DEBUG("The iis_for_btcall switch is '%s'", attr[3]);
770 if(strcmp(attr[3],"1") == 0)
771 modem->i2s_bt.is_switch = true;
772 else if(strcmp(attr[3],"0") == 0)
773 modem->i2s_bt.is_switch = false;
775 AUDIO_LOG_ERROR("no iis_ctl switch for bt call!");
777 if (strcmp(attr[4], "dst") == 0) {
778 AUDIO_LOG_DEBUG("The iis_for_btcall dst is '%s'", attr[5]);
779 if (strcmp(attr[5], "internal") == 0)
780 modem->i2s_bt.is_ext = 0;
781 else if (strcmp(attr[5], "external") == 0)
782 modem->i2s_bt.is_ext = 1;
784 AUDIO_LOG_ERROR("no dst path for bt call!");
786 } else if (strcmp(tag_name, "i2s_for_extspeaker") == 0) {
787 if (strcmp(attr[0], "index") == 0) {
788 AUDIO_LOG_DEBUG("The i2s_for_extspeaker index is '%s'", attr[1]);
789 modem->i2s_extspk.index = atoi((char *)attr[1]);
791 AUDIO_LOG_ERROR("no iis_ctl index for extspk call!");
793 if (strcmp(attr[2], "switch") == 0) {
794 AUDIO_LOG_DEBUG("The iis_for_btcall switch is '%s'", attr[3]);
795 if(strcmp(attr[3],"1") == 0)
796 modem->i2s_extspk.is_switch = true;
797 else if(strcmp(attr[3],"0") == 0)
798 modem->i2s_extspk.is_switch = false;
800 AUDIO_LOG_ERROR("no iis_ctl switch for extspk call!");
802 if (strcmp(attr[4], "dst") == 0) {
803 if (strcmp(attr[5], "external") == 0)
804 modem->i2s_extspk.is_ext = 1;
805 else if(strcmp(attr[5], "internal") == 0)
806 modem->i2s_extspk.is_ext = 0;
808 AUDIO_LOG_DEBUG("The i2s_for_extspeaker dst is '%d'", modem->i2s_extspk.is_ext);
811 AUDIO_LOG_ERROR("no dst path for bt call!");
813 } else if (strcmp(tag_name, "debug") == 0) { //parse debug info
814 if (strcmp(attr[0], "enable") == 0) {
815 if (strcmp(attr[1], "0") == 0) {
816 modem->debug_info.enable = 0;
818 modem->debug_info.enable = 1;
821 AUDIO_LOG_ERROR("no adaptable type for debug!");
824 } else if (strcmp(tag_name, "debuginfo") == 0) { //parse debug info
825 if (strcmp(attr[0], "sleepdeltatimegate") == 0) {
826 AUDIO_LOG_DEBUG("The sleepdeltatimegate is '%s'", attr[1]);
827 modem->debug_info.sleeptime_gate=atoi((char *)attr[1]);
828 } else if (strcmp(attr[0], "pcmwritetimegate") == 0) {
829 AUDIO_LOG_DEBUG("The pcmwritetimegate is '%s'", attr[1]);
830 modem->debug_info.pcmwritetime_gate=atoi((char *)attr[1]);
831 } else if (strcmp(attr[0], "lastthiswritetimegate") == 0) {
832 AUDIO_LOG_DEBUG("The lastthiswritetimegate is '%s'", attr[1]);
833 modem->debug_info.lastthis_outwritetime_gate=atoi((char *)attr[1]);
835 AUDIO_LOG_ERROR("no adaptable info for debuginfo!");
843 static void __audio_modem_end_tag(void *data, const XML_Char *tag_name)
848 static audio_modem_t * __audio_modem_parse (void)
854 audio_modem_t *modem = NULL;
856 modem = calloc(1, sizeof(audio_modem_t));
861 memset(modem, 0, sizeof(audio_modem_t));
863 modem->vbc_ctrl_pipe_info = NULL;
865 file = fopen(AUDIO_XML_PATH, "r");
867 AUDIO_LOG_ERROR("Failed to open %s", AUDIO_XML_PATH);
871 parser = XML_ParserCreate(NULL);
873 AUDIO_LOG_ERROR("Failed to create XML parser");
874 goto err_parser_create;
877 XML_SetUserData(parser, modem);
878 XML_SetElementHandler(parser, __audio_modem_start_tag, __audio_modem_end_tag);
881 buf = XML_GetBuffer(parser, BUF_SIZE);
885 bytes_read = fread(buf, 1, BUF_SIZE, file);
889 if (XML_ParseBuffer(parser, bytes_read, bytes_read == 0) == XML_STATUS_ERROR) {
890 AUDIO_LOG_ERROR("Error in codec PGA xml (%s)", AUDIO_XML_PATH);
897 XML_ParserFree(parser);
902 XML_ParserFree(parser);
912 audio_return_t _audio_modem_init(audio_hal_t *ah)
914 audio_return_t audio_ret = AUDIO_RET_OK;
916 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
918 ah->modem.vbc.vbpipe_count = 0;
920 /* Initialize vbc interface */
921 if ((audio_ret = __vbc_control_open(ah))) {
922 AUDIO_LOG_ERROR("__vbc_control_open failed");
925 ah->modem.vbc.voice_pcm_handle_p = NULL;
926 ah->modem.vbc.voice_pcm_handle_c = NULL;
927 ah->modem.samplerate = 0;
928 ah->modem.cp = __audio_modem_parse();
929 if (ah->modem.cp == NULL) {
930 AUDIO_LOG_ERROR("modem parse failed");
934 /* FIXME : Use cp type of first modem explicitly */
935 ah->modem.cp_type = ah->modem.cp->vbc_ctrl_pipe_info[0].cp_type;
937 /* This ctrl need to be set "0" always - SPRD */
938 _mixer_control_set_value(ah, PIN_SWITCH_BT_IIS_CON_SWITCH, 0);
944 audio_return_t _audio_modem_deinit(audio_hal_t *ah)
946 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
948 /* Close vbc interface */
949 __vbc_control_close(ah);