Beispiel #1
0
static void ril_cops_cb(struct ril_msg *message, gpointer user_data)
{
	struct cb_data *cbd = user_data;
	ofono_netreg_operator_cb_t cb = cbd->cb;
	struct netreg_data *nd = cbd->user;
	struct ofono_error error;
	struct parcel rilp;
	struct ofono_network_operator op;
	gchar *lalpha, *salpha, *numeric;

	if (message->error == RIL_E_SUCCESS) {
		decode_ril_error(&error, "OK");
	} else {
		ofono_error("Failed to retrive the current operator");
		goto error;
	}

	ril_util_init_parcel(message, &rilp);

	/* Size of char ** */
	if (parcel_r_int32(&rilp) == 0)
		goto error;

	lalpha = parcel_r_string(&rilp);
	salpha = parcel_r_string(&rilp);
	numeric = parcel_r_string(&rilp);

	/* Try to use long by default */
	if (lalpha)
		strncpy(op.name, lalpha, OFONO_MAX_OPERATOR_NAME_LENGTH);
	else if (salpha)
		strncpy(op.name, salpha, OFONO_MAX_OPERATOR_NAME_LENGTH);
	else
		goto error;

	extract_mcc_mnc(numeric, op.mcc, op.mnc);

	/* Set to current */
	op.status = OPERATOR_STATUS_CURRENT;
	op.tech = nd->tech;

	g_ril_append_print_buf(nd->ril,
				"(lalpha=%s, salpha=%s, numeric=%s, %s, mcc=%s, mnc=%s, %s)",
				lalpha, salpha, numeric,
				op.name, op.mcc, op.mnc,
				registration_tech_to_string(op.tech));
	g_ril_print_response(nd->ril, message);

	g_free(lalpha);
	g_free(salpha);
	g_free(numeric);

	cb(&error, &op, cbd->data);

	return;

error:
	CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
Beispiel #2
0
static void ril_ussd_notify(struct ril_msg *message, gpointer user_data)
{
	struct ofono_ussd *ussd = user_data;
	struct ussd_data *ud = ofono_ussd_get_data(ussd);
	struct parcel rilp;
	int numstr;
	char *typestr;
	int type;
	char *str = NULL;
	gsize written;
	char *ucs2;

	g_ril_init_parcel(message, &rilp);

	numstr = parcel_r_int32(&rilp);
	if (numstr < 1)
		return;

	typestr = parcel_r_string(&rilp);
	if (typestr == NULL || *typestr == '\0')
		return;

	type = *typestr - '0';
	g_free(typestr);

	if (numstr > 1)
		str = parcel_r_string(&rilp);

	g_ril_append_print_buf(ud->ril, "{%d,%s}", type, str);

	g_ril_print_unsol(ud->ril, message);

	/* To fix bug in MTK: USSD-Notify arrive with type 2 instead of 0 */
	if (g_ril_vendor(ud->ril) == OFONO_RIL_VENDOR_MTK &&
			str != NULL && type == 2)
		type = 0;

	if (str == NULL) {
		ofono_ussd_notify(ussd, type, 0, NULL, 0);
		return;
	}

	/*
	 * With data coding scheme 0x48, we are saying that the ussd string is a
	 * UCS-2 string, uncompressed, and with unspecified message class. For
	 * the DCS coding, see 3gpp 23.038, sect. 5.
	 */
	ucs2 = g_convert(str, -1, "UCS-2BE//TRANSLIT",
					"UTF-8", NULL, &written, NULL);
	g_free(str);

	if (ucs2 == NULL) {
		ofono_error("%s: Error transcoding", __func__);
		return;
	}

	ofono_ussd_notify(ussd, type, 0x48, (unsigned char *) ucs2, written);
	g_free(ucs2);
}
Beispiel #3
0
static void ril_imsi_cb(struct ril_msg *message, gpointer user_data)
{
	struct cb_data *cbd = user_data;
	ofono_sim_imsi_cb_t cb = cbd->cb;
	struct sim_data *sd = cbd->user;
	struct ofono_error error;
	struct parcel rilp;
	gchar *imsi;

	if (message->error == RIL_E_SUCCESS) {
		DBG("GET IMSI reply - OK");
		decode_ril_error(&error, "OK");
	} else {
		ofono_error("Reply failure: %s",
			    ril_error_to_string(message->error));
		decode_ril_error(&error, "FAIL");
		cb(&error, NULL, cbd->data);
		return;
	}

	ril_util_init_parcel(message, &rilp);

	/* 15 is the max length of IMSI
	 * add 4 bytes for string length */
	/* FIXME: g_assert(message->buf_len <= 19); */
	imsi = parcel_r_string(&rilp);

	g_ril_append_print_buf(sd->ril, "{%s}", imsi);
	g_ril_print_response(sd->ril, message);

	cb(&error, imsi, cbd->data);
	g_free(imsi);
}
Beispiel #4
0
struct unsol_supp_svc_notif *g_ril_unsol_parse_supp_svc_notif(GRil *gril,
						struct ril_msg *message)
{
	struct parcel rilp;
	char *tmp_number;
	int type;
	struct unsol_supp_svc_notif *unsol =
		g_new0(struct unsol_supp_svc_notif, 1);

	g_ril_init_parcel(message, &rilp);

	unsol->notif_type = parcel_r_int32(&rilp);
	unsol->code = parcel_r_int32(&rilp);
	unsol->index = parcel_r_int32(&rilp);
	type = parcel_r_int32(&rilp);
	tmp_number = parcel_r_string(&rilp);

	if (tmp_number != NULL) {
		strncpy(unsol->number.number, tmp_number,
			OFONO_MAX_PHONE_NUMBER_LENGTH);
		unsol->number.type = type;
		g_free(tmp_number);
	}

	g_ril_append_print_buf(gril, "{%d,%d,%d,%d,%s}",
				unsol->notif_type, unsol->code, unsol->index,
				type, tmp_number);
	g_ril_print_unsol(gril, message);

	return unsol;
}
Beispiel #5
0
static void ril_imsi_cb(struct ril_msg *message, gpointer user_data)
{
	struct cb_data *cbd = user_data;
	ofono_sim_imsi_cb_t cb = cbd->cb;
	struct sim_data *sd = cbd->user;
	struct parcel rilp;
	gchar *imsi;

	DBG("");

	if (message->error != RIL_E_SUCCESS) {
		ofono_error("Reply failure: %s",
				ril_error_to_string(message->error));
		goto error;
	}

	g_ril_init_parcel(message, &rilp);
	imsi = parcel_r_string(&rilp);

	g_ril_append_print_buf(sd->ril, "{%s}", imsi ? imsi : "NULL");
	g_ril_print_response(sd->ril, message);

	if (imsi == NULL)
		goto error;

	CALLBACK_WITH_SUCCESS(cb, imsi, cbd->data);
	g_free(imsi);
	return;

error:
	CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
}
Beispiel #6
0
int g_ril_reply_parse_sms_response(GRil *gril, const struct ril_msg *message)
{
	struct parcel rilp;
	int error, mr;
	char *ack_pdu;

	/* Set up Parcel struct for proper parsing */
	g_ril_init_parcel(message, &rilp);

	/*
	 * TP-Message-Reference for GSM/
	 * BearerData MessageId for CDMA
	 */
	mr = parcel_r_int32(&rilp);
	ack_pdu = parcel_r_string(&rilp);
	error = parcel_r_int32(&rilp);

	g_ril_append_print_buf(gril, "{%d,%s,%d}",
				mr, ack_pdu, error);
	g_ril_print_response(gril, message);

	g_free(ack_pdu);

	return mr;
}
Beispiel #7
0
static gboolean parse_sim_io(GRil *ril, struct ril_msg *message,
				int *sw1, int *sw2, char **hex_response)
{
	struct parcel rilp;

	/*
	 * Minimum length of SIM_IO_Response is 12:
	 * sw1 (int32)
	 * sw2 (int32)
	 * simResponse (string)
	 */
	if (message->buf_len < 12) {
		ofono_error("Invalid SIM IO reply: size too small (< 12): %u",
				message->buf_len);
		return FALSE;
	}

	g_ril_init_parcel(message, &rilp);
	*sw1 = parcel_r_int32(&rilp);
	*sw2 = parcel_r_int32(&rilp);

	*hex_response = parcel_r_string(&rilp);

	g_ril_append_print_buf(ril, "(sw1=0x%.2X,sw2=0x%.2X,%s)",
				*sw1, *sw2, *hex_response);
	g_ril_print_response(ril, message);

	if (rilp.malformed) {
		g_free(*hex_response);
		return FALSE;
	}

	return TRUE;
}
Beispiel #8
0
struct unsol_ussd *g_ril_unsol_parse_ussd(GRil *gril, struct ril_msg *message)
{
	struct parcel rilp;
	struct unsol_ussd *ussd;
	char *typestr = NULL;
	int numstr;

	ussd = g_try_malloc0(sizeof(*ussd));
	if (ussd == NULL) {
		ofono_error("%s out of memory", __func__);
		goto error;
	}

	g_ril_init_parcel(message, &rilp);

	numstr = parcel_r_int32(&rilp);
	if (numstr < 1) {
		ofono_error("%s malformed parcel", __func__);
		goto error;
	}

	typestr = parcel_r_string(&rilp);
	if (typestr == NULL || *typestr == '\0') {
		ofono_error("%s wrong type", __func__);
		goto error;
	}

	ussd->type = *typestr - '0';

	g_free(typestr);

	if (numstr > 1)
		ussd->message = parcel_r_string(&rilp);

	g_ril_append_print_buf(gril, "{%d,%s}", ussd->type, ussd->message);

	g_ril_print_unsol(gril, message);

	return ussd;

error:
	g_free(typestr);
	g_free(ussd);

	return NULL;
}
Beispiel #9
0
struct reply_sim_io *g_ril_reply_parse_sim_io(GRil *gril,
						const struct ril_msg *message)
{
	struct parcel rilp;
	char *response = NULL;
	struct reply_sim_io *reply;

	/*
	 * Minimum length of SIM_IO_Response is 12:
	 * sw1 (int32)
	 * sw2 (int32)
	 * simResponse (string)
	 */
	if (message->buf_len < 12) {
		ofono_error("Invalid SIM IO reply: size too small (< 12): %d ",
			    (int) message->buf_len);
		return NULL;
	}

	reply =	g_new0(struct reply_sim_io, 1);

	g_ril_init_parcel(message, &rilp);
	reply->sw1 = parcel_r_int32(&rilp);
	reply->sw2 = parcel_r_int32(&rilp);

	response = parcel_r_string(&rilp);

	g_ril_append_print_buf(gril,
				"(sw1=0x%.2X,sw2=0x%.2X,%s)",
				reply->sw1,
				reply->sw2,
				response);
	g_ril_print_response(gril, message);

	if (rilp.malformed)
		goto error;

	if (response != NULL) {
		reply->hex_response =
			decode_hex(response, strlen(response),
					(long *) &reply->hex_len, -1);
		g_free(response);

		if (reply->hex_response == NULL)
			goto error;
	}

	return reply;

error:
	g_free(reply);

	return NULL;
}
Beispiel #10
0
struct ofono_phone_number *g_ril_reply_parse_get_smsc_address(
						GRil *gril,
						const struct ril_msg *message)
{
	struct ofono_phone_number *sca;
	struct parcel rilp;
	char *number, *temp_buf;

	sca = g_new0(struct ofono_phone_number, 1);
	if (sca == NULL) {
		ofono_error("%s Out of memory", __func__);
		goto err_alloc;
	}

	g_ril_init_parcel(message, &rilp);

	temp_buf = parcel_r_string(&rilp);
	if (temp_buf == NULL) {
		ofono_error("%s Cannot read SMSC address", __func__);
		goto err_readsca;
	}

	/* RIL gives address in quotes */
	number = strtok(temp_buf, "\"");
	if (number == NULL || *number == '\0') {
		ofono_error("%s Invalid SMSC address", __func__);
		goto err_scaformat;
	}

	if (number[0] == '+') {
		number = number + 1;
		sca->type = OFONO_NUMBER_TYPE_INTERNATIONAL;
	} else {
		sca->type = OFONO_NUMBER_TYPE_UNKNOWN;
	}

	strncpy(sca->number, number, OFONO_MAX_PHONE_NUMBER_LENGTH);
	sca->number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';

	g_ril_append_print_buf(gril, "{type=%d,number=%s}",
				sca->type, sca->number);
	g_ril_print_response(gril, message);

	g_free(temp_buf);

	return sca;

err_scaformat:
	g_free(temp_buf);
err_readsca:
	g_free(sca);
err_alloc:
	return NULL;
}
Beispiel #11
0
gchar *g_ril_reply_parse_imsi(GRil *gril, const struct ril_msg *message)
{
	struct parcel rilp;
	gchar *imsi;

	g_ril_init_parcel(message, &rilp);

	imsi = parcel_r_string(&rilp);

	g_ril_append_print_buf(gril, "{%s}", imsi ? imsi : "NULL");
	g_ril_print_response(gril, message);

	return imsi;
}
Beispiel #12
0
static void ril_query_cb(struct ril_msg *message, gpointer user_data)
{
	struct cb_data *cbd = user_data;
	ofono_call_forwarding_query_cb_t cb = cbd->cb;
	struct ofono_call_forwarding_condition *list = NULL;
	struct parcel rilp;
	int nmbr_of_resps = 0;
	int i;

	if (message->error == RIL_E_SUCCESS) {

		ril_util_init_parcel(message, &rilp);

		nmbr_of_resps = parcel_r_int32(&rilp);

		list = g_new0(
				struct ofono_call_forwarding_condition,
				nmbr_of_resps);

		for (i = 0; i < nmbr_of_resps; i++) {
			const char *str;

			list[i].status =  parcel_r_int32(&rilp);

			parcel_r_int32(&rilp);

			list[i].cls = parcel_r_int32(&rilp);

			list[i].phone_number.type = parcel_r_int32(&rilp);

			str = parcel_r_string(&rilp);

			if (str) {

				strncpy(list[i].phone_number.number,
					str,
					OFONO_MAX_PHONE_NUMBER_LENGTH);

				list[i].phone_number.number[
					OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';

				list[i].time = parcel_r_int32(&rilp);
			}

		}

		CALLBACK_WITH_SUCCESS(cb, 1, list, cbd->data);

		g_free(list);
	} else
Beispiel #13
0
static void ril_ussd_notify(struct ril_msg *message, gpointer user_data)
{
	struct ofono_ussd *ussd = user_data;
	struct parcel rilp;
	gchar *ussd_from_network;
	gchar *type;
	gint ussdtype;

	ril_util_init_parcel(message, &rilp);
	parcel_r_int32(&rilp);
	type = parcel_r_string(&rilp);
	ussdtype = g_ascii_xdigit_value(*type);
	ussd_from_network = parcel_r_string(&rilp);

	if (ussd_from_network)
		ofono_ussd_notify(ussd, ussdtype, 0xFF,
			(const unsigned char *)ussd_from_network,
			strlen(ussd_from_network));
	else
		ofono_ussd_notify(ussd, ussdtype, 0, NULL, 0);

	return;
}
Beispiel #14
0
char *g_ril_reply_parse_baseband_version(GRil *gril,
						const struct ril_msg *message)
{
	struct parcel rilp;
	char *version;

	g_ril_init_parcel(message, &rilp);

	version = parcel_r_string(&rilp);

	g_ril_append_print_buf(gril, "{%s}", version);
	g_ril_print_response(gril, message);

	return version;
}
Beispiel #15
0
gchar *g_ril_reply_parse_imsi(GRil *gril, const struct ril_msg *message)
{
	struct parcel rilp;
	gchar *imsi;

	g_ril_init_parcel(message, &rilp);

	/* 15 is the max length of IMSI
	 * add 4 bytes for string length */
	/* FIXME: g_assert(message->buf_len <= 19); */
	imsi = parcel_r_string(&rilp);

	g_ril_append_print_buf(gril, "{%s}", imsi);
	g_ril_print_response(gril, message);

	return imsi;
}
Beispiel #16
0
struct unsol_sms_data *g_ril_unsol_parse_new_sms(GRil *gril,
						const struct ril_msg *message)
{
	struct parcel rilp;
	char *ril_pdu;
	size_t ril_pdu_len;
	struct unsol_sms_data *sms_data;

	sms_data = g_new0(struct unsol_sms_data, 1);
	if (sms_data == NULL) {
		ofono_error("%s out of memory", __func__);
		goto error;
	}

	g_ril_init_parcel(message, &rilp);

	ril_pdu = parcel_r_string(&rilp);
	if (ril_pdu == NULL) {
		ofono_error("%s Unable to parse notification", __func__);
		goto error;
	}

	ril_pdu_len = strlen(ril_pdu);

	sms_data->data = decode_hex(ril_pdu, ril_pdu_len,
					&sms_data->length, -1);
	if (sms_data->data == NULL) {
		ofono_error("%s Unable to decode notification", __func__);
		goto error_dec;
	}

	g_ril_append_print_buf(gril, "{%s}", ril_pdu);
	g_ril_print_unsol(gril, message);

	g_free(ril_pdu);

	return sms_data;

error_dec:
	g_free(ril_pdu);
error:
	g_ril_unsol_free_sms_data(sms_data);
	return NULL;
}
Beispiel #17
0
static void ril_nitz_notify(struct ril_msg *message, gpointer user_data)
{
	struct ofono_netreg *netreg = user_data;
	struct netreg_data *nd = ofono_netreg_get_data(netreg);
	struct parcel rilp;
	int year, mon, mday, hour, min, sec, dst, tzi;
	char tzs, tz[4];
	gchar *nitz;

	if (message->req != RIL_UNSOL_NITZ_TIME_RECEIVED)
		goto error;


	ril_util_init_parcel(message, &rilp);

	nitz = parcel_r_string(&rilp);

	g_ril_append_print_buf(nd->ril, "(%s)", nitz);
	g_ril_print_unsol(nd->ril, message);

	sscanf(nitz, "%u/%u/%u,%u:%u:%u%c%u,%u", &year, &mon, &mday,
			&hour, &min, &sec, &tzs, &tzi, &dst);
	sprintf(tz, "%c%d", tzs, tzi);

	nd->time.utcoff = atoi(tz) * 15 * 60;
	nd->time.dst = dst;
	nd->time.sec = sec;
	nd->time.min = min;
	nd->time.hour = hour;
	nd->time.mday = mday;
	nd->time.mon = mon;
	nd->time.year = 2000 + year;

	ofono_netreg_time_notify(netreg, &nd->time);

	g_free(nitz);

	return;

error:
	ofono_error("Unable to notify ofono about nitz");
}
Beispiel #18
0
static void ril_csca_query_cb(struct ril_msg *message, gpointer user_data)
{
	struct cb_data *cbd = user_data;
	ofono_sms_sca_query_cb_t cb = cbd->cb;
	struct ofono_error error;
	struct ofono_phone_number sca;
	struct parcel rilp;
	gchar *number, *temp_buf;

	if (message->error == RIL_E_SUCCESS) {
		decode_ril_error(&error, "OK");
	} else {
		decode_ril_error(&error, "FAIL");
		cb(&error, NULL, cbd->data);
		return;
	}

	ril_util_init_parcel(message, &rilp);
	temp_buf = parcel_r_string(&rilp);

	if (temp_buf != NULL) {
		/* RIL gives address in quotes */
		number = strtok(temp_buf, "\"");

		if (number[0] == '+') {
			number = number + 1;
			sca.type = 145;
		} else {
			sca.type = 129;
		}
		strncpy(sca.number, number, OFONO_MAX_PHONE_NUMBER_LENGTH);
		sca.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';

		DBG("csca_query_cb: %s, %d", sca.number, sca.type);

		cb(&error, &sca, cbd->data);
	} else {
		CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
	}
}
Beispiel #19
0
static void ril_stk_pcmd_notify(struct ril_msg *message, gpointer user_data)
{
	struct ofono_stk *stk = user_data;
	struct parcel rilp;
	char *pcmd = NULL;
	guchar *pdu = NULL;
	long len;

	DBG("");

	ril_util_init_parcel(message, &rilp);
	pcmd = parcel_r_string(&rilp);
	DBG("pcmd: %s", pcmd);

	pdu = decode_hex((const char *) pcmd,
			strlen(pcmd),
			&len, -1);

	g_free(pcmd);
	ofono_stk_proactive_command_notify(stk, len, (const guchar *)pdu);
	g_free(pdu);
}
Beispiel #20
0
struct parcel_str_array *parcel_r_str_array(struct parcel *p)
{
	int i;
	struct parcel_str_array *str_arr;
	int num_str = parcel_r_int32(p);

	if (p->malformed || num_str <= 0)
		return NULL;

	str_arr = g_try_malloc0(sizeof(*str_arr) + num_str * sizeof(char *));
	if (str_arr == NULL)
		return NULL;

	str_arr->num_str = num_str;
	for (i = 0; i < num_str; ++i)
		str_arr->str[i] = parcel_r_string(p);

	if (p->malformed) {
		parcel_free_str_array(str_arr);
		return NULL;
	}

	return str_arr;
}
Beispiel #21
0
static void ril_cbs_notify(struct ril_msg *message, gpointer user_data)
{
	struct ofono_cbs *cbs = user_data;

	/*
	 * Ofono does not support UMTS CB - see
	 * src/smsutil.c method cbs_decode.
	 * But let's let the core to make
	 * the rejection reserve memory here
	 * for maximum UMTS CB length
	 */

	unsigned char pdu[1252];
	char *resp;
	struct parcel rilp;

	ril_util_init_parcel(message, &rilp);

	resp = parcel_r_string(&rilp);

	memcpy(resp, pdu, strlen((char *)resp));

	ofono_cbs_notify(cbs, pdu, strlen((char *)resp));
}
Beispiel #22
0
char *g_ril_unsol_parse_nitz(GRil *gril, const struct ril_msg *message)
{
	struct parcel rilp;
	gchar *nitz = NULL;

	DBG("");

	if (message->buf_len < MIN_NITZ_SIZE) {
		ofono_error("%s: NITZ too small: %d",
				__func__,
				(int) message->buf_len);
		goto error;
	}

	g_ril_init_parcel(message, &rilp);

	nitz = parcel_r_string(&rilp);

	g_ril_append_print_buf(gril, "(%s)", nitz);
	g_ril_print_unsol(gril, message);

error:
	return nitz;
}
Beispiel #23
0
static void ril_sms_notify(struct ril_msg *message, gpointer user_data)
{
	struct ofono_sms *sms = user_data;
	struct sms_data *sd = ofono_sms_get_data(sms);
	struct parcel rilp;
	char *ril_pdu;
	int ril_pdu_len;
	unsigned int smsc_len;
	long ril_buf_len;
	guchar *ril_data;

	DBG("req: %d; data_len: %d", message->req, message->buf_len);

	switch (message->req) {
	case RIL_UNSOL_RESPONSE_NEW_SMS:
	case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT:
		break;
	default:
		goto error;
	}

	ril_util_init_parcel(message, &rilp);

	ril_pdu = parcel_r_string(&rilp);
	if (ril_pdu == NULL)
		goto error;

	ril_pdu_len = strlen(ril_pdu);

	DBG("ril_pdu_len is %d", ril_pdu_len);
	ril_data = decode_hex(ril_pdu, ril_pdu_len, &ril_buf_len, -1);
	if (ril_data == NULL)
		goto error;

	/* The first octect in the pdu contains the SMSC address length
	 * which is the X following octects it reads. We add 1 octet to
	 * the read length to take into account this read octet in order
	 * to calculate the proper tpdu length.
	 */
	smsc_len = ril_data[0] + 1;
	DBG("smsc_len is %d", smsc_len);

	g_ril_append_print_buf(sd->ril, "(%s)", ril_pdu);
	g_ril_print_unsol(sd->ril, message);

	if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS) {
		/* Last parameter is 'tpdu_len' ( substract SMSC length ) */
		ofono_sms_deliver_notify(sms, ril_data,
				ril_buf_len,
				ril_buf_len - smsc_len);
	} else if (message->req == RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT) {
		ofono_sms_status_notify(sms, ril_data, ril_buf_len,
						ril_buf_len - smsc_len);
	}

	ril_ack_delivery(sms);

	return;

error:
	ofono_error("Unable to parse NEW_SMS notification");
}
Beispiel #24
0
static void sim_status_cb(struct ril_msg *message, gpointer user_data)
{
	struct ofono_sim *sim = user_data;
	struct sim_data *sd = ofono_sim_get_data(sim);
	struct parcel rilp;
	int card_state;
	int universal_pin_state;
	int gsm_umts_app_index;
	int cdma_app_index;
	int ims_app_index;
	int num_apps;
	int i;
	int app_state;
	int perso_substate;

	DBG("");

	g_ril_init_parcel(message, &rilp);

	card_state = parcel_r_int32(&rilp);

	/*
	 * NOTE:
	 *
	 * The global pin_status is used for multi-application
	 * UICC cards.  For example, there are SIM cards that
	 * can be used in both GSM and CDMA phones.  Instead
	 * of managed PINs for both applications, a global PIN
	 * is set instead.  It's not clear at this point if
	 * such SIM cards are supported by ofono or RILD.
	 */
	universal_pin_state = parcel_r_int32(&rilp);
	gsm_umts_app_index = parcel_r_int32(&rilp);
	cdma_app_index = parcel_r_int32(&rilp);
	ims_app_index = parcel_r_int32(&rilp);
	num_apps = parcel_r_int32(&rilp);

	if (rilp.malformed)
		return;

	if (gsm_umts_app_index >= num_apps)
		return;

	DBG("[%d,%04d]< %s: card_state=%d,universal_pin_state=%d,"
			"gsm_umts_index=%d,cdma_index=%d,ims_index=%d,"
			"num_apps=%d",
			g_ril_get_slot(sd->ril),
			message->serial_no,
			"RIL_REQUEST_GET_SIM_STATUS",
			card_state, universal_pin_state,
			gsm_umts_app_index, cdma_app_index, ims_app_index,
			num_apps);

	switch (card_state) {
	case RIL_CARDSTATE_PRESENT:
		break;
	case RIL_CARDSTATE_ABSENT:
		ofono_sim_inserted_notify(sim, FALSE);
		return;
	default:
		ofono_error("%s: bad SIM state (%u)", __func__, card_state);
		return;
	}

	ofono_sim_inserted_notify(sim, TRUE);

	for (i = 0; i != gsm_umts_app_index; i++) {
		parcel_r_int32(&rilp);		/* AppType */
		parcel_r_int32(&rilp);		/* AppState */
		parcel_r_int32(&rilp);		/* PersoSubstate */
		parcel_skip_string(&rilp);	/* AID */
		parcel_skip_string(&rilp);	/* App Label */
		parcel_r_int32(&rilp);		/* PIN1 Replaced */
		parcel_r_int32(&rilp);		/* PIN1 PinState */
		parcel_r_int32(&rilp);		/* PIN2 PinState */

		if (rilp.malformed)
			return;
	}

	/*
	 * We cache the current password state. Ideally this should be done
	 * by issuing a GET_SIM_STATUS request from ril_query_passwd_state,
	 * which is called by the core after sending a password, but
	 * unfortunately the response to GET_SIM_STATUS is not reliable in mako
	 * when sent just after sending the password. Some time is needed
	 * before the modem refreshes its internal state, and when it does it
	 * sends a SIM_STATUS_CHANGED event. In that moment we retrieve the
	 * status and this function is executed. We call
	 * __ofono_sim_recheck_pin as it is the only way to indicate the core
	 * to call query_passwd_state again. An option that can be explored in
	 * the future is wait before invoking core callback for send_passwd
	 * until we know the real password state.
	 */
	sd->app_type = parcel_r_int32(&rilp);	/* AppType */
	app_state = parcel_r_int32(&rilp);	/* AppState */
	perso_substate = parcel_r_int32(&rilp);	/* PersoSubstate */

	switch (app_state) {
	case RIL_APPSTATE_PIN:
		sd->passwd_state = OFONO_SIM_PASSWORD_SIM_PIN;
		break;
	case RIL_APPSTATE_PUK:
		sd->passwd_state = OFONO_SIM_PASSWORD_SIM_PUK;
		break;
	case RIL_APPSTATE_SUBSCRIPTION_PERSO:
		switch (perso_substate) {
		case RIL_PERSOSUBSTATE_SIM_NETWORK:
			sd->passwd_state = OFONO_SIM_PASSWORD_PHNET_PIN;
			break;
		case RIL_PERSOSUBSTATE_SIM_NETWORK_SUBSET:
			sd->passwd_state = OFONO_SIM_PASSWORD_PHNETSUB_PIN;
			break;
		case RIL_PERSOSUBSTATE_SIM_CORPORATE:
			sd->passwd_state = OFONO_SIM_PASSWORD_PHCORP_PIN;
			break;
		case RIL_PERSOSUBSTATE_SIM_SERVICE_PROVIDER:
			sd->passwd_state = OFONO_SIM_PASSWORD_PHSP_PIN;
			break;
		case RIL_PERSOSUBSTATE_SIM_SIM:
			sd->passwd_state = OFONO_SIM_PASSWORD_PHSIM_PIN;
			break;
		case RIL_PERSOSUBSTATE_SIM_NETWORK_PUK:
			sd->passwd_state = OFONO_SIM_PASSWORD_PHNET_PUK;
			break;
		case RIL_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK:
			sd->passwd_state = OFONO_SIM_PASSWORD_PHNETSUB_PUK;
			break;
		case RIL_PERSOSUBSTATE_SIM_CORPORATE_PUK:
			sd->passwd_state = OFONO_SIM_PASSWORD_PHCORP_PUK;
			break;
		case RIL_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK:
			sd->passwd_state = OFONO_SIM_PASSWORD_PHSP_PUK;
			break;
		case RIL_PERSOSUBSTATE_SIM_SIM_PUK:
			sd->passwd_state = OFONO_SIM_PASSWORD_PHFSIM_PUK;
			break;
		default:
			sd->passwd_state = OFONO_SIM_PASSWORD_NONE;
			break;
		};
		break;
	case RIL_APPSTATE_READY:
		sd->passwd_state = OFONO_SIM_PASSWORD_NONE;
		break;
	case RIL_APPSTATE_UNKNOWN:
	case RIL_APPSTATE_DETECTED:
	default:
		sd->passwd_state = OFONO_SIM_PASSWORD_INVALID;
		break;
	}

	g_free(sd->aid_str);
	sd->aid_str = parcel_r_string(&rilp);	/* AID */

	DBG("[%d,%04d]< app_type: %d, passwd_state: %d, aid_str (AID): %s",
		g_ril_get_slot(sd->ril), message->serial_no,
		sd->app_type, sd->passwd_state, sd->aid_str);

	/*
	 * Note: There doesn't seem to be any other way to force the core SIM
	 * code to recheck the PIN. This call causes the core to call this
	 * atom's query_passwd() function.
	 */
	__ofono_sim_recheck_pin(sim);
}
Beispiel #25
0
struct reply_operator *g_ril_reply_parse_operator(GRil *gril,
						const struct ril_msg *message)
{
	struct parcel rilp;
	int num_params;
	struct reply_operator *reply = NULL;

	/*
	 * Minimum message length is 16:
	 * - array size
	 * - 3 NULL strings
	 */
	if (message->buf_len < 16) {
		ofono_error("%s: invalid OPERATOR reply: "
				"size too small (< 16): %d ",
				__func__,
				(int) message->buf_len);
		goto error;
	}

	g_ril_init_parcel(message, &rilp);

	if ((num_params = parcel_r_int32(&rilp)) != OPERATOR_NUM_PARAMS) {
		ofono_error("%s: invalid OPERATOR reply: "
				"number of params is %d; should be 3.",
				__func__,
				num_params);
		goto error;
	}

	reply =	g_new0(struct reply_operator, 1);

	reply->lalpha = parcel_r_string(&rilp);
	reply->salpha = parcel_r_string(&rilp);
	reply->numeric = parcel_r_string(&rilp);

	if (reply->lalpha == NULL && reply->salpha == NULL) {
		ofono_error("%s: invalid OPERATOR reply: "
				" no names returned.",
				__func__);

		goto error;
	}

	if (reply->numeric == NULL) {
		ofono_error("%s: invalid OPERATOR reply: "
				" no numeric returned.",
				__func__);
		goto error;
	}

	g_ril_append_print_buf(gril,
				"(lalpha=%s, salpha=%s, numeric=%s)",
				reply->lalpha, reply->salpha, reply->numeric);

	g_ril_print_response(gril, message);

	return reply;

error:
	if (reply)
		g_ril_reply_free_operator(reply);

	return NULL;
}
Beispiel #26
0
GSList *g_ril_reply_parse_get_calls(GRil *gril, const struct ril_msg *message)
{
	struct ofono_call *call;
	struct parcel rilp;
	GSList *l = NULL;
	int num, i;
	gchar *number, *name;

	g_ril_init_parcel(message, &rilp);

	g_ril_append_print_buf(gril, "{");

	/* maguro signals no calls with empty event data */
	if (rilp.size < sizeof(int32_t))
		goto no_calls;

	/* Number of RIL_Call structs */
	num = parcel_r_int32(&rilp);
	for (i = 0; i < num; i++) {
		call = g_try_new(struct ofono_call, 1);
		if (call == NULL)
			break;

		ofono_call_init(call);
		call->status = parcel_r_int32(&rilp);
		call->id = parcel_r_int32(&rilp);
		call->phone_number.type = parcel_r_int32(&rilp);
		parcel_r_int32(&rilp); /* isMpty */
		parcel_r_int32(&rilp); /* isMT */
		parcel_r_int32(&rilp); /* als */
		call->type = parcel_r_int32(&rilp); /* isVoice */
		parcel_r_int32(&rilp); /* isVoicePrivacy */
		number = parcel_r_string(&rilp);
		if (number) {
			strncpy(call->phone_number.number, number,
				OFONO_MAX_PHONE_NUMBER_LENGTH);
			g_free(number);
		}

		parcel_r_int32(&rilp); /* numberPresentation */
		name = parcel_r_string(&rilp);
		if (name) {
			strncpy(call->name, name,
				OFONO_MAX_CALLER_NAME_LENGTH);
			g_free(name);
		}

		parcel_r_int32(&rilp); /* namePresentation */
		parcel_r_int32(&rilp); /* uusInfo */

		if (strlen(call->phone_number.number) > 0)
			call->clip_validity = 0;
		else
			call->clip_validity = 2;

		g_ril_append_print_buf(gril,
					"%s [id=%d,status=%d,type=%d,"
					"number=%s,name=%s]",
					print_buf,
					call->id, call->status, call->type,
					call->phone_number.number, call->name);

		l = g_slist_insert_sorted(l, call, g_ril_call_compare);
	}

no_calls:
	g_ril_append_print_buf(gril, "%s}", print_buf);
	g_ril_print_response(gril, message);

	return l;
}
Beispiel #27
0
struct reply_sim_status *g_ril_reply_parse_sim_status(GRil *gril,
						const struct ril_msg *message)
{
	struct parcel rilp;
	unsigned int i;
	struct reply_sim_status *status;

	g_ril_append_print_buf(gril, "[%d,%04d]< %s",
			g_ril_get_slot(gril), message->serial_no,
			ril_request_id_to_string(message->req));

	g_ril_init_parcel(message, &rilp);

	/*
	 * FIXME: Need to come up with a common scheme for verifying the
	 * size of RIL message and properly reacting to bad messages.
	 * This could be a runtime assertion, disconnect, drop/ignore
	 * the message, ...
	 *
	 * 20 is the min length of RIL_CardStatus_v6 as the AppState
	 * array can be 0-length.
	 */
	if (message->buf_len < 20) {
		ofono_error("Size of SIM_STATUS reply too small: %d bytes",
			    (int) message->buf_len);
		return NULL;
	}

	status = g_new0(struct reply_sim_status, 1);

	status->card_state = parcel_r_int32(&rilp);

	/*
	 * NOTE:
	 *
	 * The global pin_status is used for multi-application
	 * UICC cards.  For example, there are SIM cards that
	 * can be used in both GSM and CDMA phones.  Instead
	 * of managed PINs for both applications, a global PIN
	 * is set instead.  It's not clear at this point if
	 * such SIM cards are supported by ofono or RILD.
	 */

	status->pin_state = parcel_r_int32(&rilp);
	status->gsm_umts_index = parcel_r_int32(&rilp);
	status->cdma_index = parcel_r_int32(&rilp);
	status->ims_index = parcel_r_int32(&rilp);
	status->num_apps = parcel_r_int32(&rilp);

	/* TODO:
	 * How do we handle long (>80 chars) ril_append_print_buf strings?
	 * Using line wrapping ( via '\' ) introduces spaces in the output.
	 * Do we just make a style-guide exception for PrintBuf operations?
	 */
	g_ril_append_print_buf(gril,
				"(card_state=%d,universal_pin_state=%d,"
				"gsm_umts_index=%d,cdma_index=%d,"
				"ims_index=%d, ",
				status->card_state,
				status->pin_state,
				status->gsm_umts_index,
				status->cdma_index,
				status->ims_index);

	if (status->card_state != RIL_CARDSTATE_PRESENT)
		goto done;

	if (status->num_apps > MAX_UICC_APPS) {
		ofono_error("SIM error; too many apps: %d", status->num_apps);
		status->num_apps = MAX_UICC_APPS;
	}

	for (i = 0; i < status->num_apps; i++) {
		struct reply_sim_app *app;
		DBG("processing app[%d]", i);
		status->apps[i] = g_try_new0(struct reply_sim_app, 1);
		app = status->apps[i];
		if (app == NULL) {
			ofono_error("Can't allocate app_data");
			goto error;
		}

		app->app_type = parcel_r_int32(&rilp);
		app->app_state = parcel_r_int32(&rilp);
		app->perso_substate = parcel_r_int32(&rilp);

		/* TODO: we need a way to instruct parcel to skip
		 * a string, without allocating memory...
		 */
		app->aid_str = parcel_r_string(&rilp); /* application ID (AID) */
		app->app_str = parcel_r_string(&rilp); /* application label */

		app->pin_replaced = parcel_r_int32(&rilp);
		app->pin1_state = parcel_r_int32(&rilp);
		app->pin2_state = parcel_r_int32(&rilp);

		g_ril_append_print_buf(gril,
					"%s[app_type=%d,app_state=%d,"
					"perso_substate=%d,aid_ptr=%s,"
					"app_label_ptr=%s,pin1_replaced=%d,"
					"pin1=%d,pin2=%d],",
					print_buf,
					app->app_type,
					app->app_state,
					app->perso_substate,
					app->aid_str,
					app->app_str,
					app->pin_replaced,
					app->pin1_state,
					app->pin2_state);
	}

done:
	g_ril_append_print_buf(gril, "%s}", print_buf);
	g_ril_print_response(gril, message);

	return status;

error:
	g_ril_reply_free_sim_status(status);

	return NULL;
}
Beispiel #28
0
struct reply_avail_ops *g_ril_reply_parse_avail_ops(GRil *gril,
						const struct ril_msg *message)
{
	struct parcel rilp;
	struct reply_operator *operator;
	struct reply_avail_ops *reply = NULL;
	unsigned int num_ops, num_strings;
	unsigned int i;
	int strings_per_opt;

	if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK)
		strings_per_opt = 5;
	else
		strings_per_opt = 4;

	/*
	 * Minimum message length is 4:
	 * - array size
	 */
	if (message->buf_len < 4) {
		ofono_error("%s: invalid QUERY_AVAIL_NETWORKS reply: "
				"size too small (< 4): %d ",
				__func__,
				(int) message->buf_len);
		goto error;
	}

	g_ril_init_parcel(message, &rilp);
	g_ril_append_print_buf(gril, "{");

	/* Number of operators at the list */
	num_strings = (unsigned int) parcel_r_int32(&rilp);
	if (num_strings % strings_per_opt) {
		ofono_error("%s: invalid QUERY_AVAIL_NETWORKS reply: "
				"num_strings (%d) MOD %d != 0",
				__func__,
				num_strings, strings_per_opt);
		goto error;
	}

	num_ops = num_strings / strings_per_opt;
	DBG("noperators = %d", num_ops);

	reply = g_try_new0(struct reply_avail_ops, 1);
	if (reply == NULL) {
		ofono_error("%s: can't allocate reply struct", __func__);
		goto error;
	}

	reply->num_ops = num_ops;
	for (i = 0; i < num_ops; i++) {
		operator = g_try_new0(struct reply_operator, 1);
		if (operator == NULL) {
			ofono_error("%s: can't allocate reply struct",
					__func__);
			goto error;
		}

		operator->lalpha = parcel_r_string(&rilp);
		operator->salpha = parcel_r_string(&rilp);
		operator->numeric = parcel_r_string(&rilp);
		operator->status = parcel_r_string(&rilp);

		/*
		 * MTK: additional string with technology: 2G/3G are the only
		 * valid values currently.
		 */
		if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK) {
			char *tech = parcel_r_string(&rilp);
			if (strcmp(tech, "3G") == 0)
				operator->tech = RADIO_TECH_UMTS;
			else
				operator->tech = RADIO_TECH_GSM;
			g_free(tech);
		} else {
			operator->tech = RADIO_TECH_GSM;
		}

		if (operator->lalpha == NULL && operator->salpha == NULL) {
			ofono_error("%s: operator (%s) doesn't specify names",
					operator->numeric,
					__func__);
			g_ril_reply_free_operator(operator);
			continue;
		}

		if (operator->numeric == NULL) {
			ofono_error("%s: operator (%s/%s) "
					"doesn't specify numeric",
					operator->lalpha,
					operator->salpha,
					__func__);
			g_ril_reply_free_operator(operator);
			continue;
		}

		if (operator->status == NULL) {
			ofono_error("%s: operator (%s/%s) "
					"doesn't specify status",
					operator->lalpha,
					operator->salpha,
					__func__);
			g_ril_reply_free_operator(operator);
			continue;
		}

		reply->list = g_slist_append(reply->list, operator);

		g_ril_append_print_buf(gril, "%s [lalpha=%s, salpha=%s, "
				" numeric=%s status=%s tech=%s]",
				print_buf,
				operator->lalpha,
				operator->salpha,
				operator->numeric,
				operator->status,
				ril_radio_tech_to_string(operator->tech));
	}

	g_ril_append_print_buf(gril, "%s}", print_buf);
	g_ril_print_response(gril, message);

	return reply;

error:
	if (reply)
		g_ril_reply_free_avail_ops(reply);

	return NULL;
}
Beispiel #29
0
struct reply_sim_status *g_ril_reply_parse_sim_status(GRil *gril,
						const struct ril_msg *message)
{
	struct parcel rilp;
	unsigned int i;
	struct reply_sim_status *status;

	g_ril_append_print_buf(gril, "[%d,%04d]< %s",
			g_ril_get_slot(gril), message->serial_no,
			ril_request_id_to_string(message->req));

	g_ril_init_parcel(message, &rilp);

	status = g_new0(struct reply_sim_status, 1);

	status->card_state = parcel_r_int32(&rilp);

	/*
	 * NOTE:
	 *
	 * The global pin_status is used for multi-application
	 * UICC cards.  For example, there are SIM cards that
	 * can be used in both GSM and CDMA phones.  Instead
	 * of managed PINs for both applications, a global PIN
	 * is set instead.  It's not clear at this point if
	 * such SIM cards are supported by ofono or RILD.
	 */

	status->pin_state = parcel_r_int32(&rilp);
	status->gsm_umts_index = parcel_r_int32(&rilp);
	status->cdma_index = parcel_r_int32(&rilp);
	status->ims_index = parcel_r_int32(&rilp);
	status->num_apps = parcel_r_int32(&rilp);

	if (rilp.malformed)
		goto error;

	g_ril_append_print_buf(gril,
				"(card_state=%d,universal_pin_state=%d,"
				"gsm_umts_index=%d,cdma_index=%d,"
				"ims_index=%d, ",
				status->card_state,
				status->pin_state,
				status->gsm_umts_index,
				status->cdma_index,
				status->ims_index);

	if (status->card_state != RIL_CARDSTATE_PRESENT)
		goto done;

	if (status->num_apps > MAX_UICC_APPS) {
		ofono_error("SIM error; too many apps: %d", status->num_apps);
		status->num_apps = MAX_UICC_APPS;
	}

	for (i = 0; i < status->num_apps; i++) {
		struct reply_sim_app *app;
		DBG("processing app[%d]", i);
		status->apps[i] = g_try_new0(struct reply_sim_app, 1);
		app = status->apps[i];
		if (app == NULL) {
			ofono_error("Can't allocate app_data");
			goto error;
		}

		app->app_type = parcel_r_int32(&rilp);
		app->app_state = parcel_r_int32(&rilp);
		app->perso_substate = parcel_r_int32(&rilp);

		/*
		 * TODO: we need a way to instruct parcel to skip
		 * a string, without allocating memory...
		 */
		/* application ID (AID) */
		app->aid_str = parcel_r_string(&rilp);
		/* application label */
		app->app_str = parcel_r_string(&rilp);

		app->pin_replaced = parcel_r_int32(&rilp);
		app->pin1_state = parcel_r_int32(&rilp);
		app->pin2_state = parcel_r_int32(&rilp);

		g_ril_append_print_buf(gril,
					"%s[app_type=%d,app_state=%d,"
					"perso_substate=%d,aid_ptr=%s,"
					"app_label_ptr=%s,pin1_replaced=%d,"
					"pin1=%d,pin2=%d],",
					print_buf,
					app->app_type,
					app->app_state,
					app->perso_substate,
					app->aid_str ? app->aid_str : "NULL",
					app->app_str ? app->app_str : "NULL",
					app->pin_replaced,
					app->pin1_state,
					app->pin2_state);
	}

	if (rilp.malformed)
		goto error;

done:
	g_ril_append_print_buf(gril, "%s}", print_buf);
	g_ril_print_response(gril, message);

	return status;

error:
	g_ril_reply_free_sim_status(status);

	return NULL;
}
Beispiel #30
0
struct ofono_call_forwarding_condition
	*g_ril_reply_parse_query_call_fwd(GRil *gril,
						const struct ril_msg *message,
						unsigned int *list_size)
{
	struct ofono_call_forwarding_condition *list;
	struct parcel rilp;
	unsigned int i;

	if (list_size == NULL) {
		ofono_error("%s: list_size is NULL!", __func__);
		goto error;
	}

	g_ril_init_parcel(message, &rilp);

	if (rilp.size < sizeof(int32_t)) {
		ofono_error("%s: malformed parcel, can't read num params",
				__func__);
		goto error;
	}

	*list_size = parcel_r_int32(&rilp);
	if (*list_size == 0) {
		/* not really an error; handled in caller */
		goto error;
	}

	list = g_try_new0(struct ofono_call_forwarding_condition, *list_size);
	if (list == NULL) {
		ofono_error("%s: Out of memory", __func__);
		goto error;
	}

	g_ril_append_print_buf(gril, "{");

	for (i = 0; i < *list_size; i++) {
		char *str;

		list[i].status =  parcel_r_int32(&rilp);

		parcel_r_int32(&rilp); /* skip reason */

		list[i].cls = parcel_r_int32(&rilp);
		list[i].phone_number.type = parcel_r_int32(&rilp);

		str = parcel_r_string(&rilp);

		if (str != NULL) {
			strncpy(list[i].phone_number.number, str,
				OFONO_MAX_PHONE_NUMBER_LENGTH);
			g_free(str);

			list[i].phone_number.number[
				OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
		}

		list[i].time = parcel_r_int32(&rilp);

		if (rilp.malformed) {
			ofono_error("%s: malformed parcel", __func__);
			g_free(list);
			goto error;
		}

		g_ril_append_print_buf(gril, "%s [%d,%d,%d,%s,%d]",
					print_buf,
					list[i].status,
					list[i].cls,
					list[i].phone_number.type,
					list[i].phone_number.number,
					list[i].time);

	}

	g_ril_append_print_buf(gril, "%s}", print_buf);
	g_ril_print_response(gril, message);

	return list;

error:
	return NULL;
}