blob: 33b25a84e09760942d5f4d633ac4533806f29095 [file] [log] [blame]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <string.h>
#include "mbtk_ril.h"
#include "mbtk_list.h"
#include "mbtk_utils.h"
static uint16 ril_index = 1;
static int sock_read(int fd, uint8 *msg, int data_len)
{
memset(msg, 0, data_len);
int len = 0;
int read_len = 0;
while(1)
{
len = read(fd, msg + read_len, data_len - read_len);
if(len > 0)
{
read_len += len;
}
else if(len == 0)
{
LOG("read() end.");
break;
}
else
{
if(EAGAIN == errno)
{
LOG("Read end, lenght = %d", read_len);
}
else
{
LOG("read() error[%d].", errno);
}
break;
}
}
if(read_len > 0)
{
log_hex("DATA_RECV", msg, read_len);
return read_len;
}
else
{
return -1;
}
}
static int sock_write(int fd, uint8 *msg, int data_len)
{
int len = 0;
int write_len = 0;
while(write_len < data_len)
{
len = write(fd, msg + write_len, data_len - write_len);
if(len > 0)
{
write_len += len;
}
else if(len == 0)
{
LOG("write() end.");
break;
}
else
{
LOG("write() error[%d].", errno);
break;
}
}
if(write_len > 0)
{
// log_hex("DATA_SEND", msg, write_len);
return write_len;
}
else
{
return -1;
}
}
static int pack_num_check(const void* data, int data_len)
{
int count = 0;
int pack_len;
const uint8* ptr = (const uint8*)data;
while(ptr < (const uint8*)data + data_len)
{
if(RIL_SOCK_PACKET_TAG != byte_2_uint32(ptr, false))
{
LOG("pack_num_check() - TAG error.");
break;
}
ptr += sizeof(uint32);
pack_len = byte_2_uint16(ptr, false);
if(pack_len < RIL_SOCK_PACK_LEN_MIN - RIL_SOCK_PACK_EXTRA_LEN)
{
LOG("pack_num_check() - Packet length error.");
break;
}
ptr += sizeof(uint16);
ptr += pack_len;
count++;
}
return count;
}
char* type2str(ril_msg_type_enum type)
{
switch(type)
{
case RIL_MSG_TYPE_REQ:
return "REQ";
case RIL_MSG_TYPE_RSP:
return "RSP";
case RIL_MSG_TYPE_IND:
return "IND";
default:
{
return "UNKNOWN";
}
}
}
char* apn2str(mbtk_ip_type_enum type)
{
switch(type)
{
case MBTK_IP_TYPE_IP:
return "IP";
case MBTK_IP_TYPE_IPV6:
return "IPV6";
case MBTK_IP_TYPE_IPV4V6:
return "IPV4V6";
case MBTK_IP_TYPE_PPP:
return "PPP";
default:
{
return "UNKNOWN";
}
}
}
/*
IPv6 : 254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239 -> uint128
*/
int str_2_ipv6(const void *ip_str, void *ipv6)
{
const char *ptr = (const char*)ip_str;
uint8 *ipv6_ptr = (uint8*)ipv6;
ipv6_ptr[0] = (uint8)atoi(ptr);
int i = 1;
while(i < 16) {
ptr = (const char*)strstr(ptr, ".");
if(ptr == NULL)
return -1;
ptr++;
ipv6_ptr[i] = (uint8)atoi(ptr);
i++;
}
return 0;
}
/*
IPv6 : uint128 -> fe80::215:1dff:fe81:484c
*/
int ipv6_2_str(const void *ipv6, void *ipv6_str)
{
const uint8 *ptr = (const uint8*)ipv6;
uint8 *ipv6_ptr = (uint8*)ipv6_str;
int i = 0;
int index = 0;
while(i < 16) {
index += sprintf((char*)ipv6_ptr + index, "%02x%02x", ptr[i], ptr[i + 1]);
index += sprintf((char*)ipv6_ptr + index, ":");
i += 2;
}
ipv6_ptr[index - 1] = '\0'; // Delete last ':'
return 0;
}
char* id2str(int id)
{
switch(id)
{
// <string> IMEI
case RIL_MSG_ID_DEV_IMEI:
return "IMEI";
// <string> SN
case RIL_MSG_ID_DEV_SN:
return "SN";
// <string> MEID
case RIL_MSG_ID_DEV_MEID:
return "MEID";
// <string> VERSION
case RIL_MSG_ID_DEV_VERSION:
return "VERSION";
case RIL_MSG_ID_DEV_MODEL:
return "MODEL";
// <uint8> 0:Close 1:Open
case RIL_MSG_ID_DEV_VOLTE:
return "VOLTE";
// <string> Temperature
case RIL_MSG_ID_DEV_TEMP: // Temperature
return "TEMPERATURE";
case RIL_MSG_ID_DEV_CELL_TIME:
return "CELL_TIME";
case RIL_MSG_ID_DEV_MODEM:
return "MODEM";
case RIL_MSG_ID_DEV_POWERIND:
return "POWERIND";
// Sim Information
case RIL_MSG_ID_DEV_MD_VERSION_REQ:
return "MD_VERSION";
// <uint8> 0:NOT_EXIST 1:READY ...
case RIL_MSG_ID_SIM_STATE:
return "SIM_STATE";
case RIL_MSG_ID_SIM_TYPE:
return "SIM_TYPE";
// <string> IMSI
case RIL_MSG_ID_SIM_IMSI:
return "IMSI";
// <string> ICCID
case RIL_MSG_ID_SIM_ICCID:
return "ICCID";
// <string> Phone Number
case RIL_MSG_ID_SIM_PN:
return "PHONE_NUMBER";
case RIL_MSG_ID_SIM_LOCK:
return "SIM_LOCK";
case RIL_MSG_ID_SIM_PINPUK_TIMES:
return "SIM_PINPUK_TIMES";
case RIL_MSG_ID_SIM_PLMN:
return "SIM_PLMN";
case RIL_MSG_ID_NET_AVAILABLE:
return "NET_AVAILABLE";
case RIL_MSG_ID_NET_SEL_MODE:
return "NET_SEL_MODE";
case RIL_MSG_ID_NET_BAND:
return "NET_BNAD";
// <uint16>[4] rssi,rscp,rsrp,snr
case RIL_MSG_ID_NET_SIGNAL:
return "SIGNAL";
case RIL_MSG_ID_NET_REG:
return "NET_REG";
// <string> cmnet/ctnet/3gnet/...
case RIL_MSG_ID_DATA_CALL_APN:
return "APN";
// Lock net/cell/frequency
case RIL_MSG_ID_NET_CELL:
return "NET_CELL";
case RIL_MSG_ID_NET_OOS:
return "NET_OOS";
case RIL_MSG_ID_DATA_CALL_OPT:
return "DATA_CALL";
// Call Information
case RIL_MSG_ID_CALL_STATE:
return "CALL_STATE";
case RIL_MSG_ID_CALL_START:
return "CALL_START";
case RIL_MSG_ID_CALL_ANSWER:
return "CALL_ANSWER";
case RIL_MSG_ID_CALL_HANGUP:
return "CALL_HANGUP";
case RIL_MSG_ID_CALL_HANGUP_A:
return "CALL_HANGUP_A";
case RIL_MSG_ID_CALL_HANGUP_B:
return "CALL_HANGUP_B";
case RIL_MSG_ID_CALL_HANGUP_C:
return "CALL_HANGUP_C";
case RIL_MSG_ID_CALL_WAITIN:
return "CALL_WAITIN";
case RIL_MSG_ID_CALL_MUTE:
return "CALL_MUTE";
case RIL_MSG_ID_CALL_DTMF:
return "CALL_DTMF";
// SMS Information
case RIL_MSG_ID_SMS_STATE:
return "SMS_STATE";
case RIL_MSG_ID_SMS_CMGF:
return "SMS_CMGF";
case RIL_MSG_ID_SMS_CPMS:
return "SMS_CPMS";
case RIL_MSG_ID_SMS_CMGS:
return "SMS_CMGS";
case RIL_MSG_ID_SMS_CMSS:
return "SMS_CMSS";
case RIL_MSG_ID_SMS_CMGR:
return "SMS_CMGR";
case RIL_MSG_ID_SMS_CMGW:
return "SMS_CMGW";
case RIL_MSG_ID_SMS_CMGD:
return "SMS_CMGD";
case RIL_MSG_ID_SMS_CMGL:
return "SMS_CMGL";
case RIL_MSG_ID_SMS_CSCA:
return "SMS_CSCA";
case RIL_MSG_ID_SMS_CSMP:
return "SMS_CSMP";
case RIL_MSG_ID_SMS_CSCB:
return "SMS_CSCB";
case RIL_MSG_ID_SMS_CNMI:
return "SMS_CNMI";
// PhoneBook Information
case RIL_MSG_ID_PB_STATE:
return "PB_STATE";
case RIL_MSG_ID_ECALL_MSDCFG:
return "ECALL_MSDCFG";
case RIL_MSG_ID_ECALL_MSDGEN:
return "ECALL_MSDGEN";
case RIL_MSG_ID_ECALL_MSD:
return "ECALL_MSD";
case RIL_MSG_ID_ECALL_PUSH:
return "ECALL_PUSH";
case RIL_MSG_ID_ECALL_ONLY:
return "ECALL_ONLY";
case RIL_MSG_ID_ECALL_REG:
return "ECALL_REG";
case RIL_MSG_ID_ECALL_DIAL:
return "ECALL_DIAL";
case RIL_MSG_ID_ECALL_MODE:
return "ECALL_MODE";
case RIL_MSG_ID_ECALL_CFG:
return "ECALL_CFG";
case RIL_MSG_ID_ECALL_SMS_NUM:
return "ECALL_SMS_NUM";
case RIL_MSG_ID_ECALL_MUTESPK:
return "ECALL_MUTESPK";
case RIL_MSG_ID_ECALL_DSP_GAIN:
return "ECALL_DSP_GAIN";
// IND Information
// <uint8> State
case RIL_MSG_ID_IND_SER_STATE_CHANGE:
return "IND_SER_STATE";
// <uint8> State
case RIL_MSG_ID_IND_NET_REG_STATE_CHANGE:
return "IND_NET_REG_STATE";
// <uint8> State
case RIL_MSG_ID_IND_CALL_STATE_CHANGE:
return "IND_CALL_STATE";
// <uint8> State
case RIL_MSG_ID_IND_SMS_STATE_CHANGE:
return "IND_SMS_STATE";
// <uint8> State
case RIL_MSG_ID_IND_RADIO_STATE_CHANGE:
return "IND_RADIO_STATE";
// <uint8> State
case RIL_MSG_ID_IND_SIM_STATE_CHANGE:
return "IND_SIM_STATE";
// <uint8> State
case RIL_MSG_ID_IND_PDP_STATE_CHANGE:
return "IND_PDP_STATE";
// <uint8> State
case RIL_MSG_ID_IND_SIGNAL_STATE_CHANGE:
return "IND_SIGNAL_STATE";
case RIL_MSG_ID_IND_ECALL_STATE_CHANGE:
return "IND_ECALL_STATE_CHANGE";
default:
{
return "UNKNOWN";
}
}
}
char* err2str(mbtk_ril_err_enum err)
{
switch(err)
{
case MBTK_RIL_ERR_SUCCESS:
return "SUCCESS";
case MBTK_RIL_ERR_FORMAT:
return "ERR_FORMAT";
case MBTK_RIL_ERR_REQ_UNKNOWN:
return "ERR_REQ_UNKNOWN";
case MBTK_RIL_ERR_REQ_PARAMETER:
return "ERR_REQ_PARAMETER";
case MBTK_RIL_ERR_UNSUPPORTED:
return "ERR_UNSUPPORTED";
case MBTK_RIL_ERR_MEMORY:
return "ERR_MEMORY";
case MBTK_RIL_ERR_IND_FULL:
return "ERR_IND_FULL";
case MBTK_RIL_ERR_IND_UNKNOWN:
return "ERR_IND_UNKNOWN";
default:
{
if(err >= MBTK_RIL_ERR_CME) {
return "CME ERROR";
}
return "UNKNOWN";
}
}
}
void *mbtk_memcpy(const void *src, unsigned int n)
{
void *dest = malloc(n);
if(dest) {
return memcpy(dest, src, n);
} else {
return NULL;
}
}
/*
0 GSM
1 GSM_COMPACT
2 UTRAN
3 GSM_EGPRS
4 UTRAN_HSDPA
5 UTRAN_HSUPA
6 UTRAN_HSDPA_HSUPA
7 EUTRAN
8 ECGSM
*/
mbtk_net_type_enum mbtk_net_type_get(mbtk_radio_technology_enum radio_tech)
{
switch(radio_tech)
{
case MBTK_RADIO_TECH_GSM:
case MBTK_RADIO_TECH_GSM_COMPACT:
case MBTK_RADIO_TECH_GSM_EGPRS:
case MBTK_RADIO_TECH_UTRAN_HSPA:
{
return MBTK_NET_TYPE_GSM;
}
case MBTK_RADIO_TECH_UTRAN:
case MBTK_RADIO_TECH_UTRAN_HSDPA:
case MBTK_RADIO_TECH_UTRAN_HSUPA:
case MBTK_RADIO_TECH_UTRAN_HSDPA_HSUPA:
{
return MBTK_NET_TYPE_UMTS;
}
case MBTK_RADIO_TECH_E_UTRAN:
{
return MBTK_NET_TYPE_LTE;
}
default:
{
return MBTK_NET_TYPE_UNKNOWN;
}
}
}
void ril_msg_pack_free(ril_msg_pack_info_t* pack)
{
if(pack) {
LOGV("Free msg pack - %s", id2str(pack->msg_id));
if(pack->data) {
free(pack->data);
}
free(pack);
}
}
ril_msg_pack_info_t* ril_msg_pack_creat(ATPortType_enum port, int msg_type, int msg_id, int msg_index, const void *data, int data_len)
{
ril_msg_pack_info_t *pack = (ril_msg_pack_info_t *)malloc(sizeof(ril_msg_pack_info_t));
if(!pack)
{
LOGE("malloc() error[%d]", errno);
return NULL;
}
pack->tag = RIL_SOCK_PACKET_TAG;
pack->at_port = (uint8)port;
if(msg_index < 0) {
pack->msg_index = ril_index++;
} else {
pack->msg_index = msg_index;
}
pack->msg_type = (uint16)msg_type;
pack->msg_id = (uint16)msg_id;
pack->err = (uint16)0;
if(data && data_len > 0) {
pack->msg_len = data_len + RIL_SOCK_PACK_LEN_MIN - RIL_SOCK_PACK_EXTRA_LEN;
pack->data_len = (uint16)data_len;
pack->data = (uint8*)malloc(data_len);
if(pack->data == NULL) {
LOGE("malloc(%d) fail.", data_len);
free(pack);
return NULL;
}
memcpy(pack->data, data, data_len);
} else {
pack->msg_len = RIL_SOCK_PACK_LEN_MIN - RIL_SOCK_PACK_EXTRA_LEN;
pack->data_len = (uint16)0;
pack->data = NULL;
}
return pack;
}
int ril_pack_send(int fd, ril_msg_pack_info_t *pack)
{
if(!pack)
{
LOG("Packet is NULL.");
return -1;
}
uint8 buff[RIL_SOCK_MSG_LEN_MAX] = {0};
if(pack->data && pack->data_len > 0) {
memcpy(buff, pack, RIL_SOCK_PACK_LEN_MIN);
memcpy(buff + RIL_SOCK_PACK_LEN_MIN, pack->data, pack->data_len);
return sock_write(fd, buff, RIL_SOCK_PACK_LEN_MIN + pack->data_len);
} else {
memcpy(buff, pack, RIL_SOCK_PACK_LEN_MIN);
return sock_write(fd, buff, RIL_SOCK_PACK_LEN_MIN);
}
}
ril_msg_pack_info_t** ril_pack_recv(int fd, bool is_server, mbtk_ril_err_enum *err)
{
uint8 msg[RIL_SOCK_MSG_LEN_MAX + 1];
*err = MBTK_RIL_ERR_SUCCESS;
int len = sock_read(fd, msg, RIL_SOCK_MSG_LEN_MAX + 1);
if(len < RIL_SOCK_PACK_LEN_MIN)
{
if(len > 0)
{
*err = MBTK_RIL_ERR_FORMAT;
LOGE("Insufficient packet data.");
}
return NULL;
}
int pack_count = pack_num_check(msg, len);
LOGD("Packet number : %d", pack_count);
if(pack_count < 1)
{
*err = MBTK_RIL_ERR_FORMAT;
LOGE("Packet not found.");
return NULL;
}
uint8 *ptr = msg;
ril_msg_pack_info_t** packs = (ril_msg_pack_info_t**)malloc(sizeof(ril_msg_pack_info_t*) * (pack_count + 1));
int i = 0;
while(i < pack_count)
{
packs[i] = (ril_msg_pack_info_t*)malloc(sizeof(ril_msg_pack_info_t));
if(packs[i] == NULL){
*err = MBTK_RIL_ERR_MEMORY;
goto error;
}
memcpy(packs[i], ptr, RIL_SOCK_PACK_LEN_MIN);
// TAG
if(RIL_SOCK_PACKET_TAG != packs[i]->tag)
{
*err = MBTK_RIL_ERR_FORMAT;
LOGE("Packet TAG error.");
goto error;
}
if(is_server)
{
// For server,"info_type" must by REQ or IND(Register IND).
if(packs[i]->msg_type != RIL_MSG_TYPE_REQ && packs[i]->msg_type != RIL_MSG_TYPE_IND)
{
*err = MBTK_RIL_ERR_FORMAT;
LOGE("Packet Type error : %d", packs[i]->msg_type);
goto error;
}
}
else
{
// For client,"info_type" must by RSP or IND.
if(packs[i]->msg_type != RIL_MSG_TYPE_RSP && packs[i]->msg_type != RIL_MSG_TYPE_IND)
{
*err = MBTK_RIL_ERR_FORMAT;
LOG("Packet Type error.");
goto error;
}
}
ptr += RIL_SOCK_PACK_LEN_MIN;
if(packs[i]->data_len > 0) {
packs[i]->data = (uint8*)malloc(packs[i]->data_len);
if(packs[i]->data == NULL) {
*err = MBTK_RIL_ERR_MEMORY;
goto error;
}
memcpy(packs[i]->data, ptr, packs[i]->data_len);
ptr += packs[i]->data_len;
} else {
packs[i]->data = NULL;
}
i++;
}
packs[i] = NULL;
return packs;
error:
LOGD("mbtk_ril_pack_recv error, will free().");
if(packs)
{
ril_msg_pack_info_t** pack_ptr = packs;
while(*pack_ptr)
{
ril_msg_pack_free(*pack_ptr);
pack_ptr++;
}
free(packs);
}
return NULL;
}