| /** |
| * \file ql_call.c |
| * \brief A Documented file. |
| * |
| * Detailed description |
| * \Author: js.wang<js.wang@mobiletek.cn> |
| * \Version: 1.0.0 |
| * \Date: 2022-01-18 |
| */ |
| #include "ql/ql_mcm_call.h" |
| #include <telephony/ril.h> |
| #include <telephony/ril_ext.h> |
| #include "ql/ql_mcm.h" |
| #include "rilutil.h" |
| #include "mbtk_log.h" |
| |
| // #define DEBUG 1 |
| |
| #ifdef DEBUG |
| #define mbtk_call_log(...) printf(__VA_ARGS__) |
| #else |
| #define mbtk_call_log(...) |
| #endif |
| |
| struct ql_call_ubus_t |
| { |
| struct ubus_context *ctx; |
| |
| /* RIL */ |
| struct ubus_subscriber ril_ind_event; |
| uint32_t ril_subscriber_id; |
| uint32_t ril_request_id; |
| uint8_t auto_answer; |
| uint32_t answer_time; |
| pthread_t call_status_pthread; |
| ql_mcm_voice_calls_state_t call_state; |
| QL_VoiceCall_CommonStateHandlerFunc_t _voice_call_common_state_handler; |
| QL_VoiceCall_StateHandlerFunc_t _voice_call_state_handler; |
| }; |
| |
| const char *RIL_MessageMap[] = |
| { |
| "RIL_CALL_ACTIVE", //0, |
| "RIL_CALL_HOLDING", //1, |
| "RIL_CALL_DIALING", //2, /* MO call only */ |
| "RIL_CALL_ALERTING", //3, /* MO call only */ |
| "RIL_CALL_INCOMING", //4, /* MT call only */ |
| "RIL_CALL_WAITING", //5, /* MT call only */ |
| "RIL_CALL_OFFERING", //6, /* MT call offering (call setup) */ |
| "RIL_CALL_DISCONNECTING",//7, /* call in disconnect procedure */ |
| "RIL_CALL_DISCONNECTED" //8, /* call is disconnected */ |
| }; |
| static struct ql_call_ubus_t *ql_call_ubus = NULL; |
| static void ql_voice_call_answer(struct uloop_timeout *timeout); |
| static struct uloop_timeout voice_call_answer_timeout = |
| { |
| .cb = ql_voice_call_answer, |
| }; |
| |
| static void ql_voice_call_answer(struct uloop_timeout *timeout) |
| { |
| QL_Voice_Call_Answer(ql_call_ubus, 0); |
| // uloop_timeout_set(timeout, 2000); |
| return; |
| } |
| |
| int ql_call_handle_ril_ind(struct ubus_context *ctx, unsigned int rilid, unsigned int rilerror, char *data, int data_len) |
| { |
| UNUSED(data_len); |
| UNUSED(ctx); |
| |
| int datalen = 0, callID = 0; |
| int ret = 0; |
| |
| if (rilerror) { |
| return -1; |
| } |
| |
| mbtk_call_log("call_handle_ril_ind: rcv %d\n", rilid); |
| |
| switch(rilid) |
| { |
| case RIL_UNSOL_ECALLDATA: //+ecalldata |
| // ecallHandleEcalldata(data); |
| break; |
| |
| case RIL_UNSOL_ECALLONLY: //+ecallonly |
| // ecallHandleEcallonly(data); |
| break; |
| |
| case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED_EXT: /*"CC" 1510*/ |
| { |
| RIL_Call *rilCall = (RIL_Call *)data; |
| callID = rilCall->index; |
| |
| mbtk_call_log("%s: id %d=RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED_EXT (len=%d) (state=%s), call index=%d\n", |
| __FUNCTION__, rilid, datalen, RIL_MessageMap[(int)rilCall->state], callID); |
| |
| mbtk_call_log("Received from Ril, name=%s, num=%s\n", rilCall->name, rilCall->number); |
| ql_call_ubus->call_state.calls_len = 1; |
| ql_call_ubus->call_state.calls[0].call_id; |
| memcpy(ql_call_ubus->call_state.calls[0].number, rilCall->number, strlen(rilCall->number)); |
| ql_call_ubus->call_state.calls[0].state = rilCall->state; |
| switch (rilCall->state) |
| { |
| //Call connected, for MO & MT both |
| case RIL_CALL_ACTIVE: |
| mbtk_call_log("%s, RIL_CALL_ACTIVE, call index=%d connected!!\n", __FUNCTION__, callID); |
| ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_ACTIVE; |
| break; |
| |
| //MT call only |
| case RIL_CALL_INCOMING: |
| mbtk_call_log("%s, RIL_CALL_INCOMING!!\n", __FUNCTION__); |
| ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_INCOMING; |
| if(!ql_call_ubus->auto_answer) |
| { |
| mbtk_call_log("%s, auto_answer:%d!!\n", __FUNCTION__, ql_call_ubus->answer_time); |
| uloop_timeout_set(&voice_call_answer_timeout, ql_call_ubus->answer_time); |
| } |
| break; |
| |
| //MO call only |
| case RIL_CALL_ALERTING: |
| mbtk_call_log("%s, RIL_CALL_ALERTING, call index=%d alerting!!\n", __FUNCTION__, callID); |
| ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_ALERTING; |
| break; |
| |
| case RIL_CALL_WAITING: //MT call only |
| mbtk_call_log("%s, RIL_CALL_WAITING, call index=%d alerting!!\n", __FUNCTION__, callID); |
| ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_WAITING; |
| break; |
| |
| case RIL_CALL_DISCONNECTED: |
| mbtk_call_log("%s, RIL_CALL_DISCONNECTED, call index=%d disconnected!!\n", __FUNCTION__, callID); |
| ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_END; |
| break; |
| |
| case RIL_CALL_HOLDING: |
| ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_HOLDING; |
| mbtk_call_log("%s, RIL_CALL_HOLDING, call index=%d hold!!\n", __FUNCTION__, callID); |
| break; |
| |
| case RIL_CALL_DIALING: //MO call only |
| ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_DIALING; |
| mbtk_call_log("%s, RIL_CALL_DIALING, call index=%d hold!!\n", __FUNCTION__, callID); |
| break; |
| case RIL_CALL_OFFERING: |
| case RIL_CALL_DISCONNECTING: |
| default: |
| printf("%s, state=%s ignored!!\n", __FUNCTION__, RIL_MessageMap[(int)rilCall->state]); |
| ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_END; |
| break; |
| } |
| if(ql_call_ubus->_voice_call_common_state_handler && ql_call_ubus) |
| { |
| ql_call_ubus->_voice_call_common_state_handler(E_QL_MCM_VOICE_CALL_IND, &ql_call_ubus->call_state, sizeof(ql_mcm_voice_call_ind)); |
| } |
| } |
| break; |
| case RIL_UNSOL_CALL_NO_CARRIER_EXT: /*"CC" 1511*/ |
| mbtk_call_log("%s: id %d=RIL_UNSOL_CALL_NO_CARRIER_EXT (len=%d)\n", |
| __FUNCTION__, rilid, datalen); |
| ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_END; |
| if(ql_call_ubus->_voice_call_common_state_handler && ql_call_ubus) |
| { |
| ql_call_ubus->_voice_call_common_state_handler(E_QL_MCM_VOICE_CALL_IND, &ql_call_ubus->call_state, sizeof(ql_mcm_voice_call_ind)); |
| } |
| break; |
| |
| case RIL_UNSOL_CALL_RING: /*"CC" 1018*/ |
| printf("%s: id %d=RIL_UNSOL_CALL_RING (len=%d), ignored!!\n", |
| __FUNCTION__, rilid, datalen); |
| break; |
| |
| case RIL_UNSOL_DISCONNECT_CALLID: /*"CC" 1538*/ |
| callID = *(int *)data; |
| ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_END; |
| mbtk_call_log("%s: id %d=RIL_UNSOL_DISCONNECT_CALLID (len=%d), call index=%d!\n", |
| __FUNCTION__, rilid, datalen, *(int *)data); |
| break; |
| default: |
| break; |
| } |
| |
| return ret; |
| } |
| static void ql_call_requset_cb(struct ubus_request *req, int type, struct blob_attr *msg) |
| { |
| unsigned int requestid; |
| unsigned int rilerrno; |
| void *response = NULL; |
| int responselen; |
| int ret = 0; |
| |
| ret = rilutil_parseResponse(msg, &requestid, &rilerrno, &response, &responselen); |
| if(ret) |
| { |
| fprintf(stderr, "parse blob error\n"); |
| goto done; |
| } |
| |
| if(rilerrno) |
| { |
| // RIL_REQUEST_RELEASE_CALL |
| fprintf(stderr, "unsolicited id %d, error code %d\n", requestid, rilerrno); |
| goto done; |
| } |
| |
| //process response here |
| |
| done: |
| if(response) |
| rilutil_freeResponseData(requestid, response, responselen); |
| |
| return; |
| } |
| |
| int ql_call_subscriber_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| UNUSED(ctx); |
| UNUSED(obj); |
| UNUSED(req); |
| UNUSED(method); |
| |
| unsigned int requestid = 0; |
| unsigned int rilerrno = 0; |
| void *response = NULL; |
| int responselen = 0; |
| int ret = 0; |
| |
| ret = rilutil_parseResponse(msg, &requestid, &rilerrno, &response, &responselen); |
| if (ret) |
| goto end; |
| |
| mbtk_call_log("call_subscriber_cb: rcv %d\n", requestid); |
| |
| ql_call_handle_ril_ind(ctx, requestid, rilerrno, response, responselen); |
| |
| end: |
| if (response) |
| rilutil_freeResponseData(requestid,response,responselen); |
| |
| return 0; |
| } |
| |
| void ql_call_subscriber_remove_cb(struct ubus_context *ctx, struct ubus_subscriber *obj, uint32_t id) |
| { |
| UNUSED(ctx); |
| UNUSED(obj); |
| UNUSED(id); |
| mbtk_call_log("ql_call_subscriber_remove_cb\n"); |
| } |
| |
| static void ql_call_register_ril(void* hdl) |
| { |
| static struct ubus_request req; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)hdl; |
| int ret; |
| |
| if(hdl == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| pthread_detach(pthread_self()); |
| ret = ubus_register_subscriber(voice_call_ubus->ctx, &voice_call_ubus->ril_ind_event); |
| if (ret) { |
| printf("call_daemon: Failed to add ecall_subscriber: %s\n", ubus_strerror(ret)); |
| return ret; |
| } |
| |
| voice_call_ubus->ril_ind_event.cb = ql_call_subscriber_cb; |
| voice_call_ubus->ril_ind_event.remove_cb = ql_call_subscriber_remove_cb; |
| |
| //register for CC ind |
| if (ubus_lookup_id(voice_call_ubus->ctx, "ril.unsol.cc", &voice_call_ubus->ril_subscriber_id)) { |
| printf("call_daemon: Failed to look up ril.unsol.cc object\n"); |
| return ret; |
| } |
| |
| ubus_subscribe(voice_call_ubus->ctx, &voice_call_ubus->ril_ind_event, voice_call_ubus->ril_subscriber_id); |
| mbtk_call_log("call_daemon: subscribe ril.unsol.cc object ok\n"); |
| mbtk_call_log("%s!\n", __FUNCTION__); |
| while(1) |
| { |
| uloop_run(); |
| printf("%s uloop_run done!\n", __FUNCTION__); |
| } |
| pthread_exit(NULL); |
| } |
| /* Init voice module and return h_voice, this should be called before any other APIs */ |
| int QL_Voice_Call_Client_Init(voice_client_handle_type *ph_voice) |
| { |
| int id; |
| // Set call handle. |
| //*ph_voice = 1; |
| if(ph_voice == NULL) |
| { |
| printf("ARG error or has inited."); |
| return -1; |
| } |
| ql_call_ubus = malloc(sizeof(struct ql_call_ubus_t)); |
| if(NULL == ql_call_ubus) |
| { |
| printf("malloc memory error\n"); |
| } |
| memset(ql_call_ubus, 0, sizeof(struct ql_call_ubus_t)); |
| uloop_init(); |
| |
| ql_call_ubus->ctx = ubus_connect(NULL); |
| if(!ql_call_ubus->ctx) |
| { |
| printf("Failed to connect to ubus"); |
| goto out; |
| } |
| |
| ubus_add_uloop(ql_call_ubus->ctx); |
| |
| if (ubus_lookup_id(ql_call_ubus->ctx, "ril", &ql_call_ubus->ril_request_id)) { |
| fprintf(stderr, "%s, Failed to look up test object\n", __FUNCTION__); |
| return -1; |
| } |
| ql_call_ubus->auto_answer = E_QL_MCM_VOICE_AUTO_ANSWER_DISABLE; |
| ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_END; |
| pthread_create(&ql_call_ubus->call_status_pthread, NULL, (void *)ql_call_register_ril, (void *)ql_call_ubus); |
| *ph_voice = ql_call_ubus; |
| |
| return 0; |
| out: |
| //uloop_done(); |
| |
| return 0; |
| } |
| |
| /* DeInit voice module and release resources, this should be called at last */ |
| int QL_Voice_Call_Client_Deinit(voice_client_handle_type h_voice) |
| { |
| int ret; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| // Free handle. |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| LOGE("ARG error or not inited."); |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| ret = pthread_cancel(voice_call_ubus->call_status_pthread); |
| mbtk_call_log("kill pthread : %d \n", ret); |
| pthread_join(voice_call_ubus->call_status_pthread, NULL); |
| do{ |
| ret = pthread_kill(voice_call_ubus->call_status_pthread, 0); |
| mbtk_call_log("kill pthread: %d \n", ret); |
| if(ret == ESRCH) |
| printf("The specified thread does not exist or has terminated\n"); |
| else if(ret == EINVAL) |
| printf("Useless signal\n"); |
| else |
| mbtk_call_log("The thread exists\n"); |
| usleep(100000); |
| }while(0 == ret); |
| free(h_voice); |
| ql_call_ubus = NULL; |
| uloop_done(); |
| ubus_free(voice_call_ubus->ctx); |
| return 0; |
| } |
| |
| /* Add callback function, if any call state changed, handlerPtr will be called to notify App */ |
| int QL_Voice_Call_AddStateHandler(voice_client_handle_type h_voice, |
| QL_VoiceCall_StateHandlerFunc_t handlerPtr, |
| void* contextPtr) |
| { |
| static struct ubus_request req; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| int ret; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| ret = pthread_kill(voice_call_ubus->call_status_pthread, 0); |
| mbtk_call_log("kill pthread: %d \n", ret); |
| if(ret == ESRCH) |
| mbtk_call_log("The specified thread does not exist or has terminated\n"); |
| else if(ret == EINVAL) |
| printf("Useless signal\n"); |
| else |
| mbtk_call_log("The thread exists\n"); |
| if(voice_call_ubus->ril_subscriber_id) |
| { |
| voice_call_ubus->_voice_call_state_handler = handlerPtr; |
| } |
| else |
| { |
| printf("%s error!!\n", __func__); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| /* Remove callback function, won't receive any notify anymore */ |
| int QL_Voice_Call_RemoveStateHandler(voice_client_handle_type h_voice) |
| { |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| LOGE("ARG error or not inited."); |
| return -1; |
| } |
| voice_call_ubus->_voice_call_state_handler = NULL; |
| |
| return 0; |
| } |
| |
| |
| /* Add callback function, if any call state changed, handlerPtr will be called to notify App */ |
| int QL_Voice_Call_AddCommonStateHandler(voice_client_handle_type h_voice, |
| QL_VoiceCall_CommonStateHandlerFunc_t handlerPtr) |
| { |
| static struct ubus_request req; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| int ret; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| LOGE("ARG error or not inited."); |
| return -1; |
| } |
| ret = pthread_kill(voice_call_ubus->call_status_pthread, 0); |
| mbtk_call_log("kill pthread: %d \n", ret); |
| if(ret == ESRCH) |
| mbtk_call_log("The specified thread does not exist or has terminated\n"); |
| else if(ret == EINVAL) |
| printf("Useless signal\n"); |
| else |
| mbtk_call_log("The thread exists\n"); |
| if(voice_call_ubus->ril_subscriber_id) |
| { |
| voice_call_ubus->_voice_call_common_state_handler = handlerPtr; |
| } |
| else |
| { |
| printf("%s error!!\n", __func__); |
| return -1; |
| } |
| |
| |
| return 0; |
| } |
| |
| /* Remove callback function, won't receive any notify anymore */ |
| int QL_Voice_Call_RemoveCommonStateHandler(voice_client_handle_type h_voice) |
| { |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| LOGE("ARG error or not inited."); |
| return -1; |
| } |
| voice_call_ubus->_voice_call_common_state_handler = NULL; |
| |
| return 0; |
| } |
| |
| |
| /* Start call and return call_id, this can be used in the later */ |
| int QL_Voice_Call_Start(voice_client_handle_type h_voice, |
| E_QL_VCALL_ID_T simId, |
| char* phone_number, ///< [IN] Destination identifier for the voice |
| int *call_id) ///< [OUT] call id |
| { |
| static struct ubus_request req; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| static struct blob_buf b; |
| int id, ret; |
| RIL_Dial dial_data; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| if(voice_call_ubus->call_state.calls[0].state == E_QL_MCM_VOICE_CALL_STATE_ACTIVE || |
| voice_call_ubus->call_state.calls[0].state == E_QL_MCM_VOICE_CALL_STATE_INCOMING || |
| voice_call_ubus->call_state.calls[0].state == E_QL_MCM_VOICE_CALL_STATE_ALERTING) |
| { |
| printf("A call already exists, Voice Call incoming or active!!\n"); |
| return -1; |
| } |
| memset(&dial_data, 0, sizeof(RIL_Dial)); |
| dial_data.address = phone_number; |
| printf("call number %s\n", dial_data.address); |
| if (ubus_lookup_id(ql_call_ubus->ctx, "ril", &ql_call_ubus->ril_request_id)) { |
| fprintf(stderr, "%s, Failed to look up test object\n", __FUNCTION__); |
| return -1; |
| } |
| rilutil_makeRequestBlob(&b, RIL_REQUEST_DIAL, &dial_data, 0); |
| ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0); |
| if(ret != 0) |
| { |
| printf("sim_get_imsi,ubus_invoke Failed %s\n", ubus_strerror(ret)); |
| return E_QL_ERROR_GENERIC; |
| } |
| |
| return 0; |
| } |
| |
| /* End call of call_id, which returned by QL_Voice_Call_Start or callback func register via QL_Voice_Call_AddStateHandler */ |
| int QL_Voice_Call_End(voice_client_handle_type h_voice, |
| int call_id) ///< [IN] call id, return by QL_Voice_Start |
| { |
| static struct ubus_request req; |
| static struct blob_buf b; |
| int ret; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| mbtk_call_log("Voice Call State:%s, %d\n", voice_call_ubus->call_state.calls[0].number, voice_call_ubus->call_state.calls[0].state); |
| if(voice_call_ubus->call_state.calls[0].state != E_QL_MCM_VOICE_CALL_STATE_ACTIVE && |
| voice_call_ubus->call_state.calls[0].state != E_QL_MCM_VOICE_CALL_STATE_INCOMING && |
| voice_call_ubus->call_state.calls[0].state != E_QL_MCM_VOICE_CALL_STATE_ALERTING) |
| { |
| printf("No Voice Call incoming or active!!\n"); |
| return -1; |
| } |
| //use rilutil's API, just a example |
| rilutil_makeRequestBlob(&b, RIL_REQUEST_RELEASE_CALL, NULL, 0); |
| ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0); |
| if(ret != 0) |
| { |
| printf("sim_get_imsi,ubus_invoke Failed %s", ubus_strerror(ret)); |
| return E_QL_ERROR_GENERIC; |
| } |
| return 0; |
| } |
| |
| /* Answer the call of call_id, which returned by callback func register via QL_Voice_Call_AddStateHandler */ |
| int QL_Voice_Call_Answer(voice_client_handle_type h_voice, |
| int call_id ) |
| { |
| static struct ubus_request req; |
| static struct blob_buf b; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| int ret; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| rilutil_makeRequestBlob(&b, RIL_REQUEST_ANSWER, NULL, 0); |
| ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0); |
| if(ret != 0) |
| { |
| printf("ql call, ubus_invoke Failed %s", ubus_strerror(ret)); |
| return E_QL_ERROR_GENERIC; |
| } |
| return 0; |
| } |
| |
| int QL_Voice_Call_Hold( voice_client_handle_type h_voice) |
| { |
| static struct ubus_request req; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| static struct blob_buf b; |
| int ret; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| rilutil_makeRequestBlob(&b, RIL_REQUEST_HANGUP, NULL, 0); |
| ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0); |
| if(ret != 0) |
| { |
| printf("ql call, ubus_invoke Failed %s", ubus_strerror(ret)); |
| return E_QL_ERROR_GENERIC; |
| } |
| return 0; |
| } |
| |
| int QL_Voice_Call_UnHold( voice_client_handle_type h_voice) |
| { |
| |
| return 0; |
| } |
| |
| int QL_Voice_Call_Conference( voice_client_handle_type h_voice) |
| { |
| static struct ubus_request req; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| static struct blob_buf b; |
| int ret; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| rilutil_makeRequestBlob(&b, RIL_REQUEST_CONFERENCE, NULL, 0); |
| ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0); |
| if(ret != 0) |
| { |
| printf("ql call, ubus_invoke Failed %s", ubus_strerror(ret)); |
| return E_QL_ERROR_GENERIC; |
| } |
| return 0; |
| } |
| |
| int QL_Voice_Call_EndConference( voice_client_handle_type h_voice) |
| { |
| |
| return 0; |
| } |
| |
| int QL_Voice_Call_Ecall(voice_client_handle_type h_voice, |
| E_QL_VCALL_ID_T simId, |
| char* phone_number, |
| ql_mcm_ecall_info ecall_info, |
| int *call_id) |
| { |
| // RIL_REQUEST_SET_CECALL |
| // RIL_REQUEST_GET_CECALL |
| // RIL_REQUEST_SET_ECALLONLY |
| // RIL_REQUEST_GET_ECALLONLY |
| // RIL_REQUEST_SET_ECALLREG |
| static struct ubus_request req; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| static struct blob_buf b; |
| int ret; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| //use rilutil's API, just a example |
| rilutil_makeRequestBlob(&b, RIL_REQUEST_CONFERENCE, NULL, 0); |
| ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0); |
| if(ret != 0) |
| { |
| printf("ql call, ubus_invoke Failed %s", ubus_strerror(ret)); |
| return E_QL_ERROR_GENERIC; |
| } |
| return 0; |
| } |
| |
| |
| int QL_Voice_Call_SetAutoAnswer(voice_client_handle_type h_voice, |
| E_QL_MCM_VOICE_AUTO_ANSWER_T eAnswerType, |
| uint32_t uAnswerTime) |
| { |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| voice_call_ubus->auto_answer = eAnswerType; |
| voice_call_ubus->answer_time = uAnswerTime; |
| |
| return 0; |
| } |
| |
| int QL_Voice_Call_Ecall_HangUp(voice_client_handle_type h_voice) |
| { |
| return 0; |
| } |
| |
| int QL_Voice_Call_Ecall_UpdateMsd(voice_client_handle_type h_voice,const char *msd,uint32_t msd_len) |
| { |
| return 0; |
| } |
| |
| //Ecall Push caommand |
| int QL_Voice_Call_Ecall_MsdPush(voice_client_handle_type h_voice, |
| E_QL_MCM_ECALL_STATE_T *ecall_state) |
| { |
| return 0; |
| } |
| |
| //Get Ecall config info |
| int QL_Voice_Call_Ecall_GetConfigInfo(voice_client_handle_type h_voice, |
| ql_mcm_ecall_config_info *ecall_config) |
| { |
| // RIL_REQUEST_SET_ECALLCFG |
| // RIL_REQUEST_GET_ECALLCFG |
| return 0; |
| } |
| |
| int QL_Voice_Call_Ecall_SetConfigInfo(voice_client_handle_type h_voice, |
| E_QL_MCM_ECALL_CONFIG_T ecall_config_type, |
| uint8_t value) |
| { |
| return 0; |
| } |
| |
| //Cancel dial |
| int QL_Voice_Call_CancelDial( voice_client_handle_type h_voice) |
| { |
| static struct ubus_request req; |
| static struct blob_buf b; |
| int ret; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| //use rilutil's API, just a example |
| rilutil_makeRequestBlob(&b, RIL_REQUEST_RELEASE_CALL, NULL, 0); |
| ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0); |
| if(ret != 0) |
| { |
| printf("sim_get_imsi,ubus_invoke Failed %s", ubus_strerror(ret)); |
| return E_QL_ERROR_GENERIC; |
| } |
| return 0; |
| } |
| |
| //VTS API |
| int QL_Voice_Call_Dtmf(voice_client_handle_type h_voice, uint8_t digit, int call_id) |
| { |
| static struct ubus_request req; |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| static struct blob_buf b; |
| int ret; |
| char code = digit; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| rilutil_makeRequestBlob(&b, RIL_REQUEST_DTMF, &code, 0); |
| ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0); |
| if(ret != 0) |
| { |
| printf("ql call, ubus_invoke Failed %s", ubus_strerror(ret)); |
| return E_QL_ERROR_GENERIC; |
| } |
| return 0; |
| } |
| |
| int QL_Voice_Call_GetCallStatus |
| ( |
| int h_voice, |
| int call_id, // If call_id<0, means to get all calls state, or get specified call_id info |
| ql_mcm_voice_calls_state_t *pt_callstate |
| ) |
| { |
| struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice; |
| |
| if(h_voice == NULL || ql_call_ubus == NULL) |
| { |
| printf("ARG error or not inited."); |
| return -1; |
| } |
| memcpy((void *)pt_callstate, &voice_call_ubus->call_state, sizeof(ql_mcm_voice_calls_state_t)); |
| return 0; |
| } |
| |
| //Set forwarding |
| int QL_Voice_Call_SetForwarding |
| ( |
| int h_voice, |
| E_QL_MCM_VOICE_CALL_SERVICE_T service, |
| E_QL_MCM_VOICE_CALL_FORWARDING_REASON_T reason, |
| char *number |
| ) |
| { |
| |
| return 0; |
| } |
| |
| //Get forwarding status |
| int QL_Voice_Call_GetForwardingStatus( |
| int h_voice, |
| E_QL_MCM_VOICE_CALL_FORWARDING_REASON_T reason, |
| ql_mcm_voice_call_forwarding_status_list_t *pt_status) |
| { |
| |
| return 0; |
| } |
| |
| |
| //Set voice call waiting |
| int QL_Voice_Call_SetWaiting |
| ( |
| int h_voice, |
| ql_mcm_voice_call_waiting_service_t e_service |
| ) |
| { |
| // RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND |
| return 0; |
| } |
| |
| //Get voice call waiting status |
| int QL_Voice_Call_GetWaitingStatus |
| ( |
| int h_voice, |
| ql_mcm_voice_call_waiting_service_t *pe_service |
| ) |
| { |
| |
| return 0; |
| } |