| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include <sys/socket.h> |
| #include <sys/un.h> |
| #include <netinet/in.h> |
| #include <pthread.h> |
| #include <sys/epoll.h> |
| #include <fcntl.h> |
| #include <signal.h> |
| |
| #include "mbtk_type.h" |
| #include "mbtk_ril.h" |
| #include "atchannel.h" |
| #include "at_tok.h" |
| #include "mbtk_utils.h" |
| #include "ril_info.h" |
| |
| void ril_rsp_pack_send(mbtk_sim_type_enum sim_id, ATPortType_enum port, int fd, int ril_id, int msg_index, const void* data, int data_len); |
| ATPortId_enum portType_2_portId(mbtk_sim_type_enum sim_id, ATPortType_enum port); |
| |
| /* |
| ATDXXXXXXX; |
| OK |
| |
| */ |
| static int req_call_start(mbtk_sim_type_enum sim_id, ATPortType_enum port, char *phont_number, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| // int tmp_int; |
| // char *tmp_str = NULL; |
| char cmd[100] = {0}; |
| sprintf(cmd, "ATD%s;", phont_number); |
| int err = at_send_command(portType_2_portId(sim_id, port), cmd, &response); |
| if (err < 0 || response->success == 0){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| /* |
| |
| AT+CHLD=2 |
| OK |
| |
| */ |
| static int req_answer_call(mbtk_sim_type_enum sim_id, ATPortType_enum port, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| int err = at_send_command(portType_2_portId(sim_id, port), "AT+CHLD=2", &response); |
| if (err < 0 || response->success == 0){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| /* |
| ATH |
| OK |
| |
| */ |
| static int req_hangup_call(mbtk_sim_type_enum sim_id, ATPortType_enum port, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| int err = at_send_command(portType_2_portId(sim_id, port), "ATH", &response); |
| if (err < 0 || response->success == 0){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| /* |
| AT+CHLD=1x |
| OK |
| |
| */ |
| static int req_hangup_a_call(mbtk_sim_type_enum sim_id, ATPortType_enum port, int phone_id, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| char cmd[100] = {0}; |
| sprintf(cmd, "AT+CHLD=1%d", phone_id); |
| int err = at_send_command(portType_2_portId(sim_id, port), cmd, &response); |
| if (err < 0 || response->success == 0){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| /* |
| AT+CHLD=0 |
| OK |
| |
| */ |
| static int req_hangup_waiting_or_background_call(mbtk_sim_type_enum sim_id, ATPortType_enum port, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| int err = at_send_command(portType_2_portId(sim_id, port), "AT+CHLD=0", &response); |
| if (err < 0 || response->success == 0){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| /* |
| AT+CHLD=1 |
| OK |
| |
| */ |
| static int req_hangup_foreground_resume_background_call(mbtk_sim_type_enum sim_id, ATPortType_enum port, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| int err = at_send_command(portType_2_portId(sim_id, port), "AT+CHLD=1", &response); |
| if (err < 0 || response->success == 0){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| /* |
| AT+CLCC |
| OK |
| |
| */ |
| static int req_waitin_call(mbtk_sim_type_enum sim_id, ATPortType_enum port, mbtk_call_info_t *reg, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| int tmp_int; |
| char *tmp_str = NULL; |
| |
| int err = at_send_command_multiline(portType_2_portId(sim_id, port), "AT+CLCC", "+CLCC:", &response); |
| if (err < 0 || response->success == 0){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| if(response->success == 1 && !response->p_intermediates) |
| { |
| reg->call_wait = 0; |
| goto exit; |
| } |
| |
| reg->call_wait = 1; |
| char *line = response->p_intermediates->line; |
| err = at_tok_start(&line); |
| if (err < 0) |
| { |
| goto exit; |
| } |
| err = at_tok_nextint(&line, &tmp_int); // dir1 |
| if (err < 0) |
| { |
| goto exit; |
| } |
| reg->dir1 = (uint8)tmp_int; |
| err = at_tok_nextint(&line, &tmp_int);// dir |
| if (err < 0) |
| { |
| goto exit; |
| } |
| reg->dir = (uint8)tmp_int; |
| err = at_tok_nextint(&line, &tmp_int);// state |
| if (err < 0) |
| { |
| goto exit; |
| } |
| reg->state = (uint8)tmp_int; |
| err = at_tok_nextint(&line, &tmp_int);// mode |
| if (err < 0) |
| { |
| goto exit; |
| } |
| reg->mode = (uint8)tmp_int; |
| err = at_tok_nextint(&line, &tmp_int);// mpty |
| if (err < 0) |
| { |
| goto exit; |
| } |
| reg->mpty = (uint8)tmp_int; |
| err = at_tok_nextstr(&line, &tmp_str); // phone_number |
| if (err < 0) |
| { |
| goto exit; |
| } |
| memcpy(reg->phone_number, tmp_str, strlen(tmp_str)); |
| err = at_tok_nextint(&line, &tmp_int);// tpye |
| if (err < 0) |
| { |
| goto exit; |
| } |
| reg->type = (uint8)tmp_int; |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| /* |
| AT+CMUT? |
| +CMUT: 0 |
| |
| OK |
| */ |
| static int req_mute_get(mbtk_sim_type_enum sim_id, ATPortType_enum port, int *state, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| int tmp_int; |
| int err = at_send_command_singleline(portType_2_portId(sim_id, port), "AT+CMUT?", "+CMUT:", &response); |
| |
| if (err < 0 || response->success == 0 || !response->p_intermediates){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| char *line = response->p_intermediates->line; |
| err = at_tok_start(&line); |
| if (err < 0) |
| { |
| goto exit; |
| } |
| err = at_tok_nextint(&line, &tmp_int); |
| if (err < 0) |
| { |
| goto exit; |
| } |
| *state = tmp_int; |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| /* |
| AT+CMUT=0; |
| OK |
| |
| */ |
| static int req_mute_set(mbtk_sim_type_enum sim_id, ATPortType_enum port, int state, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| char cmd[100] = {0}; |
| sprintf(cmd, "AT+CMUT=%d", state); |
| LOG("Set the mute command is = %s.\n", cmd); |
| int err = at_send_command(portType_2_portId(sim_id, port), cmd, &response); |
| if (err < 0 || response->success == 0){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| /* |
| AT+VTS=0; //0, 1, ..., 9, A, B, C, D, *, # |
| OK |
| |
| */ |
| static int req_dtmf_set(mbtk_sim_type_enum sim_id, ATPortType_enum port, mbtk_call_dtmf_info_t *state, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| char cmd[100] = {0}; |
| sprintf(cmd, "AT+VTS=%c,%d", state->character, state->duration); |
| LOG("Set the DTMF command is = %s.\n", cmd); |
| int err = at_send_command(portType_2_portId(sim_id, port), cmd, &response); |
| if (err < 0 || response->success == 0){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| static int req_centric_get(mbtk_sim_type_enum sim_id, ATPortType_enum port, int *state, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| int tmp_int = 0; |
| int err = at_send_command_singleline(portType_2_portId(sim_id, port), "AT+CEUS?", "+CEUS:", &response); |
| |
| if (err < 0 || response->success == 0 || !response->p_intermediates){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| char *line = response->p_intermediates->line; |
| err = at_tok_start(&line); |
| if (err < 0) |
| { |
| goto exit; |
| } |
| err = at_tok_nextint(&line, &tmp_int); |
| if (err < 0) |
| { |
| goto exit; |
| } |
| *state = tmp_int; |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| /* |
| AT+CMUT=0; |
| OK |
| |
| */ |
| static int req_centric_set(mbtk_sim_type_enum sim_id, ATPortType_enum port, int state, int *cme_err) |
| { |
| ATResponse *response = NULL; |
| char cmd[100] = {0}; |
| sprintf(cmd, "AT+CEUS=%d", state); |
| LOG("Set the centric command is = %s.\n", cmd); |
| int err = at_send_command(portType_2_portId(sim_id, port), cmd, &response); |
| if (err < 0 || response->success == 0){ |
| *cme_err = at_get_cme_error(response); |
| goto exit; |
| } |
| |
| exit: |
| at_response_free(response); |
| return err; |
| } |
| |
| |
| //void net_list_free(void *data); |
| // Return MBTK_INFO_ERR_SUCCESS,will call pack_error_send() to send RSP. |
| // Otherwise, do not call pack_error_send(). |
| mbtk_ril_err_enum call_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack) |
| { |
| mbtk_ril_err_enum err = MBTK_RIL_ERR_SUCCESS; |
| int cme_err = MBTK_RIL_ERR_CME_NON; |
| switch(pack->msg_id) |
| { |
| case RIL_MSG_ID_CALL_START: // <string> phone number |
| { |
| if(pack->data_len == 0 || pack->data == NULL) |
| { |
| err = MBTK_RIL_ERR_UNSUPPORTED; |
| } |
| else // Set |
| { |
| char *pn = (char*)(pack->data); |
| if(req_call_start(cli_info->sim_id, cli_info->port, pn, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("ATD fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0); |
| } |
| } |
| break; |
| } |
| case RIL_MSG_ID_CALL_ANSWER: |
| { |
| if(pack->data_len == 0 || pack->data == NULL) |
| { |
| if(req_answer_call(cli_info->sim_id, cli_info->port, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("Answer call fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0); |
| } |
| } |
| else // Set |
| { |
| err = MBTK_RIL_ERR_UNSUPPORTED; |
| LOG("Answer call fail. NO DATA\n"); |
| } |
| break; |
| } |
| case RIL_MSG_ID_CALL_HANGUP: |
| { |
| if(pack->data_len == 0 || pack->data == NULL) |
| { |
| if(req_hangup_call(cli_info->sim_id, cli_info->port, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("Hang up call fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0); |
| } |
| } |
| else // Set |
| { |
| err = MBTK_RIL_ERR_UNSUPPORTED; |
| LOG("Hang up call fail."); |
| } |
| break; |
| } |
| case RIL_MSG_ID_CALL_HANGUP_A: |
| { |
| if(pack->data_len == 0 || pack->data == NULL) |
| { |
| err = MBTK_RIL_ERR_UNSUPPORTED; |
| LOG("Hang up a call fail."); |
| } |
| else |
| { |
| uint8 phone_id = *(pack->data); |
| if(req_hangup_a_call(cli_info->sim_id, cli_info->port, phone_id, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("Hang up a call fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0); |
| } |
| } |
| break; |
| } |
| case RIL_MSG_ID_CALL_HANGUP_B: |
| { |
| if(pack->data_len == 0 || pack->data == NULL) |
| { |
| if(req_hangup_waiting_or_background_call(cli_info->sim_id, cli_info->port, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("Hang up waiting_or_background call fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0); |
| } |
| } |
| else |
| { |
| err = MBTK_RIL_ERR_UNSUPPORTED; |
| LOG("Hang up waiting_or_background call fail."); |
| } |
| break; |
| } |
| case RIL_MSG_ID_CALL_HANGUP_C: |
| { |
| if(pack->data_len == 0 || pack->data == NULL) |
| { |
| if(req_hangup_foreground_resume_background_call(cli_info->sim_id, cli_info->port, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("Hang up waiting_or_background call fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0); |
| } |
| } |
| else |
| { |
| err = MBTK_RIL_ERR_UNSUPPORTED; |
| LOG("Hang up waiting_or_background call fail."); |
| } |
| break; |
| } |
| case RIL_MSG_ID_CALL_WAITIN: |
| { |
| if(pack->data_len == 0 || pack->data == NULL) |
| { |
| mbtk_call_info_t reg; |
| memset(®, 0, sizeof(mbtk_call_info_t)); |
| if(req_waitin_call(cli_info->sim_id, cli_info->port, ®, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("Wait incoing call fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, ®, sizeof(mbtk_call_info_t)); |
| } |
| } |
| else // Set |
| { |
| err = MBTK_RIL_ERR_UNSUPPORTED; |
| LOG("Wait incoing call fail."); |
| } |
| break; |
| } |
| case RIL_MSG_ID_CALL_MUTE: |
| { |
| if(pack->data_len == 0 || pack->data == NULL) // Get VoLTE state. |
| { |
| int state; |
| if(req_mute_get(cli_info->sim_id, cli_info->port, &state, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("Get mute state fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, &state, sizeof(uint8)); |
| } |
| } |
| else // Set mute state. |
| { |
| uint8 on = *(pack->data); |
| if(pack->data_len != sizeof(uint8) || (on != 0 && on != 1)) |
| { |
| err = MBTK_RIL_ERR_REQ_PARAMETER; |
| LOG("Set mute parameter error."); |
| break; |
| } |
| |
| if(req_mute_set(cli_info->sim_id, cli_info->port, on, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("Set mute state fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0); |
| } |
| } |
| break; |
| } |
| case RIL_MSG_ID_CALL_DTMF: |
| { |
| if(pack->data_len == 0 || pack->data == NULL) |
| { |
| err = MBTK_RIL_ERR_UNSUPPORTED; |
| LOG("Wait incoing call fail."); |
| } |
| else // Set |
| { |
| mbtk_call_dtmf_info_t *reg = (mbtk_call_dtmf_info_t *)pack->data; |
| if(req_dtmf_set(cli_info->sim_id, cli_info->port, reg, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("Wait incoing call fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0); |
| } |
| } |
| break; |
| } |
| case RIL_MSG_ID_CALL_CENTRIC: |
| { |
| if(pack->data_len == 0 || pack->data == NULL) // Get VoLTE state. |
| { |
| int state; |
| if(req_centric_get(cli_info->sim_id, cli_info->port, &state, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("Get mute state fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, &state, sizeof(int)); |
| } |
| } |
| else // Set mute state. |
| { |
| uint8 on = *(pack->data); |
| if(pack->data_len != sizeof(uint8) || (on != 0 && on != 1)) |
| { |
| err = MBTK_RIL_ERR_REQ_PARAMETER; |
| LOG("Set mute parameter error."); |
| break; |
| } |
| |
| if(req_centric_set(cli_info->sim_id, cli_info->port, on, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON) |
| { |
| if(cme_err != MBTK_RIL_ERR_CME_NON) { |
| err = MBTK_RIL_ERR_CME + cme_err; |
| } else { |
| err = MBTK_RIL_ERR_UNKNOWN; |
| } |
| LOG("Set mute state fail."); |
| } |
| else |
| { |
| ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0); |
| } |
| } |
| break; |
| } |
| default: |
| { |
| err = MBTK_RIL_ERR_REQ_UNKNOWN; |
| LOG("Unknown request : %s", id2str(pack->msg_id)); |
| break; |
| } |
| } |
| |
| return err; |
| } |
| |
| |
| |