Пример #1
0
static void sim_status_cb(struct ril_msg *message, gpointer user_data)
{
	struct ofono_modem *modem = user_data;
	struct ril_data *ril = ofono_modem_get_data(modem);
	struct reply_sim_status *status;

	DBG("");

	if (message->error != RIL_E_SUCCESS) {
		ril->sim_status_retries++;

		ofono_error("GET_SIM_STATUS request failed: %s; retries: %d",
				ril_error_to_string(message->error),
				ril->sim_status_retries);

		if (ril->sim_status_retries < MAX_SIM_STATUS_RETRIES)
			g_timeout_add_seconds(2, sim_status_retry, modem);
		else
			ofono_error("Max retries for GET_SIM_STATUS exceeded!");
	} else {

		if ((status = g_ril_reply_parse_sim_status(ril->modem, message))
				!= NULL) {

			if (status->card_state == RIL_CARDSTATE_PRESENT) {
				DBG("Card PRESENT; num_apps: %d",
					status->num_apps);

				if (!ril->have_sim) {
					DBG("notify SIM inserted");
					ril->have_sim = TRUE;

					ofono_sim_inserted_notify(ril->sim, TRUE);
				}

			} else {
				ofono_warn("Card NOT_PRESENT.");

				if (ril->have_sim) {
					DBG("notify SIM removed");
					ril->have_sim = FALSE;

					ofono_sim_inserted_notify(ril->sim, FALSE);
				}
			}
			g_ril_reply_free_sim_status(status);
		}
	}
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
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 reply_sim_status *status;
	guint search_index;

	status = g_ril_reply_parse_sim_status(sd->ril, message);
	if (status == NULL) {
		ofono_error("%s: Cannot parse SIM status reply", __func__);
		return;
	}

	DBG("SIM status is %u", status->card_state);

	if (status->card_state == RIL_CARDSTATE_PRESENT)
		ofono_sim_inserted_notify(sim, TRUE);
	else if (status && status->card_state == RIL_CARDSTATE_ABSENT)
		ofono_sim_inserted_notify(sim, FALSE);
	else
		ofono_error("%s: bad SIM state (%u)",
				__func__, status->card_state);

	if (status->card_state == RIL_CARDSTATE_PRESENT) {
		/*
		 * TODO(CDMA): need some kind of logic
		 * to set the correct app_index
		 */
		search_index = status->gsm_umts_index;
		if (search_index > status->num_apps &&
				sd->vendor == OFONO_RIL_VENDOR_QCOM_MSIM) {
			/*
			 * On QCOM's multi SIM device, all index will be -1
			 * (but will wrap up to UINT_MAX because index is uint)
			 * until we send RIL_REQUEST_SET_UICC_SUBSCRIPTION.
			 * So, we need to figure out which app to use
			 * and send that request out.
			 */
			search_index = sim_select_uicc_subscription(sim,
									status);
		}

		if (search_index < status->num_apps) {
			struct reply_sim_app *app = status->apps[search_index];

			if (app->app_type != RIL_APPTYPE_UNKNOWN) {
				/*
				 * 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.
				 */
				configure_active_app(sd, app, search_index);
				DBG("passwd_state: %d", sd->passwd_state);

				/*
				 * 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);
			}
		}
	}

	g_ril_reply_free_sim_status(status);
}