aboutsummaryrefslogtreecommitdiffstats
path: root/src/sim/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim/core.c')
-rw-r--r--src/sim/core.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/sim/core.c b/src/sim/core.c
new file mode 100644
index 00000000..40a49cf2
--- /dev/null
+++ b/src/sim/core.c
@@ -0,0 +1,172 @@
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <osmocom/core/talloc.h>
+#include <osmocom/sim/sim.h>
+
+static struct osim_decoded_element *
+__element_alloc(void *ctx, const char *name, enum osim_element_type type,
+ enum osim_element_repr repr)
+{
+ struct osim_decoded_element *elem;
+
+ elem = talloc_zero(ctx, struct osim_decoded_element);
+ if (!elem)
+ return NULL;
+ elem->name = name;
+ elem->type = type;
+ elem->representation = repr;
+
+ if (elem->type == ELEM_T_GROUP)
+ INIT_LLIST_HEAD(&elem->u.siblings);
+
+ return elem;
+}
+
+
+struct osim_decoded_element *
+element_alloc(struct osim_decoded_data *dd, const char *name,
+ enum osim_element_type type, enum osim_element_repr repr)
+{
+ struct osim_decoded_element *elem;
+
+ elem = __element_alloc(dd, name, type, repr);
+ if (!elem)
+ return NULL;
+
+ llist_add_tail(&elem->list, &dd->decoded_elements);
+
+ return elem;
+}
+
+struct osim_decoded_element *
+element_alloc_sub(struct osim_decoded_element *ee, const char *name,
+ enum osim_element_type type, enum osim_element_repr repr)
+{
+ struct osim_decoded_element *elem;
+
+ elem = __element_alloc(ee, name, type, repr);
+ if (!elem)
+ return NULL;
+
+ llist_add(&elem->list, &ee->u.siblings);
+
+ return elem;
+}
+
+
+void add_filedesc(struct osim_file_desc *root, const struct osim_file_desc *in, int num)
+{
+ int i;
+
+ for (i = 0; i < num; i++) {
+ struct osim_file_desc *ofd = talloc_memdup(root, &in[i], sizeof(*in));
+ llist_add_tail(&ofd->list, &root->child_list);
+ }
+}
+
+struct osim_file_desc *alloc_df(void *ctx, uint16_t fid, const char *name)
+{
+ struct osim_file_desc *mf;
+
+ mf = talloc_zero(ctx, struct osim_file_desc);
+ mf->type = TYPE_DF;
+ mf->fid = fid;
+ mf->short_name = name;
+ INIT_LLIST_HEAD(&mf->child_list);
+
+ return mf;
+}
+
+struct osim_file_desc *
+add_df_with_ef(struct osim_file_desc *parent,
+ uint16_t fid, const char *name,
+ const struct osim_file_desc *in, int num)
+{
+ struct osim_file_desc *df;
+
+ df = alloc_df(parent, fid, name);
+ df->parent = parent;
+ llist_add_tail(&df->list, &parent->child_list);
+ add_filedesc(df, in, num);
+
+ return df;
+}
+
+struct osim_file_desc *
+add_adf_with_ef(struct osim_file_desc *parent,
+ const uint8_t *adf_name, uint8_t adf_name_len,
+ const char *name, const struct osim_file_desc *in,
+ int num)
+{
+ struct osim_file_desc *df;
+
+ df = alloc_df(parent, 0xffff, name);
+ df->type = TYPE_ADF;
+ df->df_name = adf_name;
+ df->df_name_len = adf_name_len;
+ df->parent = parent;
+ llist_add_tail(&df->list, &parent->child_list);
+ add_filedesc(df, in, num);
+
+ return df;
+}
+
+struct osim_file_desc *
+osim_file_find_name(struct osim_file_desc *parent, const char *name)
+{
+ struct osim_file_desc *ofd;
+ llist_for_each_entry(ofd, &parent->child_list, list) {
+ if (!strcmp(ofd->short_name, name)) {
+ return ofd;
+ }
+ }
+ return NULL;
+}
+
+
+
+struct msgb *osim_new_apdumsg(uint8_t cla, uint8_t ins, uint8_t p1,
+ uint8_t p2, uint16_t lc, uint16_t le)
+{
+ struct osim_apdu_cmd_hdr *ch;
+ struct msgb *msg = msgb_alloc(lc+le+sizeof(*ch)+2, "APDU");
+ if (!msg)
+ return NULL;
+
+ ch = (struct osim_apdu_cmd_hdr *) msgb_put(msg, sizeof(*ch));
+ msg->l2h = (char *) ch;
+
+ ch->cla = cla;
+ ch->ins = ins;
+ ch->p1 = p1;
+ ch->p2 = p2;
+
+ msgb_apdu_lc(msg) = lc;
+ msgb_apdu_le(msg) = le;
+
+ if (lc == 0 && le == 0)
+ msgb_apdu_case(msg) = APDU_CASE_1;
+ else if (lc == 0 && le >= 1) {
+ if (le <= 256)
+ msgb_apdu_case(msg) = APDU_CASE_2;
+ else
+ msgb_apdu_case(msg) = APDU_CASE_2_EXT;
+ } else if (le == 0 && lc >= 1) {
+ if (lc <= 255)
+ msgb_apdu_case(msg) = APDU_CASE_3;
+ else
+ msgb_apdu_case(msg) = APDU_CASE_3_EXT;
+ } else if (lc >= 1 && le >= 1) {
+ if (lc <= 255 & le <= 256)
+ msgb_apdu_case(msg) = APDU_CASE_4;
+ else
+ msgb_apdu_case(msg) = APDU_CASE_4_EXT;
+ }
+
+ return msg;
+}
+
+
+
+