| #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; |
| } |
| |