blob: 941f5eb206cccbe75c184d14b06aa012f18e6c69 [file] [log] [blame]
#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);
/*
AT+CGSN
864788050901201
OK
*/
static int req_imei_get(mbtk_sim_type_enum sim_id, ATPortType_enum port, void *data, int *cme_err)
{
ATResponse *response = NULL;
int err = at_send_command_numeric(portType_2_portId(sim_id, port), "AT+CGSN", &response);
if (err < 0 || response->success == 0 || !response->p_intermediates) {
*cme_err = at_get_cme_error(response);
goto exit;
}
memcpy(data, response->p_intermediates->line, strlen(response->p_intermediates->line));
exit:
at_response_free(response);
return err;
}
/*
AT+MRD_SN=R
+MRD_SN:0101,Thu Nov 12 00:00:00 2020,G4M32301020006
OK
*/
static int req_sn_get(mbtk_sim_type_enum sim_id, ATPortType_enum port, void *data, int *cme_err)
{
ATResponse *response = NULL;
char *tmp_ptr = NULL;
int err = at_send_command_singleline(portType_2_portId(sim_id, port), "AT+MRD_SN=R", "+MRD_SN:", &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_nextstr(&line, &tmp_ptr);
if (err < 0)
{
goto exit;
}
err = at_tok_nextstr(&line, &tmp_ptr);
if (err < 0)
{
goto exit;
}
err = at_tok_nextstr(&line, &tmp_ptr);
if (err < 0)
{
goto exit;
}
memcpy(data, tmp_ptr, strlen(tmp_ptr));
goto exit;
exit:
at_response_free(response);
return err;
}
/*
ATI
Manufacturer:"LYNQ"
Model:"LYNQ_L508TLC"
Revision:L508TLCv02.01b01.00
IMEI:864788050901201
OK
*/
static int req_version_get(mbtk_sim_type_enum sim_id, ATPortType_enum port, void *data, int *cme_err)
{
ATResponse *response = NULL;
// sleep(3);
int err = at_send_command_multiline(portType_2_portId(sim_id, port), "ATI", "", &response);
if (err < 0 || response->success == 0 || !response->p_intermediates){
*cme_err = at_get_cme_error(response);
goto exit;
}
ATLine* lines_ptr = response->p_intermediates;
char *line = NULL;
while(lines_ptr)
{
line = lines_ptr->line;
if(strStartsWith(line, "Revision"))
{
err = at_tok_start(&line);
if (err < 0)
{
goto exit;
}
memcpy(data, line, strlen(line));
break;
}
lines_ptr = lines_ptr->p_next;
}
goto exit;
exit:
at_response_free(response);
return err;
}
/*
ATI
Manufacturer:"LYNQ"
Model:"LYNQ_L508TLC"
Revision:L508TLCv02.01b01.00
IMEI:864788050901201
OK
*/
static int req_model_get(mbtk_sim_type_enum sim_id, ATPortType_enum port, void *data, int *cme_err)
{
ATResponse *response = NULL;
int err = at_send_command_multiline(portType_2_portId(sim_id, port), "ATI", "", &response);
if (err < 0 || response->success == 0 || !response->p_intermediates){
*cme_err = at_get_cme_error(response);
goto exit;
}
ATLine* lines_ptr = response->p_intermediates;
char *line = NULL;
while(lines_ptr)
{
line = lines_ptr->line;
if(strStartsWith(line, "Model"))
{
err = at_tok_start(&line);
if (err < 0)
{
goto exit;
}
memcpy(data, line, strlen(line));
break;
}
lines_ptr = lines_ptr->p_next;
}
goto exit;
exit:
at_response_free(response);
return err;
}
/*
AT+ACONFIG="IMSD=1"
or
AT+ACONFIG="IMSD=0"
OK
*/
static int req_volte_set(mbtk_sim_type_enum sim_id, ATPortType_enum port, int state, int *cme_err)
{
ATResponse *response = NULL;
char cmd[30] = {0};
if(state)
{
strcpy(cmd, "AT+ACONFIG=\"IMSD=1\"");
}
else
{
strcpy(cmd, "AT+ACONFIG=\"IMSD=0\"");
}
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;
}
err = 0;
exit:
at_response_free(response);
return err;
}
/*
AT+ACONFIG?
PID=0,VID=0,IMSD=1,PIPE=0,FAST=0,RDUP=1,NOCP=0,GEFL=-1237040617
OK
*/
static int req_volte_get(mbtk_sim_type_enum sim_id, ATPortType_enum port, int *state, int *cme_err)
{
ATResponse *response = NULL;
// char *tmp_ptr = NULL;
int err = at_send_command_singleline(portType_2_portId(sim_id, port), "AT+ACONFIG?", "", &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;
char* ptr = strstr(line, "IMSD=");
if(ptr)
{
*state = atoi(ptr + strlen("IMSD="));
}
else
{
err = -1;
}
exit:
at_response_free(response);
return err;
}
/*
* Get system temperature.
*
* type[IN]:
* 0: Soc temperature.
* 1: RF temperature.
* temp[OUT]:
* temperature in celsius.
*
AT*RFTEMP
*RFTEMP:0,28
OK
AT*SOCTEMP
*SOCTEMP:24000
OK
*/
static int req_temp_get(mbtk_sim_type_enum sim_id, ATPortType_enum port, mbtk_temp_type_enum type, int16 *temp, int *cme_err)
{
ATResponse *response = NULL;
int err = -1;
int tmp_int;
if(type == MBTK_TEMP_TYPE_SOC) { // Soc
err = at_send_command_singleline(portType_2_portId(sim_id, port), "AT*SOCTEMP", "*SOCTEMP:", &response);
} else { // RF
err = at_send_command_singleline(portType_2_portId(sim_id, port), "AT*RFTEMP", "*RFTEMP:", &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;
}
if(type == MBTK_TEMP_TYPE_RF) { // RF
err = at_tok_nextint(&line, &tmp_int);
if (err < 0)
{
goto exit;
}
*temp = (int16)tmp_int;
} else {
tmp_int = tmp_int / 1000;
*temp = (int16)tmp_int;
}
exit:
at_response_free(response);
return err;
}
/*
AT+CCLK?
+CCLK: "23/03/20,01:58:00+32"
OK
*/
static int req_cell_time_get(mbtk_sim_type_enum sim_id, ATPortType_enum port, char *data, int *cme_err)
{
ATResponse *response = NULL;
char *tmp_ptr = NULL;
int err = at_send_command_singleline(portType_2_portId(sim_id, port), "AT+CCLK?", "+CCLK:", &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_nextstr(&line, &tmp_ptr);
if (err < 0)
{
goto exit;
}
memcpy(data, tmp_ptr, strlen(tmp_ptr));
exit:
at_response_free(response);
return err;
}
/*
0: minimum functionality
1: full functionality
3: disable phone receive RF circuits.
4: disable phone both transmit and receive RF circuits
5: disable SIM
6: turn off full secondary receive.
-1: fail
*/
mbtk_radio_state_enum ril_radio_state_get(mbtk_sim_type_enum sim_id, ATPortType_enum port)
{
ATResponse *p_response = NULL;
int err;
char *line;
int ret;
err = at_send_command_singleline(portType_2_portId(sim_id, port), "AT+CFUN?", "+CFUN:", &p_response);
if (err < 0 || p_response->success == 0 || !p_response->p_intermediates)
{
// assume radio is off
goto done;
}
line = p_response->p_intermediates->line;
err = at_tok_start(&line);
if (err < 0) goto done;
err = at_tok_nextint(&line, &ret);
if (err < 0) goto done;
at_response_free(p_response);
ril_info.radio_state[sim_id] = (mbtk_radio_state_enum)ret;
return ril_info.radio_state[sim_id];
done:
at_response_free(p_response);
return MBTK_RADIO_STATE_UNKNOWN;
}
mbtk_ril_err_enum ril_radio_state_set(mbtk_sim_type_enum sim_id, ATPortType_enum port, mbtk_radio_state_enum state, bool reset)
{
int err;
ATResponse *p_response = NULL;
mbtk_ril_err_enum ret = MBTK_RIL_ERR_UNKNOWN;
if(state == ril_info.radio_state[sim_id]) {
LOGE("Radio state is same.");
//return MBTK_RIL_ERR_PARAMETER;
return MBTK_RIL_ERR_SUCCESS;
}
LOGI("Set radio state - %d", state);
char cmd[64] = {0};
if(reset) {
snprintf(cmd, sizeof(cmd), "AT+CFUN=%d,1", state);
} else {
snprintf(cmd, sizeof(cmd), "AT+CFUN=%d", state);
}
err = at_send_command(portType_2_portId(sim_id, port), cmd, &p_response);
if (err || !p_response->success) {
goto done;
}
if(state == MBTK_RADIO_STATE_FULL_FUNC) { // +CFUN=1
if(ril_radio_state_get(sim_id, port) == MBTK_RADIO_STATE_FULL_FUNC) { // success
ril_info.radio_state[sim_id] = MBTK_RADIO_STATE_FULL_FUNC;
ret = MBTK_RIL_ERR_SUCCESS;
LOGD("Radio open success.");
} else {
LOGW("Radio open fail.");
}
} else {
ril_info.radio_state[sim_id] = state;
ret = MBTK_RIL_ERR_SUCCESS;
LOGD("Set radio state to %d success.", state);
}
done:
at_response_free(p_response);
return ret;
}
/*
AT*POWERIND=0"
or
AT*POWERIND=1~31"
OK
AT*POWERIND=31,就相当于设置NETWORK、SIM、SMS、CS CALL、PS DATA变化时都不主动上报,
其中PS DATA目前暂时不支持,只是保留了这个标志位,0 means resume all.
AP power state: 1~31 means suspend,
bitmap:
bit0 - NETWORK;
bit1 - SIM;
bit2 - SMS;
bit3 - CS CALL
bit4 - PS DATA
*/
static int req_powerind_set(mbtk_sim_type_enum sim_id, ATPortType_enum port, uint8 state, int *cme_err)
{
ATResponse *response = NULL;
int err = -1;
if (state >= 0 && state < 32)
{
char cmd[100] = {0};
sprintf(cmd, "AT*POWERIND=%d", state);
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_md_version_get(mbtk_sim_type_enum sim_id, ATPortType_enum port,void *data, int *cme_err)
{
ATResponse *response = NULL;
int err = at_send_command_multiline(portType_2_portId(sim_id, port), "AT*CGMR", "", &response);
if (err < 0 || response->success == 0 || !response->p_intermediates)
{
*cme_err = at_get_cme_error(response);
goto exit;
}
ATLine* lines_ptr = response->p_intermediates;
char *line = NULL;
while(lines_ptr)
{
line = lines_ptr->line;
char *start = strstr(line, "FALCON_CP");
if(start)
{
char *end = strstr(start, "_Linux");
if(end)
{
end += strlen("_Linux");
int length = end - start;
if (length)
{
strncpy(data, start, length);
((char*)data)[length] = '\0';
break;
}
else
{
err = -1;
goto exit;
}
}
else
{
err = -1;
goto exit;
}
}
lines_ptr = lines_ptr->p_next;
}
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 dev_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_DEV_IMEI:
{
if(pack->data_len == 0 || pack->data == NULL) // Get IMEI
{
char imei[20] = {0};
if(req_imei_get(cli_info->sim_id, cli_info->port, imei, &cme_err) || strlen(imei) == 0 || 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 IMEI fail.");
}
else
{
ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, imei, strlen(imei));
}
}
else // Set IMEI(Unsupport).
{
err = MBTK_RIL_ERR_UNSUPPORTED;
LOG("Unsupport set IMEI.");
}
break;
}
case RIL_MSG_ID_DEV_SN:
{
if(pack->data_len == 0 || pack->data == NULL)
{
char sn[20] = {0};
if(req_sn_get(cli_info->sim_id, cli_info->port, sn, &cme_err) || strlen(sn) == 0 || 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 SN fail.");
}
else
{
ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, sn, strlen(sn));
}
}
else // Set
{
err = MBTK_RIL_ERR_UNSUPPORTED;
LOG("Unsupport set SN.");
}
break;
}
case RIL_MSG_ID_DEV_MEID:
{
if(pack->data_len == 0 || pack->data == NULL)
{
err = MBTK_RIL_ERR_UNSUPPORTED;
LOG("Support only for CDMA.");
}
else // Set
{
err = MBTK_RIL_ERR_UNSUPPORTED;
LOG("Unsupport set MEID.");
}
break;
}
case RIL_MSG_ID_DEV_VERSION:
{
if(pack->data_len == 0 || pack->data == NULL)
{
char version[50] = {0};
if(req_version_get(cli_info->sim_id, cli_info->port, version, &cme_err) || strlen(version) == 0 || 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 Version fail.");
}
else
{
ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, version, strlen(version));
}
}
else // Set
{
err = MBTK_RIL_ERR_UNSUPPORTED;
LOG("Unsupport set Version.");
}
break;
}
case RIL_MSG_ID_DEV_MODEL:
{
if(pack->data_len == 0 || pack->data == NULL)
{
char model[50] = {0};
if(req_model_get(cli_info->sim_id, cli_info->port, model, &cme_err) || strlen(model) == 0 || 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 Version fail.");
}
else
{
ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, model, strlen(model));
}
}
else // Set
{
err = MBTK_RIL_ERR_UNSUPPORTED;
LOG("Unsupport set Model.");
}
break;
}
case RIL_MSG_ID_DEV_VOLTE: // <uint8> 0:Close 1:Open
{
if(pack->data_len == 0 || pack->data == NULL) // Get VoLTE state.
{
int state;
if(req_volte_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 VoLTE 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 VoLTE state.
{
if(pack->data == NULL || pack->data_len != sizeof(uint8)
|| (*(pack->data) != 0 && *(pack->data) != 1))
{
err = MBTK_RIL_ERR_REQ_PARAMETER;
LOG("Set VOLTE parameter error.");
break;
}
uint8 on = *(pack->data);
if(req_volte_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 VoLTE 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);
// Restart is required to take effect.
// LOG("Will reboot system...");
}
}
break;
}
case RIL_MSG_ID_DEV_TEMP:
{
if(pack->data && pack->data_len == sizeof(uint8)) {
int16 temp;
mbtk_temp_type_enum type = (mbtk_temp_type_enum)(*(pack->data));
if(req_temp_get(cli_info->sim_id, cli_info->port, type, &temp, &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 temperature fail.");
}
else
{
ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, &temp, sizeof(int16));
}
} else {
err = MBTK_RIL_ERR_UNSUPPORTED;
LOG("Unsupport set Temperature.");
}
break;
}
case RIL_MSG_ID_DEV_CELL_TIME:
{
if(pack->data_len == 0 || pack->data == NULL) // Get Time
{
char time[100] = {0};
if(req_cell_time_get(cli_info->sim_id, cli_info->port, time, &cme_err) || strlen(time) == 0 || 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 cell time fail.");
}
else
{
ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, time, strlen(time));
}
}
else // Set Time
{
err = MBTK_RIL_ERR_UNSUPPORTED;
LOG("Unsupport set cell time.");
}
break;
}
case RIL_MSG_ID_DEV_MODEM:
{
if(pack->data_len == 0 || pack->data == NULL)
{
mbtk_radio_state_enum radio_state = ril_radio_state_get(cli_info->sim_id, cli_info->port);
if(radio_state == MBTK_RADIO_STATE_UNKNOWN)
{
err = MBTK_RIL_ERR_UNKNOWN;
LOG("Get Version fail.");
}
else
{
ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, &radio_state, sizeof(uint8));
}
}
else // Set
{
// <func><reset>
if(pack->data && pack->data_len == 2) {
mbtk_radio_state_enum radio_state = (mbtk_radio_state_enum)(*(pack->data));
bool reset = *(pack->data + 1);
err = ril_radio_state_set(cli_info->sim_id, cli_info->port, radio_state, reset);
if(MBTK_RIL_ERR_SUCCESS == err) {
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_FORMAT;
}
}
break;
}
case RIL_MSG_ID_DEV_POWERIND:
{
if(pack->data_len == 0 || pack->data == NULL)
{
err = MBTK_RIL_ERR_UNSUPPORTED;
LOG("Get POWERIND state UNSUPPORTED.");
}
else // Set powerind state.
{
uint8 state = *(pack->data);
if(req_powerind_set(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("Set POWERIND state fail.");
}
else
{
// pack_rsp_send(cli_info->fd, MBTK_INFO_ID_WAKEUP_STA_RSP, NULL, 0);
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_DEV_MD_VERSION_REQ:
{
if(pack->data_len == 0 || pack->data == NULL) // Get VERSION
{
char version[50] = {0};
if(req_md_version_get(cli_info->sim_id, cli_info->port,version, &cme_err) || strlen(version) == 0 || 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 MD Version fail.");
}
else
{
ril_rsp_pack_send(cli_info->sim_id, cli_info->port, cli_info->fd, pack->msg_id, pack->msg_index, version, strlen((char*)version));
}
}
break;
}
default:
{
err = MBTK_RIL_ERR_REQ_UNKNOWN;
LOG("Unknown request : %s", id2str(pack->msg_id));
break;
}
}
return err;
}