All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 1/4] sim: header definitions for AID session APIs
@ 2017-11-03 22:34 James Prestwood
  2017-11-03 22:34 ` [PATCHv2 2/4] sim: AID session management James Prestwood
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: James Prestwood @ 2017-11-03 22:34 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 4073 bytes --]

ISIM and newer AID's require opening a logical channel to read
their EF's. This requires new driver API's to discover AID's,
open/close a channel, and reading the EF's from an opened channel.

This functionality was moved from the simauth module.
---
 include/sim.h | 30 ++++++++++++++++++++++++++++++
 src/ofono.h   | 27 +++++++++++++++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/include/sim.h b/include/sim.h
index 0c91ce2..4c0d4b1 100644
--- a/include/sim.h
+++ b/include/sim.h
@@ -121,6 +121,18 @@ typedef void (*ofono_sim_lock_unlock_cb_t)(const struct ofono_error *error,
 typedef void (*ofono_query_facility_lock_cb_t)(const struct ofono_error *error,
 					ofono_bool_t status, void *data);
 
+typedef void (*ofono_sim_list_apps_cb_t)(const struct ofono_error *error,
+					const unsigned char *dataobj,
+					int len, void *data);
+typedef void (*ofono_sim_open_channel_cb_t)(const struct ofono_error *error,
+					int session_id, void *data);
+
+typedef void (*ofono_sim_close_channel_cb_t)(const struct ofono_error *error,
+					void *data);
+
+typedef void (*ofono_sim_session_event_cb_t)(ofono_bool_t active,
+		int session_id, void *data);
+
 struct ofono_sim_driver {
 	const char *name;
 	int (*probe)(struct ofono_sim *sim, unsigned int vendor, void *data);
@@ -173,6 +185,24 @@ struct ofono_sim_driver {
 	void (*query_facility_lock)(struct ofono_sim *sim,
 			enum ofono_sim_password_type lock,
 			ofono_query_facility_lock_cb_t cb, void *data);
+	void (*list_apps)(struct ofono_sim *sim,
+			ofono_sim_list_apps_cb_t cb, void *data);
+	void (*open_channel)(struct ofono_sim *sim, const unsigned char *aid,
+			ofono_sim_open_channel_cb_t cb, void *data);
+	void (*close_channel)(struct ofono_sim *sim, int session_id,
+			ofono_sim_close_channel_cb_t cb, void *data);
+	void (*session_read_binary)(struct ofono_sim *sim, int session,
+			int fileid, int start, int length,
+			const unsigned char *path, unsigned int path_len,
+			ofono_sim_read_cb_t cb, void *data);
+	void (*session_read_record)(struct ofono_sim *sim, int session_id,
+			int fileid, int record, int length,
+			const unsigned char *path, unsigned int path_len,
+			ofono_sim_read_cb_t cb, void *data);
+	void (*session_read_info)(struct ofono_sim *sim, int session_id,
+			int fileid, const unsigned char *path,
+			unsigned int path_len, ofono_sim_file_info_cb_t cb,
+			void *data);
 };
 
 int ofono_sim_driver_register(const struct ofono_sim_driver *d);
diff --git a/src/ofono.h b/src/ofono.h
index bac4b48..ddfd045 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -370,6 +370,9 @@ unsigned short __ofono_sms_get_next_ref(struct ofono_sms *sms);
 
 #include <ofono/sim.h>
 
+struct ofono_sim_aid_session;
+enum sim_app_type;
+
 ofono_bool_t __ofono_sim_ust_service_available(struct ofono_sim *sim,
 						int ust_service);
 ofono_bool_t __ofono_sim_service_available(struct ofono_sim *sim,
@@ -389,6 +392,30 @@ void __ofono_sim_refresh(struct ofono_sim *sim, GSList *file_list,
 
 void __ofono_sim_recheck_pin(struct ofono_sim *sim);
 
+GSList *__ofono_sim_get_aid_list(struct ofono_sim *sim);
+
+unsigned int __ofono_sim_add_session_watch(
+		struct ofono_sim_aid_session *session,
+		ofono_sim_session_event_cb_t notify, void *data,
+		ofono_destroy_func destroy);
+
+void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
+		unsigned int id);
+
+struct ofono_sim_aid_session *__ofono_sim_get_session_by_aid(
+		struct ofono_sim *sim, unsigned char *aid);
+
+struct ofono_sim_aid_session *__ofono_sim_get_session_by_type(
+		struct ofono_sim *sim, enum sim_app_type type);
+
+int __ofono_sim_session_get_id(struct ofono_sim_aid_session *session);
+
+enum sim_app_type __ofono_sim_session_get_type(
+		struct ofono_sim_aid_session *session);
+
+unsigned char *__ofono_sim_session_get_aid(
+		struct ofono_sim_aid_session *session);
+
 #include <ofono/stk.h>
 
 typedef void (*__ofono_sms_sim_download_cb_t)(ofono_bool_t ok,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCHv2 2/4] sim: AID session management
  2017-11-03 22:34 [PATCHv2 1/4] sim: header definitions for AID session APIs James Prestwood
@ 2017-11-03 22:34 ` James Prestwood
  2017-11-03 22:34 ` [PATCHv2 3/4] atmodem: helper for appending the file path to a command James Prestwood
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: James Prestwood @ 2017-11-03 22:34 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 8793 bytes --]

Accessing an AID requires opening a channel to that application.
This patch implements session management API's so that other atoms
can access a given AID. Now any atom can get a session ID from the
sim atom. This will either reuse an existing session or open a new
channel. Once done, the atom should release the session which will
automatically close the channel when no atoms are using it.

The major functional change to the sim atom is the AID discovery
phase of initialization. Now, the sim atom is not 'ready' until AID
discovery finishes where before, the sim was 'ready' after the IMSI
had been obtained. If application discovery is not supported then
the the sim atom behaves as it did before.
---
 src/sim.c | 255 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 255 insertions(+)

diff --git a/src/sim.c b/src/sim.c
index 155f421..3a084c6 100644
--- a/src/sim.c
+++ b/src/sim.c
@@ -48,6 +48,26 @@
 
 #define SIM_FLAG_READING_SPN	0x1
 
+/*
+ * A new session object will be created if a USim/ISim applications are
+ * found during app discovery. Any concurrent file/logical access to
+ * these applications will share the same session ID.
+ */
+enum session_state {
+	SESSION_STATE_INACTIVE,
+	SESSION_STATE_OPENING,
+	SESSION_STATE_CLOSING,
+	SESSION_STATE_OPEN
+};
+
+struct ofono_sim_aid_session {
+	struct sim_app_record *record;
+	int session_id;
+	struct ofono_sim *sim;
+	struct ofono_watchlist *watches;
+	enum session_state state;
+};
+
 struct ofono_sim {
 	int flags;
 
@@ -114,6 +134,9 @@ struct ofono_sim {
 	void *driver_data;
 	struct ofono_atom *atom;
 	unsigned int hfp_watch;
+
+	GSList *aid_sessions;
+	GSList *aid_list;
 };
 
 struct msisdn_set_request {
@@ -1434,6 +1457,36 @@ static void sim_set_ready(struct ofono_sim *sim)
 	call_state_watches(sim);
 }
 
+static void discover_apps_cb(const struct ofono_error *error,
+		const unsigned char *dataobj,
+		int len, void *data)
+{
+	GSList *iter;
+	struct ofono_sim *sim = data;
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+		return;
+
+	sim->aid_list = sim_parse_app_template_entries(dataobj, len);
+
+	iter = sim->aid_list;
+
+	while (iter) {
+		struct sim_app_record *app = iter->data;
+		struct ofono_sim_aid_session *s = g_try_new0(
+				struct ofono_sim_aid_session, 1);
+
+		s->watches = __ofono_watchlist_new(g_free);
+		s->record = app;
+		s->sim = sim;
+		s->session_id = -1;
+		s->state = SESSION_STATE_INACTIVE;
+		sim->aid_sessions = g_slist_prepend(sim->aid_sessions, s);
+
+		iter = g_slist_next(iter);
+	}
+}
+
 static void sim_imsi_obtained(struct ofono_sim *sim, const char *imsi)
 {
 	DBusConnection *conn = ofono_dbus_get_connection();
@@ -1844,6 +1897,12 @@ static void sim_initialize_after_pin(struct ofono_sim *sim)
 {
 	sim->context = ofono_sim_context_create(sim);
 
+	/*
+	 * Discover applications on SIM
+	 */
+	if (sim->driver->list_apps)
+		sim->driver->list_apps(sim, discover_apps_cb, sim);
+
 	ofono_sim_read(sim->context, SIM_EFPHASE_FILEID,
 			OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
 			sim_efphase_read_cb, sim);
@@ -2386,6 +2445,15 @@ static void sim_spn_close(struct ofono_sim *sim)
 	sim->spn_dc = NULL;
 }
 
+static void aid_session_free(gpointer data)
+{
+	struct ofono_sim_aid_session *session = data;
+
+	__ofono_watchlist_free(session->watches);
+
+	g_free(session);
+}
+
 static void sim_free_main_state(struct ofono_sim *sim)
 {
 	if (sim->imsi) {
@@ -2450,6 +2518,9 @@ static void sim_free_main_state(struct ofono_sim *sim)
 		ofono_sim_context_free(sim->context);
 		sim->context = NULL;
 	}
+
+	if (sim->aid_sessions)
+		g_slist_free_full(sim->aid_sessions, aid_session_free);
 }
 
 static void sim_free_state(struct ofono_sim *sim)
@@ -3304,3 +3375,187 @@ void __ofono_sim_refresh(struct ofono_sim *sim, GSList *file_list,
 		}
 	}
 }
+
+static void open_channel_cb(const struct ofono_error *error, int session_id,
+		void *data);
+
+static void close_channel_cb(const struct ofono_error *error, void *data)
+{
+	struct ofono_sim_aid_session *session = data;
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+		DBG("session %d failed to close", session->session_id);
+
+	if (g_slist_length(session->watches->items) > 0 &&
+				session->state == SESSION_STATE_OPENING) {
+		/*
+		 * An atom requested to open during a close, we can re-open
+		 * here.
+		 */
+		session->sim->driver->open_channel(session->sim,
+				session->record->aid, open_channel_cb,
+				session);
+		return;
+	}
+
+	session->state = SESSION_STATE_INACTIVE;
+}
+
+static void open_channel_cb(const struct ofono_error *error, int session_id,
+		void *data)
+{
+	struct ofono_sim_aid_session *session = data;
+	GSList *iter = session->watches->items;
+	ofono_bool_t active = TRUE;
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+		session->state = SESSION_STATE_INACTIVE;
+		session->session_id = 0;
+		active = FALSE;
+		goto end;
+	}
+
+	if (g_slist_length(iter) == 0) {
+		/*
+		 * All watchers stopped watching before the channel could open.
+		 * Close the channel.
+		 */
+		session->state = SESSION_STATE_CLOSING;
+		session->sim->driver->close_channel(session->sim,
+				session->session_id, close_channel_cb, session);
+		return;
+	}
+
+	session->session_id = session_id;
+	session->state = SESSION_STATE_OPEN;
+end:
+	/*
+	 * Notify any watchers, after this point, all future watchers will be
+	 * immediately notified with the session ID.
+	 */
+	while (iter) {
+		struct ofono_watchlist_item *item = iter->data;
+		ofono_sim_session_event_cb_t notify = item->notify;
+
+		notify(active, session->session_id, item->notify_data);
+
+		iter = g_slist_next(iter);
+	}
+}
+
+unsigned int __ofono_sim_add_session_watch(
+		struct ofono_sim_aid_session *session,
+		ofono_sim_session_event_cb_t notify, void *data,
+		ofono_destroy_func destroy)
+{
+	struct ofono_watchlist_item *item;
+
+	DBG("%p", session);
+
+	if (session == NULL)
+		return 0;
+
+	if (notify == NULL)
+		return 0;
+
+	item = g_new0(struct ofono_watchlist_item, 1);
+
+	item->notify = notify;
+	item->destroy = destroy;
+	item->notify_data = data;
+
+	if (g_slist_length(session->watches->items) == 0 &&
+			session->state == SESSION_STATE_INACTIVE) {
+		/*
+		 * If the session is inactive and there are no watchers, open
+		 * a new session.
+		 */
+		session->state = SESSION_STATE_OPENING;
+		session->sim->driver->open_channel(session->sim,
+				session->record->aid, open_channel_cb,
+				session);
+	} else if (session->state == SESSION_STATE_OPEN) {
+		/*
+		 * Session is already open and available, just call the
+		 * notify callback immediately.
+		 */
+		notify(TRUE, session->session_id, data);
+	} else if (session->state == SESSION_STATE_CLOSING) {
+		/*
+		 * There is a pending close, the close callback will handle
+		 * re-opening the session.
+		 */
+		session->state = SESSION_STATE_OPENING;
+	}
+
+	return __ofono_watchlist_add_item(session->watches, item);
+}
+
+void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
+		unsigned int id)
+{
+	if (g_slist_length(session->watches->items) == 1) {
+		/* last watcher, close session */
+		session->state = SESSION_STATE_CLOSING;
+		session->sim->driver->close_channel(session->sim,
+				session->session_id, close_channel_cb, session);
+	}
+
+	__ofono_watchlist_remove_item(session->watches, id);
+}
+
+struct ofono_sim_aid_session *__ofono_sim_get_session_by_aid(
+		struct ofono_sim *sim, unsigned char *aid)
+{
+	GSList *iter = sim->aid_sessions;
+
+	while (iter) {
+		struct ofono_sim_aid_session *session = iter->data;
+
+		if (!memcmp(session->record->aid, aid, 16))
+			return session;
+
+		iter = g_slist_next(iter);
+	}
+
+	return NULL;
+}
+
+struct ofono_sim_aid_session *__ofono_sim_get_session_by_type(
+		struct ofono_sim *sim, enum sim_app_type type)
+{
+	GSList *iter = sim->aid_sessions;
+
+	while (iter) {
+		struct ofono_sim_aid_session *session = iter->data;
+
+		if (session->record->type == type)
+			return session;
+
+		iter = g_slist_next(iter);
+	}
+
+	return NULL;
+}
+
+int __ofono_sim_session_get_id(struct ofono_sim_aid_session *session)
+{
+	return session->session_id;
+}
+
+enum sim_app_type __ofono_sim_session_get_type(
+		struct ofono_sim_aid_session *session)
+{
+	return session->record->type;
+}
+
+unsigned char *__ofono_sim_session_get_aid(
+		struct ofono_sim_aid_session *session)
+{
+	return session->record->aid;
+}
+
+GSList *__ofono_sim_get_aid_list(struct ofono_sim *sim)
+{
+	return sim->aid_list;
+}
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCHv2 3/4] atmodem: helper for appending the file path to a command
  2017-11-03 22:34 [PATCHv2 1/4] sim: header definitions for AID session APIs James Prestwood
  2017-11-03 22:34 ` [PATCHv2 2/4] sim: AID session management James Prestwood
@ 2017-11-03 22:34 ` James Prestwood
  2017-11-03 22:34 ` [PATCHv2 4/4] atmodem: implement new driver APIs for AID sessions James Prestwood
  2017-11-03 23:04 ` [PATCHv2 1/4] sim: header definitions for AID session APIs Denis Kenzior
  3 siblings, 0 replies; 5+ messages in thread
From: James Prestwood @ 2017-11-03 22:34 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 2596 bytes --]

Several file read API's were re-using the same code to append
a file path. This code was moved into a helper API.
---
 drivers/atmodem/sim.c | 43 ++++++++++++++++++++++---------------------
 1 file changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c
index 8665274..421abfb 100644
--- a/drivers/atmodem/sim.c
+++ b/drivers/atmodem/sim.c
@@ -72,6 +72,22 @@ static const char *qpinc_prefix[] = { "+QPINC:", NULL };
 static const char *upincnt_prefix[] = { "+UPINCNT:", NULL };
 static const char *none_prefix[] = { NULL };
 
+static void append_file_path(char *buf, const unsigned char *path,
+		unsigned int path_len)
+{
+	if (path_len > 0) {
+		*buf++ = ',';
+		*buf++ = ',';
+		*buf++ = '\"';
+
+		for (; path_len; path_len--)
+			buf += sprintf(buf, "%02hhX", *path++);
+
+		*buf++ = '\"';
+		*buf = '\0';
+	}
+}
+
 static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
 	struct cb_data *cbd = user_data;
@@ -176,15 +192,7 @@ static void at_sim_read_info(struct ofono_sim *sim, int fileid,
 		break;
 	}
 
-	if (path_len > 0) {
-		len += sprintf(buf + len, ",,\"");
-
-		for (; path_len; path_len--)
-			len += sprintf(buf + len, "%02hhX", *path++);
-
-		buf[len++] = '\"';
-		buf[len] = '\0';
-	}
+	append_file_path(buf + len, path, path_len);
 
 	if (g_at_chat_send(sd->chat, buf, crsm_prefix,
 				at_crsm_info_cb, cbd, g_free) > 0)
@@ -258,17 +266,7 @@ static void at_sim_read_binary(struct ofono_sim *sim, int fileid,
 	len = snprintf(buf, sizeof(buf), "AT+CRSM=176,%i,%i,%i,%i", fileid,
 			start >> 8, start & 0xff, length);
 
-	if (path_len > 0) {
-		buf[len++] = ',';
-		buf[len++] = ',';
-		buf[len++] = '\"';
-
-		for (; path_len; path_len--)
-			len += sprintf(buf + len, "%02hhX", *path++);
-
-		buf[len++] = '\"';
-		buf[len] = '\0';
-	}
+	append_file_path(buf + len, path, path_len);
 
 	if (g_at_chat_send(sd->chat, buf, crsm_prefix,
 				at_crsm_read_cb, cbd, g_free) > 0)
@@ -288,10 +286,13 @@ static void at_sim_read_record(struct ofono_sim *sim, int fileid,
 	struct sim_data *sd = ofono_sim_get_data(sim);
 	struct cb_data *cbd = cb_data_new(cb, data);
 	char buf[128];
+	unsigned int len;
 
-	snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
+	len = snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
 			record, length);
 
+	append_file_path(buf + len, path, path_len);
+
 	if (g_at_chat_send(sd->chat, buf, crsm_prefix,
 				at_crsm_read_cb, cbd, g_free) > 0)
 		return;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCHv2 4/4] atmodem: implement new driver APIs for AID sessions
  2017-11-03 22:34 [PATCHv2 1/4] sim: header definitions for AID session APIs James Prestwood
  2017-11-03 22:34 ` [PATCHv2 2/4] sim: AID session management James Prestwood
  2017-11-03 22:34 ` [PATCHv2 3/4] atmodem: helper for appending the file path to a command James Prestwood
@ 2017-11-03 22:34 ` James Prestwood
  2017-11-03 23:04 ` [PATCHv2 1/4] sim: header definitions for AID session APIs Denis Kenzior
  3 siblings, 0 replies; 5+ messages in thread
From: James Prestwood @ 2017-11-03 22:34 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 9936 bytes --]

Implementation for open/close channel, list applications,
and session based file read.
---
 drivers/atmodem/sim.c | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 339 insertions(+)

diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c
index 421abfb..6bf5478 100644
--- a/drivers/atmodem/sim.c
+++ b/drivers/atmodem/sim.c
@@ -39,6 +39,7 @@
 #include "gatresult.h"
 #include "simutil.h"
 #include "vendor.h"
+#include "util.h"
 
 #include "atmodem.h"
 
@@ -70,6 +71,9 @@ static const char *pct_prefix[] = { "#PCT:", NULL };
 static const char *pnnm_prefix[] = { "+PNNM:", NULL };
 static const char *qpinc_prefix[] = { "+QPINC:", NULL };
 static const char *upincnt_prefix[] = { "+UPINCNT:", NULL };
+static const char *cuad_prefix[] = { "+CUAD:", NULL };
+static const char *ccho_prefix[] = { "+CCHO:", NULL };
+static const char *crla_prefix[] = { "+CRLA:", NULL };
 static const char *none_prefix[] = { NULL };
 
 static void append_file_path(char *buf, const unsigned char *path,
@@ -1604,6 +1608,335 @@ done:
 	ofono_sim_register(sim);
 }
 
+static void at_discover_apps_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	GAtResultIter iter;
+	ofono_sim_list_apps_cb_t cb = cbd->cb;
+	struct ofono_error error;
+	const unsigned char *dataobj;
+	gint linelen;
+	unsigned char *buffer;
+	int len;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, NULL, 0, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	len = 0;
+	while (g_at_result_iter_next(&iter, "+CUAD:")) {
+		if (!g_at_result_iter_next_hexstring(&iter, NULL, &linelen))
+			goto error;
+
+		len += linelen;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	buffer = g_malloc(len);
+	len = 0;
+
+	while (g_at_result_iter_next(&iter, "+CUAD:")) {
+		g_at_result_iter_next_hexstring(&iter, &dataobj, &linelen);
+		memcpy(buffer + len, dataobj, linelen);
+		len += linelen;
+	}
+
+	cb(&error, buffer, len, cbd->data);
+
+	g_free(buffer);
+	return;
+
+error:
+	CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+}
+
+static void at_discover_apps(struct ofono_sim *sim,
+				ofono_sim_list_apps_cb_t cb,
+				void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	if (g_at_chat_send(sd->chat, "AT+CUAD", cuad_prefix,
+			at_discover_apps_cb, cbd, g_free) > 0)
+		return;
+
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
+}
+
+static void at_open_channel_cb(gboolean ok, GAtResult *result,
+		gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	GAtResultIter iter;
+	ofono_sim_open_channel_cb_t cb = cbd->cb;
+	struct ofono_error error;
+	int session_id = -1;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok)
+		goto error;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CCHO:"))
+		goto error;
+
+	if (!g_at_result_iter_next_number(&iter, &session_id))
+		goto error;
+
+	cb(&error, session_id, cbd->data);
+
+	return;
+
+error:
+	cb(&error, -1, cbd->data);
+}
+
+static void at_open_channel(struct ofono_sim *sim, const unsigned char *aid,
+		ofono_sim_open_channel_cb_t cb, void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char cmd[43];
+	int ret = 0;
+
+	strcpy(cmd, "AT+CCHO=\"");
+	ret += 9;
+
+	encode_hex_own_buf(aid, 16, 0, cmd + ret);
+	ret += 32;
+
+	strcpy(cmd + ret, "\"");
+
+	if (g_at_chat_send(sd->chat, cmd, ccho_prefix, at_open_channel_cb,
+			cbd, g_free) > 0)
+		return;
+
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, -1, data);
+}
+
+static void at_close_channel_cb(gboolean ok, GAtResult *result,
+		gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_sim_close_channel_cb_t cb = cbd->cb;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (cb)
+		cb(&error, cbd->data);
+}
+
+static void at_close_channel(struct ofono_sim *sim, int session_id,
+		ofono_sim_close_channel_cb_t cb, void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char cmd[15];
+
+	sprintf(cmd, "AT+CCHC=%d", session_id);
+
+	g_at_chat_send(sd->chat, cmd, NULL, at_close_channel_cb, cbd, g_free);
+}
+
+static void at_crla_read_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	GAtResultIter iter;
+	ofono_sim_read_cb_t cb = cbd->cb;
+	struct ofono_error error;
+	const guint8 *response;
+	gint sw1, sw2, len;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, NULL, 0, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CRLA:")) {
+		CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_next_number(&iter, &sw1);
+	g_at_result_iter_next_number(&iter, &sw2);
+
+	if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
+			(sw1 == 0x90 && sw2 != 0x00)) {
+		memset(&error, 0, sizeof(error));
+
+		error.type = OFONO_ERROR_TYPE_SIM;
+		error.error = (sw1 << 8) | sw2;
+
+		cb(&error, NULL, 0, cbd->data);
+		return;
+	}
+
+	if (!g_at_result_iter_next_hexstring(&iter, &response, &len)) {
+		CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+		return;
+	}
+
+	DBG("crla_read_cb: %02x, %02x, %d", sw1, sw2, len);
+
+	cb(&error, response, len, cbd->data);
+}
+
+static void at_session_read_binary(struct ofono_sim *sim, int session,
+				int fileid, int start, int length,
+				const unsigned char *path,
+				unsigned int path_len,
+				ofono_sim_read_cb_t cb, void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char buf[64];
+	unsigned int len;
+
+	len = snprintf(buf, sizeof(buf), "AT+CRLA=%i,176,%i,%i,%i,%i,,",
+			session, fileid, start >> 8, start & 0xff, length);
+
+	append_file_path(buf + len, path, path_len);
+
+	if (g_at_chat_send(sd->chat, buf, crla_prefix,
+			at_crla_read_cb, cbd, g_free) > 0)
+		return;
+
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
+}
+
+static void at_session_read_record(struct ofono_sim *sim, int session_id,
+				int fileid, int record, int length,
+				const unsigned char *path,
+				unsigned int path_len,
+				ofono_sim_read_cb_t cb, void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char buf[128];
+	unsigned int len;
+
+	len = snprintf(buf, sizeof(buf), "AT+CRLA=%i,178,%i,%i,4,%i", session_id,
+			fileid, record, length);
+
+	append_file_path(buf + len, path, path_len);
+
+	if (g_at_chat_send(sd->chat, buf, crla_prefix,
+			at_crla_read_cb, cbd, g_free) > 0)
+		return;
+
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
+}
+
+static void at_crla_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	GAtResultIter iter;
+	ofono_sim_file_info_cb_t cb = cbd->cb;
+	struct ofono_error error;
+	const guint8 *response;
+	gint sw1, sw2, len;
+	int flen, rlen;
+	int str;
+	unsigned char access[3];
+	unsigned char file_status;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CRLA:"))
+		goto error;
+
+	g_at_result_iter_next_number(&iter, &sw1);
+	g_at_result_iter_next_number(&iter, &sw2);
+
+	if (!g_at_result_iter_next_hexstring(&iter, &response, &len) ||
+			(sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92) ||
+			(sw1 == 0x90 && sw2 != 0x00)) {
+		memset(&error, 0, sizeof(error));
+
+		error.type = OFONO_ERROR_TYPE_SIM;
+		error.error = (sw1 << 8) | sw2;
+
+		cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
+		return;
+	}
+
+	DBG("crla_info_cb: %02x, %02x, %i", sw1, sw2, len);
+
+	if (response[0] == 0x62) {
+		ok = sim_parse_3g_get_response(response, len, &flen, &rlen,
+						&str, access, NULL);
+
+		file_status = EF_STATUS_VALID;
+	}
+
+	if (!ok)
+		goto error;
+
+	cb(&error, flen, str, rlen, access, file_status, cbd->data);
+
+	return;
+
+error:
+	CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
+				EF_STATUS_INVALIDATED, cbd->data);
+}
+
+static void at_session_read_info(struct ofono_sim *sim, int session_id,
+				int fileid, const unsigned char *path,
+				unsigned int path_len,
+				ofono_sim_file_info_cb_t cb, void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char buf[128];
+	unsigned int len;
+
+	len = snprintf(buf, sizeof(buf), "AT+CRLA=%i,192,%i", session_id,
+			fileid);
+
+	append_file_path(buf + len, path, path_len);
+
+	if (g_at_chat_send(sd->chat, buf, crla_prefix,
+			at_crla_info_cb, cbd, g_free) > 0)
+		return;
+
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
+				EF_STATUS_INVALIDATED, data);
+}
+
 static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
 				void *data)
 {
@@ -1663,6 +1996,12 @@ static struct ofono_sim_driver driver = {
 	.lock			= at_pin_enable,
 	.change_passwd		= at_change_passwd,
 	.query_facility_lock	= at_query_clck,
+	.list_apps		= at_discover_apps,
+	.open_channel		= at_open_channel,
+	.close_channel		= at_close_channel,
+	.session_read_binary	= at_session_read_binary,
+	.session_read_record	= at_session_read_record,
+	.session_read_info	= at_session_read_info,
 };
 
 static struct ofono_sim_driver driver_noef = {
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCHv2 1/4] sim: header definitions for AID session APIs
  2017-11-03 22:34 [PATCHv2 1/4] sim: header definitions for AID session APIs James Prestwood
                   ` (2 preceding siblings ...)
  2017-11-03 22:34 ` [PATCHv2 4/4] atmodem: implement new driver APIs for AID sessions James Prestwood
@ 2017-11-03 23:04 ` Denis Kenzior
  3 siblings, 0 replies; 5+ messages in thread
From: Denis Kenzior @ 2017-11-03 23:04 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 534 bytes --]

Hi James,

On 11/03/2017 05:34 PM, James Prestwood wrote:
> ISIM and newer AID's require opening a logical channel to read
> their EF's. This requires new driver API's to discover AID's,
> open/close a channel, and reading the EF's from an opened channel.
> 
> This functionality was moved from the simauth module.
> ---
>   include/sim.h | 30 ++++++++++++++++++++++++++++++
>   src/ofono.h   | 27 +++++++++++++++++++++++++++
>   2 files changed, 57 insertions(+)
> 

Patches 1-3 applied, thanks.

Regards,
-Denis


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-11-03 23:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-03 22:34 [PATCHv2 1/4] sim: header definitions for AID session APIs James Prestwood
2017-11-03 22:34 ` [PATCHv2 2/4] sim: AID session management James Prestwood
2017-11-03 22:34 ` [PATCHv2 3/4] atmodem: helper for appending the file path to a command James Prestwood
2017-11-03 22:34 ` [PATCHv2 4/4] atmodem: implement new driver APIs for AID sessions James Prestwood
2017-11-03 23:04 ` [PATCHv2 1/4] sim: header definitions for AID session APIs Denis Kenzior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.