sim: re-structure how we support cards + applications

Before this change, a card application (USIM, ISIM, ...) didn't
exist as a separate concept from a card profile.  This meant,
we had a manual combination of UICC card profile with USIM application,
and another one of UICC card profile and ISIM application.  But what
if there's a combined USIM+ISIM?

In reality, applications exist as separate objects, on top of an
ETSI UICC.  Lets therefore register all known applications to the
osim library core, and add code to osmo-sim-test which dynamically
detects all applications present on a given card (by reading EF.DIR).

Change-Id: Ic4b4ac433a9976842b30a017fb0fc347d87201cd
diff --git a/include/osmocom/sim/sim.h b/include/osmocom/sim/sim.h
index 5440d85..33ebdd7 100644
--- a/include/osmocom/sim/sim.h
+++ b/include/osmocom/sim/sim.h
@@ -9,6 +9,7 @@
 #include <osmocom/core/linuxlist.h>
 
 #define APDU_HDR_LEN	5
+#define MAX_AID_LEN	16 /* Table 13.2 of TS 102 221 */
 
 /*! command-response pairs cases
  *
@@ -66,6 +67,8 @@
 #define msgb_apdu_dc(__x)	((__x)->l2h + sizeof(struct osim_apdu_cmd_hdr))
 #define msgb_apdu_de(__x)	((__x)->l2h + sizeof(struct osim_apdu_cmd_hdr) + msgb_apdu_lc(__x))
 
+int osim_init(void *ctx);
+
 /* FILES */
 
 struct osim_file;
@@ -285,6 +288,28 @@
 	.class = SW_CLS_NONE, .u.str = NULL		\
 }
 
+/*! A card application (e.g. USIM, ISIM, HPSIM) */
+struct osim_card_app_profile {
+	/*! entry in the global list of card application profiles */
+	struct llist_head list;
+	/*! human-readable name */
+	const char *name;
+	/*! AID of this application, as used in EF.DIR */
+	uint8_t aid[MAX_AID_LEN];
+	uint8_t aid_len;
+	/*! file system description */
+	struct osim_file_desc *adf;
+	/*! Status words defined by application */
+	const struct osim_card_sw *sw;
+};
+
+const struct osim_card_app_profile *
+osim_app_profile_find_by_name(const char *name);
+
+const struct osim_card_app_profile *
+osim_app_profile_find_by_aid(const uint8_t *aid, uint8_t aid_len);
+
+
 /*! A card profile (e.g. SIM card */
 struct osim_card_profile {
 	const char *name;
@@ -357,6 +382,19 @@
 	struct osim_card_hdl *card;
 };
 
+/*! descriptor for a given application present on a card */
+struct osim_card_app_hdl {
+	/*! member in card list of applications */
+	struct llist_head list;
+	/*! AID of the application */
+	uint8_t aid[MAX_AID_LEN];
+	uint8_t aid_len;
+	/*! application label from EF_DIR */
+	char *label;
+	/*! application profile (if any known) */
+	const struct osim_card_app_profile *prof;
+};
+
 struct osim_card_hdl {
 	/*! member in global list of cards */
 	struct llist_head list;
@@ -369,6 +407,9 @@
 
 	/*! list of channels for this card */
 	struct llist_head channels;
+
+	/*! list of applications found on card */
+	struct llist_head apps;
 };
 
 struct osim_chan_hdl {
@@ -376,9 +417,15 @@
 	struct llist_head list;
 	/*! card to which this channel belongs */
 	struct osim_card_hdl *card;
+	/*! current working directory */
 	const struct osim_file_desc *cwd;
+	/*! currently selected application (if any) */
+	struct osim_card_app_hdl *cur_app;
 };
 
+int osim_card_hdl_add_app(struct osim_card_hdl *ch, const uint8_t *aid, uint8_t aid_len,
+			  const char *label);
+
 /* reader.c */
 int osim_transceive_apdu(struct osim_chan_hdl *st, struct msgb *amsg);
 struct osim_reader_hdl *osim_reader_open(enum osim_reader_driver drv, int idx,