| /* Copyright Statement: |
| * |
| * This software/firmware and related documentation ("MediaTek Software") are |
| * protected under relevant copyright laws. The information contained herein |
| * is confidential and proprietary to MediaTek Inc. and/or its licensors. |
| * Without the prior written permission of MediaTek inc. and/or its licensors, |
| * any reproduction, modification, use or disclosure of MediaTek Software, |
| * and information contained herein, in whole or in part, shall be strictly prohibited. |
| */ |
| /* MediaTek Inc. (C) 2010. All rights reserved. |
| * |
| * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES |
| * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") |
| * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON |
| * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. |
| * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE |
| * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR |
| * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH |
| * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES |
| * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES |
| * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK |
| * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR |
| * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND |
| * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, |
| * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, |
| * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO |
| * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. |
| * |
| * The following software/firmware and/or related documentation ("MediaTek Software") |
| * have been modified by MediaTek Inc. All revisions are subject to any receiver's |
| * applicable license agreements with MediaTek Inc. |
| */ |
| #include "cc.h" |
| #include <alloca.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <cutils/jstring.h> |
| #include <stdbool.h> |
| #include <glib.h> |
| #include <string.h> |
| #include <string> |
| #include <thread> |
| #include "eCall.h" |
| |
| static int dtmf_volume = 0; |
| void *dtmf_handle = NULL; |
| |
| extern "C" { |
| #include <dtmf.h> |
| #include "mixer_ctrl.h" |
| } |
| #undef LOG_TAG |
| #define LOG_TAG "DEMO_CC" |
| |
| static speech_status speechStatus = SPEECH_OFF; |
| int autoAnswerMode = 0; |
| static int inCallRecordMode = 0; |
| static call_status inCallstatus = CALL_OFF; |
| //int callIndex = 0; |
| const char g_card_name[] = "mtk_phonecall"; |
| /*for speech on*/ |
| const char g_mixer_name[] = "Speech_on"; |
| const char g_mixer_name_ecall[] = "Speech_on_ecall"; |
| const char g_mixer_reset_name[] = "Modem_reset_notify"; |
| const char g_mixer_name_bt[] = "Speech_on_bt"; |
| const char g_bt_has_ecnr_name[] = "BT_HAS_ECNR"; |
| const char g_bt_wbs_name[] = "BT_WBS"; |
| int g_audio_path = 0; // 0: normal, 1: bt |
| int g_bt_has_ecnr_value = 0; // 0: ecnr, 1, no ecnr |
| int g_bt_wbs_value = 0; // 0: 8000, 1, 16000 |
| /*for DL call volume*/ |
| const char g_mixer_name_volume[] = "DL Call"; |
| const char g_mixer_name_volume_bt[] = "DL BT"; |
| |
| const char g_DL_mute_name[] = "Speech_DL_mute"; |
| const char g_UL_mute_name[] = "Speech_UL_mute"; |
| |
| const char *RING_PATH = "/system/etc/tele/ring/ring.wav"; |
| static bool isRingStart = false; |
| |
| #if defined(TARGET_PLATFORM_MT2731)||defined(TARGET_PLATFORM_MT2735) |
| #define MAX_VOLUME (6) |
| #define MIN_VOLUME (0) |
| #endif |
| |
| #ifdef TARGET_PLATFORM_MT2635 |
| #define MAX_VOLUME (17) |
| #define MIN_VOLUME (-23) |
| #endif |
| |
| #define BT_MAX_VOLUME (15) |
| #define BT_MIN_VOLUME (0) |
| #define DTMF_MAX_VOLUME (36) |
| #define DTMF_MIN_VOLUME (0) |
| |
| int get_call_status(void) |
| { |
| return inCallstatus; |
| } |
| |
| void set_audio_path(int path) |
| { |
| if ((path != 0) && (path != 1)) { |
| RLOGE("set_audio_path() illegal value %d, we support 0: normal, 1: bt", path); |
| return; |
| } |
| |
| g_audio_path = path; |
| } |
| |
| int get_audio_path(void) |
| { |
| return g_audio_path; |
| } |
| |
| void set_bt_has_ecnr(int ecnr) |
| { |
| if ((ecnr != 0) && (ecnr != 1)) { |
| RLOGE("set_bt_has_ecnr() illegal value %d, we support 0: do ecnr, 1: no ecnr", ecnr); |
| return; |
| } |
| |
| g_bt_has_ecnr_value = ecnr; |
| } |
| |
| int get_bt_has_ecnr(void) |
| { |
| return g_bt_has_ecnr_value; |
| } |
| |
| void set_bt_wbs(int wbs) |
| { |
| if ((wbs < 0) || (wbs > 15)) { |
| RLOGE("set_bt_wbs() illegal value %d, we support 0~15", wbs); |
| return; |
| } |
| |
| g_bt_wbs_value = wbs; |
| } |
| |
| int get_bt_wbs(void) |
| { |
| return g_bt_wbs_value; |
| } |
| |
| int mixer_init() |
| { |
| int ret; |
| |
| // only need to set card name once |
| ret = set_card_name(g_card_name); |
| RLOGD("mixer_init(%s) = %d", g_card_name, ret); |
| return ret; |
| } |
| int mixer_set(int value ) |
| { |
| int ret; |
| |
| //set mixer ctl to om:1 or off:0 |
| if(value){ |
| ret = set_mixer_ctrl_value_int(isEcallAudioPath() ? g_mixer_name_ecall: g_mixer_name, value); |
| RLOGD("mixer_set(%s) = %d, ret: %d", (isEcallAudioPath() ? g_mixer_name_ecall: g_mixer_name), value, ret); |
| } else { |
| //setEcallAudioPathOn(false); |
| ret = get_mixer_ctrl_value_int(g_mixer_name); |
| RLOGD("mixer_set(get_mixer_ctrl_value_int: %s) = %d", g_mixer_name, ret); |
| if(ret == 0) { |
| ret = set_mixer_ctrl_value_int(g_mixer_name, value); |
| RLOGD("mixer_set(%s) = %d", g_mixer_name, ret); |
| } else { |
| ret = set_mixer_ctrl_value_int(g_mixer_name_ecall, value); |
| RLOGD("mixer_set(%s) = %d", g_mixer_name_ecall, ret); |
| } |
| } |
| |
| |
| return ret; |
| } |
| int mixer_reset_set(int value ) |
| { |
| int ret; |
| |
| // set mixer to reset:1 |
| ret = set_mixer_ctrl_value_int(g_mixer_reset_name, value); |
| RLOGD("mixer_reset_set(%s) = %d", g_mixer_reset_name, ret); |
| return ret; |
| } |
| int bt_mixer_set(int value) |
| { |
| int ret; |
| |
| //set mixer ctrl to on:1 or off:0 |
| // bt speech |
| int bt_has_ecnr = get_bt_has_ecnr(); |
| int bt_wbs = get_bt_wbs(); |
| ret = set_mixer_ctrl_value_int(g_bt_has_ecnr_name, bt_has_ecnr); |
| ret = set_mixer_ctrl_value_int(g_bt_wbs_name, bt_wbs); |
| ret = set_mixer_ctrl_value_int(g_mixer_name_bt, value); |
| |
| if (ret) |
| RLOGE("set_mixer_ctrl_value_int err: %d", ret); |
| return ret; |
| } |
| |
| int mixer_check(int mix) |
| { |
| int ret; |
| |
| if (mix == 0) { |
| ret = get_mixer_ctrl_value_int(g_mixer_name); |
| } else if (mix == 1){ |
| ret = get_mixer_ctrl_value_int(g_mixer_name_bt); |
| } else { |
| RLOGE("mixer_check wrong mix %d", mix); |
| } |
| RLOGD("The ctrl \"%s\" is set to %d ", g_mixer_name, ret); |
| return ret; |
| } |
| int mixer_set_volume(int value) |
| { |
| int ret; |
| if (get_audio_path() == 0) { |
| ret = set_mixer_ctrl_volume_value(g_mixer_name_volume, value); |
| } else { |
| ret = set_mixer_ctrl_volume_value(g_mixer_name_volume_bt, value); |
| } |
| if (ret) |
| RLOGE("set_mixer_ctrl_volume_value_int err: %d", ret); |
| return ret; |
| } |
| long int mixer_get_volume() |
| { |
| long int vol_value; |
| if (get_audio_path() == 0) { |
| vol_value = get_mixer_ctrl_volume_value(g_mixer_name_volume); |
| } else { |
| vol_value = get_mixer_ctrl_volume_value(g_mixer_name_volume_bt); |
| } |
| RLOGD("The ctrl \"%s\" is set to %d", g_mixer_name_volume, vol_value); |
| return vol_value; |
| } |
| |
| GstElement *pipeline_element; |
| GstState gst_cur_state = GST_STATE_NULL; |
| static int gst_status = 0; |
| |
| int GSM_Init(char* filepath) |
| { |
| GstElement *pipeline, *source, *mux, *encoder, *sink; |
| RLOGD("[GSM]GSM Init Start!"); |
| /* Initialisation */ |
| gst_init (NULL, NULL); |
| |
| pipeline = gst_pipeline_new ("3gppmux-test"); |
| source = gst_element_factory_make ("pulsesrc", "file-source"); |
| encoder = gst_element_factory_make ("faac", "encoder"); |
| mux = gst_element_factory_make ("3gppmux", "muxer"); |
| sink = gst_element_factory_make ("filesink", "output"); |
| |
| g_object_set(mux, "fragment-duration", 100, NULL); |
| g_object_set(sink, "location", filepath, NULL); |
| |
| if (!pipeline || !source || !encoder || !mux || !sink) { |
| if(pipeline) { |
| gst_object_unref (GST_OBJECT (pipeline)); |
| pipeline = NULL; |
| } |
| if(source) { |
| gst_object_unref (GST_OBJECT (source)); |
| source = NULL; |
| } |
| if(encoder) { |
| gst_object_unref (GST_OBJECT (encoder)); |
| encoder = NULL; |
| } |
| if(mux) { |
| gst_object_unref (GST_OBJECT (mux)); |
| mux = NULL; |
| } |
| if(sink) { |
| gst_object_unref (GST_OBJECT (sink)); |
| sink = NULL; |
| } |
| RLOGE ("[GSM]One element could not be created. Exiting"); |
| return -1; |
| } |
| |
| gst_bin_add_many (GST_BIN (pipeline), source, encoder, mux, sink, NULL); |
| gst_element_link_many (source, encoder, mux, sink, NULL); |
| |
| pipeline_element = pipeline; |
| gst_status = 1; //initial done |
| RLOGD("[GSM]GSM Init Done!"); |
| return 0; |
| } |
| |
| int GSM_Start(void) |
| { |
| RLOGD("[GSM]GSM Start start!"); |
| if(gst_status == 2) |
| return 0; |
| |
| if(gst_status == 1 || gst_status ==3) { |
| GstStateChangeReturn ret = gst_element_set_state (pipeline_element, GST_STATE_PLAYING); |
| |
| RLOGD("[GSM]Running... return: %d", ret); |
| //g_main_loop_run (gst_loop); |
| gst_status = 2; //start done |
| } else { |
| return -1; |
| } |
| RLOGD("[GSM]GSM Start End!"); |
| return 0; |
| } |
| |
| int GSM_Stop() |
| { |
| RLOGD("[GSM]GSM Stop Start!"); |
| if (gst_status == 4) |
| return 0; |
| |
| if(gst_status == 2 || gst_status == 3) { |
| /* Out of the main loop, clean up nicely */ |
| gboolean isSend = gst_element_send_event (pipeline_element, gst_event_new_eos ()); |
| GstStateChangeReturn ret = gst_element_set_state (pipeline_element, GST_STATE_NULL); |
| RLOGD("[GSM]Returned, stopping playback. ret: %d, isSend: %d", ret, isSend); |
| gst_status = 4; |
| } else { |
| return -1; |
| } |
| RLOGD("[GSM]GSM Stop End!"); |
| return 0; |
| } |
| |
| int GSM_Close() |
| { |
| RLOGD("[GSM]Deleting pipeline"); |
| gst_object_unref (GST_OBJECT (pipeline_element)); |
| gst_deinit (); |
| gst_status = 0; |
| RLOGD("[GSM]GSM Close Done!"); |
| return 0; |
| } |
| /*cmd:1, address, |
| *2, clirMode, |
| *3, if present, uusinfo.type |
| *4, as above, uusinfo.Dcs |
| *5, as above, uusinfo.userdatalength |
| *6, as above, uusinfo.UserData |
| */ |
| //RIL_REQUEST_DIAL |
| int dial(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| |
| if (argc < 3 || argv[1]==NULL) { |
| //add log msg |
| free(pRI); |
| return -1; |
| } |
| //address; |
| writeStringToParcel(p, (const char *)argv[1]); |
| //clirMode |
| if (argc >=2) { |
| p.writeInt32(atoi(argv[2])); |
| |
| if (argc == 7 && argv[3] != NULL |
| && argv[4] != NULL && argv[5] != NULL |
| && argv[6] != NULL ) { |
| p.writeInt32(1); // UUS information is present |
| p.writeInt32(atoi(argv[3])); |
| p.writeInt32(atoi(argv[4])); |
| p.writeByteArray((size_t)atoi(argv[5]),(uint8_t*)argv[6]); |
| } else { |
| p.writeInt32(0); // UUS information is absent |
| } |
| } |
| p.setDataPosition(pos); |
| setEcallAudioPathOn(false); |
| pRI->pCI->dispatchFunction(p, pRI); |
| inCallstatus = CALL_ON; |
| return 0; |
| } |
| #if 0 //not need user setup |
| //RIL_REQUEST_OEM_HOOK_STRINGS |
| int invokeOemRilRequestStrings(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| RLOGD("OEM_HOOK_STRINGS: p1->\"%s\",p2->\"%s\"",argv[1],argv[2]); |
| p.writeInt32(2); |
| writeStringToParcel(p, (const char *)argv[1]); |
| writeStringToParcel(p, "\"\"");//(const char *)argv[2]); |
| p.setDataPosition(pos); |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| #endif |
| |
| extern void ARspRequest (int request,RIL_SOCKET_ID socket_id); |
| //RIL_REQUEST_SET_AUDIO_PATH |
| /*cmd:1, speech mode, |
| *2, bt_has_ecnr |
| *3, bt_wbs |
| */ |
| int setAudioPath(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| if (argc < 1) { |
| free(pRI); |
| RLOGE("set bt mode need bt_has_encr and bt_wbs"); |
| return -1; |
| } |
| |
| int temp_audio_path = atoi(argv[1]); |
| int bt_has_ecnr; |
| int bt_wbs; |
| int current_audio_path = get_audio_path(); |
| RLOGD("setAudioPath enter"); |
| if ((temp_audio_path != 0) && (temp_audio_path != 1)) { |
| RLOGE("audio path illegal %d, only support 0 and 1", temp_audio_path); |
| return -1; |
| } |
| set_audio_path(temp_audio_path); |
| RLOGD("set audio path to %d, current audio path is %d", temp_audio_path, current_audio_path); |
| if (temp_audio_path == 1) { |
| /* bt speech need BT_HAS_ECNR and BT_WBS */ |
| bt_has_ecnr = atoi(argv[2]); |
| bt_wbs = atoi(argv[3]); |
| set_bt_has_ecnr(bt_has_ecnr); |
| set_bt_wbs(bt_wbs); |
| RLOGD("set bt_has_ecnr %d, bt_wbs %d", bt_has_ecnr, bt_wbs); |
| } |
| if ((current_audio_path != temp_audio_path) |
| && (get_call_status() == CALL_ON)) { |
| if (current_audio_path == 0) { |
| if (getSpeechStatus() == NORMAL_SPEECH_ON) { |
| RLOGD("normal speech off then bt speech on"); |
| mixer_set(0); |
| setSpeechAndStatus(2); |
| } |
| } else { |
| if (getSpeechStatus() == BT_SPEECH_ON) { |
| RLOGD("bt speech off then normal speech on"); |
| bt_mixer_set(0); |
| setSpeechAndStatus(1); |
| } |
| } |
| } |
| if (pRI != NULL) { |
| free(pRI); |
| } |
| |
| RLOGD("setAudioPath done"); |
| return 0; |
| } |
| |
| |
| //RIL_REQUEST_HANGUP |
| int hangupConnection(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| |
| p.writeInt32(1); |
| p.writeInt32(atoi(argv[1])); |
| p.setDataPosition(pos); |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| |
| //RIL_REQUEST_FORCE_RELEASE_CALL |
| int forceReleaseCall(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| |
| p.writeInt32(1); |
| p.writeInt32(atoi(argv[1])); |
| p.setDataPosition(pos); |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| |
| //RIL_REQUEST_SEPARATE_CONNECTION |
| int separateConnection(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| |
| p.writeInt32(1); |
| p.writeInt32(atoi(argv[1])); |
| p.setDataPosition(pos); |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_DTMF |
| //RIL_REQUEST_DTMF_START |
| int sendDtmf(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| int number; |
| size_t pos = p.dataPosition(); |
| char * c_num = NULL; |
| |
| c_num = argv[1]; |
| if (c_num == NULL) { |
| free(pRI); |
| return -1; |
| } |
| number = int(c_num[0] - '0'); |
| if(number == -6) |
| number = 10; |
| if(number == -13) |
| number = 11; |
| RLOGD("DTMF input number is %s-->%d",c_num,number); |
| if ( number < 0 || number > 15 ) { |
| RLOGE("DTMF input number error"); |
| free(pRI); |
| return -1; |
| } |
| |
| writeStringToParcel(p, (const char *)argv[1]); |
| p.setDataPosition(pos); |
| |
| dtmf_stop(dtmf_handle); |
| gint time_ms = 500; |
| if (pRI->pCI->requestNumber == RIL_REQUEST_DTMF_START) { |
| time_ms = 0; |
| } |
| RLOGD("request: %d, time_ms = %d", pRI->pCI->requestNumber, time_ms); |
| dtmf_handle = dtmf_start(number, time_ms, dtmf_volume, NULL); |
| pRI->pCI->dispatchFunction(p, pRI); |
| if (dtmf_handle == NULL) |
| RLOGE("[DTMF] dtmf_start return NULL!"); |
| return 0; |
| } |
| |
| //RIL_REQUEST_UDUB |
| int rejectCall(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_ANSWER |
| int acceptCall(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| inCallstatus = CALL_ON; |
| return 0; |
| } |
| |
| //RIL_REQUEST_HANGUP_ALL |
| int hangupAll(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| |
| //RIL_REQUEST_CONFERENCE |
| int conference(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND |
| int hangupWaitingOrBackground(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE |
| int switchWaitingOrHoldingAndActive(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND |
| int hangupForegroundResumeBackground(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_EXPLICIT_CALL_TRANSFER |
| int explicitCallTransfer(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| |
| //RIL_REQUEST_ADD_IMS_CONFERENCE_CALL_MEMBER |
| int addImsConferenceCallMember(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| |
| p.writeInt32(3); |
| writeStringToParcel(p, (const char *)argv[1]);//confCallId |
| writeStringToParcel(p, (const char *)argv[2]);//address |
| writeStringToParcel(p, (const char *)argv[3]);//CallIdToAdd |
| |
| p.setDataPosition(pos); |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_REMOVE_IMS_CONFERENCE_CALL_MEMBER |
| int removeImsConferenceCallMember(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| |
| p.writeInt32(3); |
| writeStringToParcel(p, (const char *)argv[1]);//confCallId |
| writeStringToParcel(p, (const char *)argv[2]);//address |
| writeStringToParcel(p, (const char *)argv[3]);//CallIdToRemove |
| |
| p.setDataPosition(pos); |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_CONFERENCE_DIAL |
| //argv[1]:DialMethod |
| //argv[2]:ParticipantsNumber |
| //argv[2+ParticipantsNumber]:addresss |
| //argv[2+ParticipantsNumber+1]:clir |
| int conferenceDial(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| int ParticipantsNumber,i; |
| |
| if( argc < 3 ) { |
| free(pRI); |
| RLOGE("Error: conference Dial parameter is error!"); |
| return -1; |
| } |
| |
| ParticipantsNumber = atoi(argv[2]); |
| |
| if( argc < (ParticipantsNumber+3) ) { |
| free(pRI); |
| RLOGE("Error: Dial With SIP URI parameter is error! \ |
| argc is %d, and need parameter %d",argc,(ParticipantsNumber+3)); |
| return -1; |
| } |
| |
| p.writeInt32((ParticipantsNumber+3)); |
| writeStringToParcel(p, (const char *)argv[1]); //DialMethod |
| writeStringToParcel(p, (const char *)argv[2]); //ParticipantsNumber |
| for( i=0; i<ParticipantsNumber; i++ ){ //address |
| writeStringToParcel(p, (const char *)argv[3+i]); |
| } |
| writeStringToParcel(p, (const char *)argv[3+ParticipantsNumber]);//clir |
| |
| p.setDataPosition(pos); |
| setEcallAudioPathOn(false); |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_DIAL_WITH_SIP_URI |
| int dialWithSipUri(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| |
| if (argc < 3 || argv[1]==NULL) { |
| free(pRI); |
| return -1; |
| } |
| |
| writeStringToParcel(p, (const char *)argv[1]);//address |
| /* for compatibility of test script, still receive clirMode and UUS, |
| but don't send them to libvendor-ril */ |
| #if 0 |
| p.writeInt32(atoi(argv[2]));//clirMode |
| p.writeInt32(0); // UUS information is absent |
| #endif |
| |
| p.setDataPosition(pos); |
| setEcallAudioPathOn(false); |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_HOLD_CALL |
| int holdCall(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| |
| if (argc < 2 || argv[1]==NULL) { |
| free(pRI); |
| return -1; |
| } |
| |
| //callIDToHold |
| p.writeInt32(1); |
| p.writeInt32(atoi(argv[1])); |
| |
| p.setDataPosition(pos); |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_RESUME_CALL |
| int resumeCall(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| |
| if (argc < 2 || argv[1]==NULL) { |
| free(pRI); |
| return -1; |
| } |
| |
| //callIDToResume |
| p.writeInt32(1); |
| p.writeInt32(atoi(argv[1])); |
| |
| p.setDataPosition(pos); |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| int getCurrentCalls(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| int autoAnswerCall(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| if(argc < 2) { |
| RLOGW("[error],set auto answer call parameter error!"); |
| free(pRI); |
| return 0; |
| } |
| //need add lock to pretect. |
| autoAnswerMode = atoi(argv[1]) ? 1 : 0; |
| RLOGD("SetAutoAnserMode is %s",autoAnswerMode ? "On" :"Off"); |
| if(pRI) { |
| free(pRI); |
| } |
| return 0; |
| } |
| |
| int inCallRecord(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| int recordEnable = 0; |
| char* filepath = NULL; |
| if(inCallstatus == CALL_OFF || speechStatus == SPEECH_OFF) { |
| RLOGW("[warning],not in calling status. Can't do record!"); |
| return 0; |
| } |
| |
| if(argc < 3) { |
| free(pRI); |
| RLOGW("[error],inCallRecord parameter error!"); |
| return 0; |
| } |
| |
| recordEnable = atoi(argv[1]) ? 1 : 0; |
| RLOGD("InCall record %s!",recordEnable ? "enable" : "disable"); |
| filepath = argv[2]; |
| RLOGD("InCall record file path as \'%s\'",filepath); |
| |
| if (recordEnable == 1) {//enable record |
| RLOGD("start GSM!"); |
| if(-1 != GSM_Init(filepath) && -1 != GSM_Start()) { |
| inCallRecordMode = 1; |
| RLOGW("inCallRecord Start OK!"); |
| }else{ |
| inCallRecordMode = 0; |
| RLOGW("[error],inCallRecord Start fail!"); |
| } |
| } else { //disable record |
| if (inCallRecordMode == 1) { |
| if(!(-1 != GSM_Stop() && -1 != GSM_Close())) |
| RLOGW("[error],inCallRecord fail!"); |
| |
| inCallRecordMode = 0; |
| } |
| } |
| |
| if(pRI != NULL) { |
| free(pRI); |
| } |
| return 0; |
| } |
| |
| int StopRecord() |
| { |
| RLOGD("After Handup, stop record! Before Record is %s",inCallRecordMode ? "Enable" : "Disable"); |
| if (inCallRecordMode == 1) { |
| if(!(-1 != GSM_Stop() && -1 != GSM_Close())) |
| RLOGW("[error],inCallRecord fail!"); |
| |
| inCallRecordMode = 0; |
| /*From GSM report stop_record to PulseAudio send record_off need 15ms. so after stop record delay 30ms*/ |
| usleep(30*1000); |
| } |
| return 0; |
| } |
| |
| int setSpeechVolume(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| int setValue = 0; |
| RLOGD("setSpeechVolume start!"); |
| |
| if(argc < 2) { |
| free(pRI); |
| RLOGW("Warning: no set volume value!"); |
| return -1; |
| } |
| |
| setValue = atoi(argv[1]); |
| RLOGD("set Speech Volume value is %d!",setValue); |
| if (get_audio_path() == 0) { |
| if(setValue < MIN_VOLUME || setValue > MAX_VOLUME) { |
| RLOGW("Warning: set volume value is over-range!"); |
| return -1; |
| } |
| } else { |
| if(setValue < BT_MIN_VOLUME || setValue > BT_MAX_VOLUME) { |
| RLOGW("Warning: set bt volume value is over-range!"); |
| return -1; |
| } |
| } |
| //paramter is from 1 to 7 |
| mixer_set_volume(setValue); |
| free(pRI); |
| return 0; |
| } |
| int setDtmfVolume(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| int setValue = 0; |
| RLOGD("setDtmfVolume start!"); |
| |
| if(argc < 2) { |
| RLOGW("Warning: no set volume value!"); |
| free(pRI); |
| return -1; |
| } |
| |
| setValue = atoi(argv[1]); |
| RLOGD("set dtmf Volume value is %d!",setValue); |
| if(setValue < DTMF_MIN_VOLUME || setValue > DTMF_MAX_VOLUME) { |
| RLOGW("Warning: set volume value is over-range!"); |
| free(pRI); |
| return -1; |
| } |
| //paramter is from 0 to 36 |
| dtmf_volume = setValue; |
| |
| free(pRI); |
| return 0; |
| } |
| |
| speech_status getSpeechStatus() |
| { |
| return speechStatus; |
| } |
| |
| void setSpeechAndStatus(int value) |
| { |
| RLOGD("setSpeechAndStatus value: %d, speechStatus: %d", value, speechStatus); |
| if (value == 1) { |
| speechStatus = NORMAL_SPEECH_ON; |
| mixer_set(1); |
| } else if (value == 2) { |
| speechStatus = BT_SPEECH_ON; |
| bt_mixer_set(1); |
| } else if (value == 0) { |
| speechStatus == BT_SPEECH_ON ? bt_mixer_set(0) : mixer_set(0); |
| speechStatus = SPEECH_OFF; |
| } else { |
| RLOGE("set speech value is invaild!\n"); |
| } |
| } |
| //RIL_REQUEST_EMERGENCY_DIAL |
| /*cmd:1, address, |
| *2, clirMode, |
| *3, if present, uusinfo.type |
| *4, as above, uusinfo.Dcs |
| *5, as above, uusinfo.userdatalength |
| *6, as above, uusinfo.UserData |
| */ |
| int emergencyDial(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| |
| if (argc < 3 || argv[1] == NULL) |
| { |
| //add log msg |
| free(pRI); |
| return -1; |
| } |
| //address; |
| writeStringToParcel(p, (const char *) argv[1]); |
| //clirMode |
| if (argc >= 2) |
| { |
| p.writeInt32(atoi(argv[2])); |
| |
| if (argc == 7&& argv[3] != NULL |
| && argv[4] != NULL && argv[5] != NULL |
| && argv[6] != NULL) |
| { |
| p.writeInt32(1); // UUS information is present |
| p.writeInt32(atoi(argv[3])); |
| p.writeInt32(atoi(argv[4])); |
| p.writeByteArray((size_t) atoi(argv[5]), (uint8_t*) argv[6]); |
| } else |
| { |
| p.writeInt32(0); // UUS information is absent |
| } |
| } |
| p.setDataPosition(pos); |
| setEcallAudioPathOn(false); |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_SET_ECC_SERVICE_CATEGORY |
| int setEccServiceCategory(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| |
| //if ( getSpeechStatus() != 1) |
| // setSpeechAndStatus(1); |
| |
| p.writeInt32(1); |
| p.writeInt32(atoi(argv[1])); |
| p.setDataPosition(pos); |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| //RIL_REQUEST_SET_ECC_LIST |
| /* argv[1]: list number |
| argv[2+i]: ECC string |
| argv[3+i]: Categroy |
| argv[4+i]: Conditon |
| */ |
| int setEccList(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| int num = 0; |
| //if ( getSpeechStatus() != 1) |
| // setSpeechAndStatus(1); |
| if(argc < 3) { |
| RLOGE("%s parameter error!",__func__); |
| free(pRI); |
| return -1; |
| } |
| num = atoi(argv[1]); |
| RLOGD("list number is %d, argc is %d",num, argc); |
| if((num == 0) || ((argc-2) < num*3)) { |
| RLOGE("%s parameter error!",__func__); |
| free(pRI); |
| return -1; |
| } |
| |
| p.writeInt32(num*3); |
| for(int i = 0; i < num; i++){ |
| writeStringToParcel(p, (const char *)argv[2+i*3+0]); //ECC |
| writeStringToParcel(p, (const char *)argv[2+i*3+1]); //Category |
| writeStringToParcel(p, (const char *)argv[2+i*3+2]); //Condition |
| RLOGD("list[%d],ECC is %s, Category is %s, Condition is %s!",i+1,argv[2+i*3+0],argv[2+i*3+1],argv[2+i*3+2]); |
| } |
| p.setDataPosition(pos); |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| |
| //RIL_REQUEST_SET_ECC_NUM |
| int setEccNum(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| int num = 0; |
| |
| if(argc < 2 || argc > 3) { |
| RLOGE("%s parameter error!",__func__); |
| free(pRI); |
| return -1; |
| } |
| |
| num = (argc > 2)?2:1; |
| |
| p.writeInt32(num); |
| writeStringToParcel(p, (const char *)argv[1]); //ECC number with card |
| RLOGD("Set ECC number with card: %s",argv[1]); |
| if (num>1){ |
| writeStringToParcel(p, (const char *)argv[2]); //ECC number without card |
| RLOGD("Set ECC number without card: %s",argv[2]); |
| } |
| p.setDataPosition(pos); |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| |
| //RIL_REQUEST_GET_ECC_NUM |
| int getEccNum(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| |
| int handleECCNumResponse(const void *data, int datalen, RIL_SOCKET_ID socket_id){ |
| if (data == NULL || datalen <= 0){ |
| RLOGE("%s parameter error!",__func__); |
| return -1; |
| } |
| |
| printf("[ECC NUM][Slot%d] %s\n", socket_id, (const char*)data); |
| RLOGD("[ECC NUM][Slot%d] %s\n", socket_id, (const char*)data); |
| return 0; |
| } |
| |
| |
| //RIL_REQUEST_LAST_CALL_FAIL_CAUSE |
| int getLastCallFailCause(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) { |
| if(argc != 1) |
| { |
| RLOGD("the peremeters numbers isn't right , so return"); |
| free(pRI); |
| return -1; |
| } |
| RLOGD("getLastCallFailCause %d: " , pRI->pCI->requestNumber); |
| android::Parcel p; |
| |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| |
| #ifdef C2K_SUPPORT |
| static bool is12Key(char c) { |
| return (c >= '0' && c <= '9') || c == '*' || c == '#'; |
| } |
| |
| //RIL_REQUEST_CDMA_BURST_DTMF |
| int sendBurstDtmf(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI){ |
| if(argc < 4) { |
| RLOGE("%s parameter error!",__func__); |
| free(pRI); |
| return -1; |
| } |
| int number; |
| char * c_num = NULL; |
| |
| c_num = argv[1]; |
| if (c_num == NULL) { |
| free(pRI); |
| return -1; |
| } |
| number = int(c_num[0] - '0'); |
| if(number == -6) |
| number = 10; |
| if(number == -13) |
| number = 11; |
| RLOGD("DTMF input number is %s-->%d",c_num,number); |
| if ( number < 0 || number > 15 ) { |
| RLOGE("DTMF input number error"); |
| free(pRI); |
| return -1; |
| } |
| dtmf_stop(dtmf_handle); |
| dtmf_handle = dtmf_start(number, 500, dtmf_volume, NULL); |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| p.writeInt32(3); |
| writeStringToParcel(p, c_num); |
| writeStringToParcel(p, argv[2]); |
| writeStringToParcel(p, argv[3]); |
| p.setDataPosition(pos); |
| pRI->pCI->dispatchFunction(p, pRI); |
| if (dtmf_handle == NULL) |
| RLOGE("[DTMF] dtmf_start return NULL!"); |
| return 0; |
| } |
| |
| //RIL_REQUEST_CDMA_FLASH |
| int sendCDMAFeatureCode(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI){ |
| if(argc > 2) |
| { |
| RLOGD("the peremeters numbers isn't right , so return"); |
| free(pRI); |
| return -1; |
| } |
| android::Parcel p; |
| size_t pos = p.dataPosition(); |
| writeStringToParcel(p, ((argc == 1) ? "" : argv[1])); |
| p.setDataPosition(pos); |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |
| #endif /*C2K_SUPPORT*/ |
| |
| static int mixer_set_mute(int path, int value) |
| { |
| RLOGD("mixer_set_mute path: %d , value: %d", path, value); |
| int ret; |
| /* DL:0 UL:1 */ |
| if (path == 0) { |
| ret = set_mixer_ctrl_value_int(g_DL_mute_name, value); |
| } else { |
| ret = set_mixer_ctrl_value_int(g_UL_mute_name, value); |
| } |
| if (ret) { |
| RLOGE("set_mixer_ctrl_volume_value_int err: %d", ret); |
| } |
| return ret; |
| } |
| |
| static long int mixer_get_mute(int path) |
| { |
| long int is_mute; |
| |
| /* DL:0 UL:1 */ |
| if (path == 0) { |
| is_mute = get_mixer_ctrl_value_int(g_DL_mute_name); |
| RLOGD("The ctrl \"%s\" is set to %d", g_DL_mute_name, is_mute); |
| } else { |
| is_mute = get_mixer_ctrl_value_int(g_UL_mute_name); |
| RLOGD("The ctrl \"%s\" is set to %d", g_UL_mute_name, is_mute); |
| } |
| |
| return is_mute; |
| } |
| |
| int setCallMute(bool mute) { |
| RLOGD("setCallMute: %d", mute); |
| return mixer_set_mute(1, (mute ? 1: 0)); |
| } |
| |
| int getCallMute() { |
| long int cc_mute = mixer_get_mute(1); |
| RLOGD("getCallMute: %d", cc_mute); |
| return cc_mute; |
| } |
| |
| void resetMute() { |
| if (getCallMute() > 0) { |
| setCallMute(false); |
| } |
| } |
| |
| void callRing(RIL_SOCKET_ID soc_id) |
| { |
| resetMute(); |
| if (autoAnswerMode) { |
| RLOGD("Auto Answer MT Call!"); |
| android::requestAnswer(soc_id); |
| } |
| return; |
| } |
| |
| void autoAnswerForCdma(RIL_SOCKET_ID socket_id) |
| { |
| resetMute(); |
| if (autoAnswerMode) { |
| RLOGD("Auto Answer MT Call for cdma"); |
| ARspRequest(RIL_REQUEST_CDMA_FLASH, socket_id); |
| } |
| return; |
| } |
| |
| //void callStateChange(void) |
| void speechonoff(int callnum) |
| { |
| static int callIndex = 0; |
| RLOGD("callnum = %d, Call State Change then judge speech on/off!", callnum); |
| callIndex = callnum; |
| if( callIndex == 1 && speechStatus == SPEECH_OFF) { //speech on |
| //RLOGD("DemoAPP Call shell command (pactl set-card-profile 0 phonecall)"); |
| //system("pactl set-card-profile 0 phonecall"); |
| //RLOGD("DemoAPP Call shell command end"); |
| if (get_audio_path() == 0) { |
| mixer_set(1); |
| speechStatus = NORMAL_SPEECH_ON; |
| } else { |
| bt_mixer_set(1); |
| speechStatus = BT_SPEECH_ON; |
| } |
| inCallstatus = CALL_ON; |
| RLOGD("[speech]: set on"); |
| sendCallMsg(true); //for Power Manager test |
| } else if (callIndex == 0 |
| && (speechStatus == NORMAL_SPEECH_ON |
| || speechStatus == BT_SPEECH_ON)) { //speech off |
| StopRecord(); |
| sendCallMsg(false); // for Power Manager test. |
| dtmf_stop(dtmf_handle); |
| if (speechStatus == NORMAL_SPEECH_ON) { |
| mixer_set(0); |
| } else { |
| bt_mixer_set(0); |
| } |
| //RLOGD("DemoAPP Call shell command (pactl set-card-profile 0 HiFi)"); |
| //system("pactl set-card-profile 0 HiFi"); |
| //RLOGD("DemoAPP Call(pactl set-card-profile 0 HiFi) command end"); |
| speechStatus = SPEECH_OFF; |
| inCallstatus = CALL_OFF; |
| resetMute(); |
| RLOGD("[speech]: set off"); |
| } else { |
| RLOGD("callIndex is %d, speechStatus is %d.",callIndex, speechStatus); |
| } |
| |
| return; |
| } |
| |
| //RIL_REQUEST_SET_MUTE |
| int setMute(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| if(pRI) { |
| free(pRI); |
| } |
| bool mute = (atoi(argv[1]) > 0) ? true: false; |
| RLOGD("set mute %s", ((atoi(argv[1]) > 0) ? "on": "off")); |
| int ret = setCallMute(mute); |
| std::string str; |
| if(ret) { |
| str.append("set mute fail, please try agian\n"); |
| } else { |
| str.append("set mute "); |
| str.append((atoi(argv[1]) > 0) ? "on ": "off "); |
| str.append("success\n"); |
| } |
| android::emResultNotify(str.c_str()); |
| return 0; |
| } |
| |
| //RIL_REQUEST_GET_MUTE |
| int getMute(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| if(pRI) { |
| free(pRI); |
| } |
| std::string str; |
| int mute = getCallMute(); |
| //TBC -200 fail status |
| if(mute == -200) { |
| str.append("get mute state fail, please check whether does call exsit. \n"); |
| } else { |
| str.append("current mute state is "); |
| str.append((mute == 1) ? "on\n" : "off\n"); |
| } |
| android::emResultNotify(str.c_str()); |
| return 0; |
| } |
| |
| //RIL_UNSOL_SIP_CALL_PROGRESS_INDICATOR |
| int handleUnsolSipCallProgressInd(const void *response, size_t responselen) { |
| if (response == NULL && responselen != 0) { |
| RLOGE("handleUnsolSipCallProgressInd: invalid response: NULL"); |
| return -1; |
| } |
| if (responselen % sizeof(char *) != 0) { |
| RLOGE("handleUnsolSipCallProgressInd: invalid response length %d expected multiple of %d\n", |
| (int)responselen, (int)sizeof(char *)); |
| return -1; |
| } |
| |
| int numStrings = responselen / sizeof(char *); |
| RLOGD("handleUnsolSipCallProgressInd: numStrings: %d", numStrings); |
| if(numStrings < 6) { |
| RLOGE("handleUnsolSipCallProgressInd: invalid response numbers: NULL"); |
| return -1; |
| } |
| char **p_cur = (char **) response; |
| //<call_id>,<dir>,<SIP_msg_type>,<method>,<response_code>,"<reason_text>" |
| //if response == <id>, 1, 0, 4, 0, "call completed elsewhere" ,printf "SIP CANCEL:Call completed elsewhere" |
| //if response == <id>, 1, 0, 4, 0, " declined" ,printf "SIP CANCEL:declined" |
| std::string call_id(p_cur[0]); |
| std::string dir(p_cur[1]); |
| std::string sip_msg_type(p_cur[2]); |
| std::string method(p_cur[3]); |
| std::string resp_code(p_cur[4]); |
| std::string reason_text(p_cur[5]); |
| RLOGD("%s, call_id=%s, dir=%s, sip_msg_type=%s, method=%s, resp_code=%s, reason_text=%s", |
| __FUNCTION__, call_id.c_str(),dir.c_str(),sip_msg_type.c_str(),method.c_str(),resp_code.c_str(), reason_text.c_str()); |
| printf("call_id=%s, dir=%s, sip_msg_type=%s, method=%s, resp_code=%s, reason_text=%s\n", |
| call_id.c_str(),dir.c_str(),sip_msg_type.c_str(),method.c_str(),resp_code.c_str(), reason_text.c_str()); |
| |
| if ((std::stoi(dir) == 1) && (std::stoi(sip_msg_type) == 0) |
| && (std::stoi(method) == 4) && (std::stoi(resp_code) == 0)) { |
| std::string msg("SIP CANCEL:"); |
| msg.append(reason_text); |
| printf("%s", msg.c_str()); |
| } |
| return 0; |
| } |
| |
| //RIL_UNSOL_CALL_INFO_INDICATION |
| int handleUnsolCallInfoInd(const void *response, size_t responselen, RIL_SOCKET_ID socket_id) { |
| int numStrings = 0; |
| |
| if (response == NULL && responselen != 0) { |
| RLOGE("[slot%d]handleUnsolCallInfoInd, invalid response: NULL", socket_id); |
| return -1; |
| } |
| if (responselen % sizeof(char *) != 0) { |
| RLOGE("[slot%d]handleUnsolCallInfoInd: invalid response length %d expected multiple of %d\n",socket_id, |
| (int)responselen, (int)sizeof(char *)); |
| return -1; |
| } |
| |
| if (response == NULL) { |
| RLOGE("[slot%d]handleUnsolCallInfoInd, length and invalid response : NULL", socket_id); |
| } else { |
| char **p_cur = (char **) response; |
| |
| numStrings = responselen / sizeof(char *); |
| RLOGD("[slot%d]handleUnsolCallInfoInd: numStrings: %d",socket_id, numStrings); |
| if(numStrings < 9) { |
| RLOGE("[slot%d]handleUnsolCallInfoInd, invalid numStrings(%d) < 9, no pau value : numStrings", socket_id); |
| return -1; |
| } else { |
| RLOGD("[slot%d]handleUnsolCallInfoInd(): pau: %s", socket_id, p_cur[8]); |
| printf("[slot%d]handleUnsolCallInfoInd(): pau: %s\n", socket_id, p_cur[8]); |
| } |
| } |
| return 0; |
| } |
| |
| static void playtone(int start) { |
| RLOGD("playtone(): start: %d, isRingStart %d", start, isRingStart); |
| char cmd[256]; |
| sprintf(cmd, "aplay %s", RING_PATH); |
| system(cmd); |
| isRingStart = false; |
| } |
| |
| //RIL_UNSOL_RINGBACK_TONE |
| int handleRingbackTone(const void *response, size_t responselen, RIL_SOCKET_ID socket_id) { |
| |
| int numInts = 0; |
| |
| if (response == NULL && responselen != 0) { |
| RLOGE("[slot%d]handleRingbackTone, invalid response: NULL", socket_id); |
| return -1; |
| } |
| if (responselen % sizeof(int) != 0) { |
| RLOGE("[slot%d]handleRingbackTone: invalid response length %d expected multiple of %d\n",socket_id, |
| (int)responselen, (int)sizeof(char *)); |
| return -1; |
| } |
| |
| int *p_int = (int *) response; |
| |
| numInts = responselen / sizeof(int); |
| RLOGD("[slot%d]handleRingbackTone: numInts: %d",socket_id, numInts); |
| if(numInts < 1) { |
| RLOGE("[slot%d]handleRingbackTone, invalid numStrings(%d) < 1", socket_id); |
| return -1; |
| } else { |
| int start = p_int[0]; |
| RLOGD("[slot%d]handleRingbackTone(): start: %d, isRingStart %d", socket_id, start, isRingStart); |
| printf("[slot%d]handleRingbackTone(): start: %d, isRingStart %d\n", socket_id, start, isRingStart); |
| #if defined(TARGET_PLATFORM_MT2731) |
| if(start && (!isRingStart)) { |
| isRingStart = true; |
| std::thread t(playtone, start); |
| t.detach(); |
| } else if((!start) && isRingStart) { |
| isRingStart = false; |
| system("kill $(ps aux | grep '[a]play' | awk '{print $2}')"); |
| } |
| #endif |
| } |
| return 0; |
| } |
| |
| //RIL_REQUEST_DTMF_STOP |
| int stopDtmf(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) |
| { |
| android::Parcel p; |
| |
| dtmf_stop(dtmf_handle); |
| pRI->pCI->dispatchFunction(p, pRI); |
| return 0; |
| } |