Files
ofono/ofono/drivers/ril/ril_util.c

482 lines
13 KiB
C

/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ril_util.h"
#include "ril_log.h"
#include <grilio_channel.h>
#include <gutil_misc.h>
#include <sys/socket.h>
#include <ctype.h>
#include "common.h"
#include "netreg.h"
#define RIL_PROTO_IP_STR "IP"
#define RIL_PROTO_IPV6_STR "IPV6"
#define RIL_PROTO_IPV4V6_STR "IPV4V6"
const char *ril_error_to_string(int error)
{
#define RIL_E_(name) case RIL_E_##name: return #name
#define GRILIO_E_(name) case GRILIO_STATUS_##name: return "GRILIO_" #name
static char unknown[12];
switch (error) {
case RIL_E_SUCCESS: return "OK";
GRILIO_E_(TIMEOUT);
GRILIO_E_(CANCELLED);
RIL_E_(RADIO_NOT_AVAILABLE);
RIL_E_(GENERIC_FAILURE);
RIL_E_(PASSWORD_INCORRECT);
RIL_E_(SIM_PIN2);
RIL_E_(SIM_PUK2);
RIL_E_(REQUEST_NOT_SUPPORTED);
RIL_E_(CANCELLED);
RIL_E_(OP_NOT_ALLOWED_DURING_VOICE_CALL);
RIL_E_(OP_NOT_ALLOWED_BEFORE_REG_TO_NW);
RIL_E_(SMS_SEND_FAIL_RETRY);
RIL_E_(SIM_ABSENT);
RIL_E_(SUBSCRIPTION_NOT_AVAILABLE);
RIL_E_(MODE_NOT_SUPPORTED);
RIL_E_(FDN_CHECK_FAILURE);
RIL_E_(ILLEGAL_SIM_OR_ME);
RIL_E_(MISSING_RESOURCE);
RIL_E_(NO_SUCH_ELEMENT);
RIL_E_(DIAL_MODIFIED_TO_USSD);
RIL_E_(DIAL_MODIFIED_TO_SS);
RIL_E_(DIAL_MODIFIED_TO_DIAL);
RIL_E_(USSD_MODIFIED_TO_DIAL);
RIL_E_(USSD_MODIFIED_TO_SS);
RIL_E_(USSD_MODIFIED_TO_USSD);
RIL_E_(SS_MODIFIED_TO_DIAL);
RIL_E_(SS_MODIFIED_TO_USSD);
RIL_E_(SUBSCRIPTION_NOT_SUPPORTED);
RIL_E_(SS_MODIFIED_TO_SS);
RIL_E_(LCE_NOT_SUPPORTED);
RIL_E_(NO_MEMORY);
RIL_E_(INTERNAL_ERR);
RIL_E_(SYSTEM_ERR);
RIL_E_(MODEM_ERR);
RIL_E_(INVALID_STATE);
RIL_E_(NO_RESOURCES);
RIL_E_(SIM_ERR);
RIL_E_(INVALID_ARGUMENTS);
RIL_E_(INVALID_SIM_STATE);
RIL_E_(INVALID_MODEM_STATE);
RIL_E_(INVALID_CALL_ID);
RIL_E_(NO_SMS_TO_ACK);
RIL_E_(NETWORK_ERR);
RIL_E_(REQUEST_RATE_LIMITED);
RIL_E_(SIM_BUSY);
RIL_E_(SIM_FULL);
RIL_E_(NETWORK_REJECT);
RIL_E_(OPERATION_NOT_ALLOWED);
RIL_E_(EMPTY_RECORD);
RIL_E_(INVALID_SMS_FORMAT);
RIL_E_(ENCODING_ERR);
RIL_E_(INVALID_SMSC_ADDRESS);
RIL_E_(NO_SUCH_ENTRY);
RIL_E_(NETWORK_NOT_READY);
RIL_E_(NOT_PROVISIONED);
RIL_E_(NO_SUBSCRIPTION);
RIL_E_(NO_NETWORK_FOUND);
RIL_E_(DEVICE_IN_USE);
RIL_E_(ABORTED);
RIL_E_(INVALID_RESPONSE);
default:
snprintf(unknown, sizeof(unknown), "%d", error);
return unknown;
}
}
const char *ril_request_to_string(guint request)
{
#define RIL_REQUEST_(name) case RIL_REQUEST_##name: return #name
static char unknown[24];
switch (request) {
RIL_REQUEST_(GET_SIM_STATUS);
RIL_REQUEST_(ENTER_SIM_PIN);
RIL_REQUEST_(ENTER_SIM_PUK);
RIL_REQUEST_(ENTER_SIM_PIN2);
RIL_REQUEST_(ENTER_SIM_PUK2);
RIL_REQUEST_(CHANGE_SIM_PIN);
RIL_REQUEST_(CHANGE_SIM_PIN2);
RIL_REQUEST_(ENTER_NETWORK_DEPERSONALIZATION);
RIL_REQUEST_(GET_CURRENT_CALLS);
RIL_REQUEST_(DIAL);
RIL_REQUEST_(GET_IMSI);
RIL_REQUEST_(HANGUP);
RIL_REQUEST_(HANGUP_WAITING_OR_BACKGROUND);
RIL_REQUEST_(HANGUP_FOREGROUND_RESUME_BACKGROUND);
RIL_REQUEST_(SWITCH_HOLDING_AND_ACTIVE);
RIL_REQUEST_(CONFERENCE);
RIL_REQUEST_(UDUB);
RIL_REQUEST_(LAST_CALL_FAIL_CAUSE);
RIL_REQUEST_(SIGNAL_STRENGTH);
RIL_REQUEST_(VOICE_REGISTRATION_STATE);
RIL_REQUEST_(DATA_REGISTRATION_STATE);
RIL_REQUEST_(OPERATOR);
RIL_REQUEST_(RADIO_POWER);
RIL_REQUEST_(DTMF);
RIL_REQUEST_(SEND_SMS);
RIL_REQUEST_(SEND_SMS_EXPECT_MORE);
RIL_REQUEST_(SETUP_DATA_CALL);
RIL_REQUEST_(SIM_IO);
RIL_REQUEST_(SEND_USSD);
RIL_REQUEST_(CANCEL_USSD);
RIL_REQUEST_(GET_CLIR);
RIL_REQUEST_(SET_CLIR);
RIL_REQUEST_(QUERY_CALL_FORWARD_STATUS);
RIL_REQUEST_(SET_CALL_FORWARD);
RIL_REQUEST_(QUERY_CALL_WAITING);
RIL_REQUEST_(SET_CALL_WAITING);
RIL_REQUEST_(SMS_ACKNOWLEDGE);
RIL_REQUEST_(GET_IMEI);
RIL_REQUEST_(GET_IMEISV);
RIL_REQUEST_(ANSWER);
RIL_REQUEST_(DEACTIVATE_DATA_CALL);
RIL_REQUEST_(QUERY_FACILITY_LOCK);
RIL_REQUEST_(SET_FACILITY_LOCK);
RIL_REQUEST_(CHANGE_BARRING_PASSWORD);
RIL_REQUEST_(QUERY_NETWORK_SELECTION_MODE);
RIL_REQUEST_(SET_NETWORK_SELECTION_AUTOMATIC);
RIL_REQUEST_(SET_NETWORK_SELECTION_MANUAL);
RIL_REQUEST_(QUERY_AVAILABLE_NETWORKS);
RIL_REQUEST_(DTMF_START);
RIL_REQUEST_(DTMF_STOP);
RIL_REQUEST_(BASEBAND_VERSION);
RIL_REQUEST_(SEPARATE_CONNECTION);
RIL_REQUEST_(SET_MUTE);
RIL_REQUEST_(GET_MUTE);
RIL_REQUEST_(QUERY_CLIP);
RIL_REQUEST_(LAST_DATA_CALL_FAIL_CAUSE);
RIL_REQUEST_(DATA_CALL_LIST);
RIL_REQUEST_(RESET_RADIO);
RIL_REQUEST_(OEM_HOOK_RAW);
RIL_REQUEST_(OEM_HOOK_STRINGS);
RIL_REQUEST_(SCREEN_STATE);
RIL_REQUEST_(SET_SUPP_SVC_NOTIFICATION);
RIL_REQUEST_(WRITE_SMS_TO_SIM);
RIL_REQUEST_(DELETE_SMS_ON_SIM);
RIL_REQUEST_(SET_BAND_MODE);
RIL_REQUEST_(QUERY_AVAILABLE_BAND_MODE);
RIL_REQUEST_(STK_GET_PROFILE);
RIL_REQUEST_(STK_SET_PROFILE);
RIL_REQUEST_(STK_SEND_ENVELOPE_COMMAND);
RIL_REQUEST_(STK_SEND_TERMINAL_RESPONSE);
RIL_REQUEST_(STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM);
RIL_REQUEST_(EXPLICIT_CALL_TRANSFER);
RIL_REQUEST_(SET_PREFERRED_NETWORK_TYPE);
RIL_REQUEST_(GET_PREFERRED_NETWORK_TYPE);
RIL_REQUEST_(GET_NEIGHBORING_CELL_IDS);
RIL_REQUEST_(SET_LOCATION_UPDATES);
RIL_REQUEST_(CDMA_SET_SUBSCRIPTION_SOURCE);
RIL_REQUEST_(CDMA_SET_ROAMING_PREFERENCE);
RIL_REQUEST_(CDMA_QUERY_ROAMING_PREFERENCE);
RIL_REQUEST_(SET_TTY_MODE);
RIL_REQUEST_(QUERY_TTY_MODE);
RIL_REQUEST_(CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE);
RIL_REQUEST_(CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE);
RIL_REQUEST_(CDMA_FLASH);
RIL_REQUEST_(CDMA_BURST_DTMF);
RIL_REQUEST_(CDMA_VALIDATE_AND_WRITE_AKEY);
RIL_REQUEST_(CDMA_SEND_SMS);
RIL_REQUEST_(CDMA_SMS_ACKNOWLEDGE);
RIL_REQUEST_(GSM_GET_BROADCAST_SMS_CONFIG);
RIL_REQUEST_(GSM_SET_BROADCAST_SMS_CONFIG);
RIL_REQUEST_(GSM_SMS_BROADCAST_ACTIVATION);
RIL_REQUEST_(CDMA_GET_BROADCAST_SMS_CONFIG);
RIL_REQUEST_(CDMA_SET_BROADCAST_SMS_CONFIG);
RIL_REQUEST_(CDMA_SMS_BROADCAST_ACTIVATION);
RIL_REQUEST_(CDMA_SUBSCRIPTION);
RIL_REQUEST_(CDMA_WRITE_SMS_TO_RUIM);
RIL_REQUEST_(CDMA_DELETE_SMS_ON_RUIM);
RIL_REQUEST_(DEVICE_IDENTITY);
RIL_REQUEST_(EXIT_EMERGENCY_CALLBACK_MODE);
RIL_REQUEST_(GET_SMSC_ADDRESS);
RIL_REQUEST_(SET_SMSC_ADDRESS);
RIL_REQUEST_(REPORT_SMS_MEMORY_STATUS);
RIL_REQUEST_(REPORT_STK_SERVICE_IS_RUNNING);
RIL_REQUEST_(CDMA_GET_SUBSCRIPTION_SOURCE);
RIL_REQUEST_(ISIM_AUTHENTICATION);
RIL_REQUEST_(ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU);
RIL_REQUEST_(STK_SEND_ENVELOPE_WITH_STATUS);
RIL_REQUEST_(VOICE_RADIO_TECH);
RIL_REQUEST_(GET_CELL_INFO_LIST);
RIL_REQUEST_(SET_UNSOL_CELL_INFO_LIST_RATE);
RIL_REQUEST_(SET_INITIAL_ATTACH_APN);
RIL_REQUEST_(IMS_REGISTRATION_STATE);
RIL_REQUEST_(IMS_SEND_SMS);
RIL_REQUEST_(SIM_TRANSMIT_APDU_BASIC);
RIL_REQUEST_(SIM_OPEN_CHANNEL);
RIL_REQUEST_(SIM_CLOSE_CHANNEL);
RIL_REQUEST_(SIM_TRANSMIT_APDU_CHANNEL);
RIL_REQUEST_(NV_READ_ITEM);
RIL_REQUEST_(NV_WRITE_ITEM);
RIL_REQUEST_(NV_WRITE_CDMA_PRL);
RIL_REQUEST_(NV_RESET_CONFIG);
RIL_REQUEST_(SET_UICC_SUBSCRIPTION);
RIL_REQUEST_(ALLOW_DATA);
RIL_REQUEST_(GET_HARDWARE_CONFIG);
RIL_REQUEST_(SIM_AUTHENTICATION);
RIL_REQUEST_(GET_DC_RT_INFO);
RIL_REQUEST_(SET_DC_RT_INFO_RATE);
RIL_REQUEST_(SET_DATA_PROFILE);
RIL_REQUEST_(SHUTDOWN);
RIL_REQUEST_(GET_RADIO_CAPABILITY);
RIL_REQUEST_(SET_RADIO_CAPABILITY);
RIL_REQUEST_(START_LCE);
RIL_REQUEST_(STOP_LCE);
RIL_REQUEST_(GET_ACTIVITY_INFO);
RIL_REQUEST_(GET_CARRIER_RESTRICTIONS);
RIL_REQUEST_(SEND_DEVICE_STATE);
RIL_REQUEST_(SET_UNSOLICITED_RESPONSE_FILTER);
RIL_REQUEST_(SET_SIM_CARD_POWER);
RIL_REQUEST_(SET_CARRIER_INFO_IMSI_ENCRYPTION);
RIL_REQUEST_(START_NETWORK_SCAN);
RIL_REQUEST_(STOP_NETWORK_SCAN);
RIL_REQUEST_(START_KEEPALIVE);
RIL_REQUEST_(STOP_KEEPALIVE);
case RIL_RESPONSE_ACKNOWLEDGEMENT:
return "RESPONSE_ACK";
default:
snprintf(unknown, sizeof(unknown), "RIL_REQUEST_%d", request);
return unknown;
}
}
const char *ril_unsol_event_to_string(guint event)
{
#define RIL_UNSOL_(name) case RIL_UNSOL_##name: return #name
static char unknown[24];
switch (event) {
RIL_UNSOL_(RESPONSE_RADIO_STATE_CHANGED);
RIL_UNSOL_(RESPONSE_CALL_STATE_CHANGED);
RIL_UNSOL_(RESPONSE_VOICE_NETWORK_STATE_CHANGED);
RIL_UNSOL_(RESPONSE_NEW_SMS);
RIL_UNSOL_(RESPONSE_NEW_SMS_STATUS_REPORT);
RIL_UNSOL_(RESPONSE_NEW_SMS_ON_SIM);
RIL_UNSOL_(ON_USSD);
RIL_UNSOL_(ON_USSD_REQUEST);
RIL_UNSOL_(NITZ_TIME_RECEIVED);
RIL_UNSOL_(SIGNAL_STRENGTH);
RIL_UNSOL_(DATA_CALL_LIST_CHANGED);
RIL_UNSOL_(SUPP_SVC_NOTIFICATION);
RIL_UNSOL_(STK_SESSION_END);
RIL_UNSOL_(STK_PROACTIVE_COMMAND);
RIL_UNSOL_(STK_EVENT_NOTIFY);
RIL_UNSOL_(STK_CALL_SETUP);
RIL_UNSOL_(SIM_SMS_STORAGE_FULL);
RIL_UNSOL_(SIM_REFRESH);
RIL_UNSOL_(CALL_RING);
RIL_UNSOL_(RESPONSE_SIM_STATUS_CHANGED);
RIL_UNSOL_(RESPONSE_CDMA_NEW_SMS);
RIL_UNSOL_(RESPONSE_NEW_BROADCAST_SMS);
RIL_UNSOL_(CDMA_RUIM_SMS_STORAGE_FULL);
RIL_UNSOL_(RESTRICTED_STATE_CHANGED);
RIL_UNSOL_(ENTER_EMERGENCY_CALLBACK_MODE);
RIL_UNSOL_(CDMA_CALL_WAITING);
RIL_UNSOL_(CDMA_OTA_PROVISION_STATUS);
RIL_UNSOL_(CDMA_INFO_REC);
RIL_UNSOL_(OEM_HOOK_RAW);
RIL_UNSOL_(RINGBACK_TONE);
RIL_UNSOL_(RESEND_INCALL_MUTE);
RIL_UNSOL_(CDMA_SUBSCRIPTION_SOURCE_CHANGED);
RIL_UNSOL_(CDMA_PRL_CHANGED);
RIL_UNSOL_(EXIT_EMERGENCY_CALLBACK_MODE);
RIL_UNSOL_(RIL_CONNECTED);
RIL_UNSOL_(VOICE_RADIO_TECH_CHANGED);
RIL_UNSOL_(CELL_INFO_LIST);
RIL_UNSOL_(RESPONSE_IMS_NETWORK_STATE_CHANGED);
RIL_UNSOL_(UICC_SUBSCRIPTION_STATUS_CHANGED);
RIL_UNSOL_(SRVCC_STATE_NOTIFY);
RIL_UNSOL_(HARDWARE_CONFIG_CHANGED);
RIL_UNSOL_(DC_RT_INFO_CHANGED);
RIL_UNSOL_(RADIO_CAPABILITY);
RIL_UNSOL_(ON_SS);
RIL_UNSOL_(STK_CC_ALPHA_NOTIFY);
default:
snprintf(unknown, sizeof(unknown), "RIL_UNSOL_%d", event);
return unknown;
}
}
const char *ril_radio_state_to_string(int radio_state)
{
#define RADIO_STATE_(name) case RADIO_STATE_##name: return #name
static char unknown[16];
switch (radio_state) {
RADIO_STATE_(OFF);
RADIO_STATE_(UNAVAILABLE);
RADIO_STATE_(SIM_NOT_READY);
RADIO_STATE_(SIM_LOCKED_OR_ABSENT);
RADIO_STATE_(SIM_READY);
RADIO_STATE_(RUIM_NOT_READY);
RADIO_STATE_(RUIM_READY);
RADIO_STATE_(RUIM_LOCKED_OR_ABSENT);
RADIO_STATE_(NV_NOT_READY);
RADIO_STATE_(NV_READY);
RADIO_STATE_(ON);
default:
snprintf(unknown, sizeof(unknown), "%d (?)", radio_state);
return unknown;
}
}
const char *ril_protocol_from_ofono(enum ofono_gprs_proto proto)
{
switch (proto) {
case OFONO_GPRS_PROTO_IPV6:
return RIL_PROTO_IPV6_STR;
case OFONO_GPRS_PROTO_IPV4V6:
return RIL_PROTO_IPV4V6_STR;
case OFONO_GPRS_PROTO_IP:
return RIL_PROTO_IP_STR;
}
return NULL;
}
int ril_protocol_to_ofono(const gchar *str)
{
if (str) {
if (!strcmp(str, RIL_PROTO_IPV6_STR)) {
return OFONO_GPRS_PROTO_IPV6;
} else if (!strcmp(str, RIL_PROTO_IPV4V6_STR)) {
return OFONO_GPRS_PROTO_IPV4V6;
} else if (!strcmp(str, RIL_PROTO_IP_STR)) {
return OFONO_GPRS_PROTO_IP;
}
}
return -1;
}
enum ril_auth ril_auth_method_from_ofono(enum ofono_gprs_auth_method auth)
{
switch (auth) {
case OFONO_GPRS_AUTH_METHOD_NONE:
return RIL_AUTH_NONE;
case OFONO_GPRS_AUTH_METHOD_CHAP:
return RIL_AUTH_CHAP;
case OFONO_GPRS_AUTH_METHOD_PAP:
return RIL_AUTH_PAP;
case OFONO_GPRS_AUTH_METHOD_ANY:
/* Use default */
break;
}
/* Default */
return RIL_AUTH_BOTH;
}
/* Returns enum access_technology or -1 on failure. */
int ril_parse_tech(const char *stech, int *ril_tech)
{
int access_tech = -1;
int tech = -1;
if (gutil_parse_int(stech, 0, &tech)) {
switch (tech) {
case RADIO_TECH_GPRS:
case RADIO_TECH_GSM:
access_tech = ACCESS_TECHNOLOGY_GSM;
break;
case RADIO_TECH_EDGE:
access_tech = ACCESS_TECHNOLOGY_GSM_EGPRS;
break;
case RADIO_TECH_UMTS:
access_tech = ACCESS_TECHNOLOGY_UTRAN;
break;
case RADIO_TECH_HSDPA:
access_tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA;
break;
case RADIO_TECH_HSUPA:
access_tech = ACCESS_TECHNOLOGY_UTRAN_HSUPA;
break;
case RADIO_TECH_HSPA:
case RADIO_TECH_HSPAP:
access_tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
break;
case RADIO_TECH_LTE:
case RADIO_TECH_LTE_CA:
access_tech = ACCESS_TECHNOLOGY_EUTRAN;
break;
default:
DBG("Unknown RIL tech %s", stech);
/* no break */
case RADIO_TECH_IWLAN:
case RADIO_TECH_UNKNOWN:
tech = -1;
break;
}
}
if (ril_tech) {
*ril_tech = tech;
}
return access_tech;
}
gboolean ril_parse_mcc_mnc(const char *str, struct ofono_network_operator *op)
{
if (str) {
int i;
const char *ptr = str;
/* Three digit country code */
for (i = 0;
i < OFONO_MAX_MCC_LENGTH && *ptr && isdigit(*ptr);
i++) {
op->mcc[i] = *ptr++;
}
op->mcc[i] = 0;
if (i == OFONO_MAX_MCC_LENGTH) {
/* Usually 2 but sometimes 3 digit network code */
for (i = 0;
i < OFONO_MAX_MNC_LENGTH && *ptr && isdigit(*ptr);
i++) {
op->mnc[i] = *ptr++;
}
op->mnc[i] = 0;
if (i > 0) {
/*
* Sometimes MCC/MNC are followed by + and
* what looks like the technology code. This
* is of course completely undocumented.
*/
if (*ptr == '+') {
int tech = ril_parse_tech(ptr+1, NULL);
if (tech >= 0) {
op->tech = tech;
}
}
return TRUE;
}
}
}
return FALSE;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/