[WIP] target/fw/sim: SIM Layer 1 driver
[osmocom-bb.git] / src / target / firmware / apps / layer1 / main.c
index d918145..749dde4 100644 (file)
 
 const char *hr = "======================================================================\n";
 
+/* SIM Stuff, TODO: clean it up */
+
+#include <calypso/sim.h>
+
+#include <l1ctl_proto.h>
+
+#define SIM_CLASS              0xA0    /* Class that contains the following instructions */
+#define SIM_GET_RESPONSE       0xC0    /* Get the response of a command from the card */
+#define SIM_READ_BINARY                0xB0    /* Read file in binary mode */
+
+#define L3_MSG_HEAD 4
+
+static uint8_t sim_data[256]; /* buffer for SIM command */
+static volatile uint16_t sim_len = 0; /* lenght of data in sim_data[] */
+
+void sim_apdu(uint16_t len, uint8_t *data)
+{
+       memcpy(sim_data, data, len);
+       sim_len = len;
+}
+
+/* allocate a large enough buffer for the SIM response */
+
+struct msgb *my_l1ctl_msgb_alloc(uint8_t msg_type)
+{
+       struct msgb *msg;
+       struct l1ctl_hdr *l1h;
+
+       msg = msgb_alloc_headroom(256, L3_MSG_HEAD, "l1ctl1");
+       if (!msg) {
+               while (1) {
+                       puts("OOPS. Out of buffers...\n");
+               }
+
+               return NULL;
+       }
+       l1h = (struct l1ctl_hdr *) msgb_put(msg, sizeof(*l1h));
+       l1h->msg_type = msg_type;
+       l1h->flags = 0;
+
+       msg->l1h = (uint8_t *)l1h;
+
+       return msg;
+}
+
+static void sim_handler(void)
+{
+       uint8_t status_word[2];
+       struct msgb *msg;
+       uint8_t *dat;
+       uint16_t length;
+
+       if(sim_len) /* a new SIM command has arrived */
+       {
+               status_word[0] = 0;
+               status_word[1] = 0;
+
+               msg = my_l1ctl_msgb_alloc(L1CTL_SIM_CONF);
+
+               /* check if instructions expects a response (TODO: add more instructions */
+               if (/* GET RESPONSE needs SIM_APDU_GET */
+                   (sim_len == 5 && sim_data[0] == SIM_CLASS &&
+                    sim_data[1] == SIM_GET_RESPONSE && sim_data[2] == 0x00 &&
+                    sim_data[3] == 0x00) ||
+                   /* READ BINARY needs SIM_APDU_GET */
+                    (sim_len >= 5 && sim_data[0] == SIM_CLASS &&
+                     sim_data[1] == SIM_READ_BINARY))
+               {
+                       /* allocate space for expected response */
+                       length = sim_data[4];
+                       dat = msgb_put(msg, length + 2);
+
+                       if(calypso_sim_transceive(sim_data[0], sim_data[1], sim_data[2], sim_data[3], sim_data[4], dat, status_word, SIM_APDU_GET) != 0)
+                               puts("SIM ERROR !\n");
+                       printf("Status 1: %02X %02X\n", status_word[0], status_word[1]);
+
+                       /* copy status at the end */
+                       memcpy(dat + length, status_word, 2);
+
+                       l1_queue_for_l2(msg);
+               }
+               else
+               {
+                       if(calypso_sim_transceive(sim_data[0], sim_data[1], sim_data[2], sim_data[3], sim_data[4], &sim_data[5], status_word, SIM_APDU_PUT) != 0)
+                               puts("SIM ERROR !\n");
+                       printf("Status 2: %02X %02X\n", status_word[0], status_word[1]);
+
+                       /* 2 bytes status */
+                       length = 2;
+                       dat = msgb_put(msg, length);
+                       memcpy(dat, status_word, length);
+
+                       l1_queue_for_l2(msg);
+               }
+
+               sim_len = 0;
+       }
+}
+
 /* MAIN program **************************************************************/
 
 static void key_handler(enum key_codes code, enum key_states state);
 
+/* called while waiting for SIM */
+
+void sim_wait_handler(void)
+{
+       l1a_compl_execute();
+       update_timers();
+}
+
 int main(void)
 {
+       uint8_t atr[20];
+       uint8_t atrLength = 0;
+
        board_init();
 
        puts("\n\nOSMOCOM Layer 1 (revision " GIT_REVISION ")\n");
@@ -72,6 +182,14 @@ int main(void)
        display_set_attr(DISP_ATTR_INVERT);
        display_puts("layer1.bin");
 
+       /* initialize SIM */
+        calypso_sim_init(sim_wait_handler);
+
+        puts("Power up simcard:\n");
+        memset(atr,0,sizeof(atr));
+        atrLength = calypso_sim_powerup(atr);
+
+
        layer1_init();
 
        tpu_frame_irq_en(1, 1);
@@ -79,6 +197,7 @@ int main(void)
        while (1) {
                l1a_compl_execute();
                update_timers();
+               sim_handler();
        }
 
        /* NOT REACHED */
@@ -156,6 +275,9 @@ static void key_handler(enum key_codes code, enum key_states state)
        default:
                break;
        }
+       /* power down SIM, TODO:  this will happen with every key pressed,
+       put it somewhere else ! */
+       calypso_sim_powerdown();
 }