Merge branch 'master' into testing testing
authorDobrica Pavlinusic <dpavlin@rot13.org>
Tue, 18 Jan 2011 16:33:38 +0000 (17:33 +0100)
committerDobrica Pavlinusic <dpavlin@rot13.org>
Tue, 18 Jan 2011 16:33:38 +0000 (17:33 +0100)
include/l1ctl_proto.h
src/host/layer23/src/common/l1ctl.c
src/target/firmware/Makefile
src/target/firmware/apps/layer1/main.c
src/target/firmware/apps/simtest/main.c
src/target/firmware/calypso/sim.c [changed mode: 0755->0644]
src/target/firmware/include/calypso/sim.h
src/target/firmware/layer1/l23_api.c
src/target/firmware/layer1/prim_tch.c
src/target/firmware/layer1/sync.c

index 9adadfd..f5ea1f9 100644 (file)
@@ -51,6 +51,9 @@ enum {
        L1CTL_SIM_CONF,
        L1CTL_TCH_MODE_REQ,
        L1CTL_TCH_MODE_CONF,
+       L1CTL_VOICE_REQ,
+       L1CTL_VOICE_CONF,
+       L1CTL_VOICE_IND,
 };
 
 enum ccch_mode {
@@ -120,6 +123,11 @@ struct l1ctl_data_ind {
        uint8_t data[23];
 } __attribute__((packed));
 
+/* voice data from network */
+struct l1ctl_voice_ind {
+       uint8_t data[33];
+} __attribute__((packed));
+
 /*
  * uplink info
  */
@@ -255,4 +263,9 @@ struct l1ctl_reset {
        uint8_t pad[3];
 } __attribute__((packed));
 
+/* voice data to network */
+struct l1ctl_voice_req {
+       uint8_t data[33];
+} __attribute__((packed));
+
 #endif /* __L1CTL_PROTO_H__ */
index ac8bac8..d4d394d 100644 (file)
@@ -724,6 +724,36 @@ static int rx_l1_tch_mode_conf(struct osmocom_ms *ms, struct msgb *msg)
        return 0;
 }
 
+/* Receive L1CTL_VOICE_IND (Voice Indication from L1) */
+static int rx_l1_voice_ind(struct osmocom_ms *ms, struct msgb *msg)
+{
+       struct l1ctl_info_dl *dl;
+       struct l1ctl_voice_ind *vi;
+
+       /* Header handling */
+       dl = (struct l1ctl_info_dl *) msg->l1h;
+       msg->l2h = dl->payload;
+       vi = (struct l1ctl_voice_ind *) msg->l2h;
+
+       LOGP(DL1C, LOGL_INFO, "VOICE IND\n");
+
+       {
+               static FILE *out = NULL;
+               int i;
+
+               if (!out)
+                       out = fopen("voice.raw", "wb");
+
+               fwrite(vi->data, 33, 1, out);
+
+               for (i=0; i<33; i++)
+                       printf("%02x ", vi->data[i]);
+               printf("\n");
+       }
+
+       return 0;
+}
+
 /* Receive incoming data from L1 using L1CTL format */
 int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
 {
@@ -780,6 +810,10 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
        case L1CTL_SIM_CONF:
                rc = rx_l1_sim_conf(ms, msg);
                break;
+       case L1CTL_VOICE_IND:
+               rc = rx_l1_voice_ind(ms, msg);
+               msgb_free(msg);
+               break;
        default:
                LOGP(DL1C, LOGL_ERROR, "Unknown MSG: %u\n", l1h->msg_type);
                msgb_free(msg);
index 56e0068..c69aab7 100644 (file)
@@ -73,7 +73,7 @@ ANY_APP_LIBS+=calypso/libcalypso.a layer1/liblayer1.a lib/libmini.a comm/libcomm
 -include Makefile.inc
 
 # Uncomment this line if you want to enable Tx (Transmit) Support.
-#CFLAGS += -DCONFIG_TX_ENABLE
+CFLAGS += -DCONFIG_TX_ENABLE
 
 # Uncomment this line if you want to write to flash.
 #CFLAGS += -DCONFIG_FLASH_WRITE
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();
 }
 
 
index 83f708e..d055672 100755 (executable)
@@ -52,14 +52,14 @@ static void myHexdump(uint8_t *data, int len)
        int i;
 
        for(i=0;i<len;i++)
-               printf("%x ",data[i]);
+               printf("%02x ",data[i]);
 
        printf("(%i bytes)\n", len);
 
        return;
 }
 
-/* SIM instructions 
+/* SIM instructions
    All instructions a standard sim card must feature: */
 #define SIM_CLASS 0xA0                 /* Class that contains the following instructions */
 #define SIM_SELECT 0xA4                        /* Select a file on the card */
@@ -135,7 +135,7 @@ uint16_t sim_select(uint16_t fid)
 }
 
 /* Get the status of the currently selected file */
-uint16_t sim_status(void) 
+uint16_t sim_status(void)
 {
        uint8_t status_word[2];
 
@@ -158,6 +158,58 @@ uint16_t sim_readbinary(uint8_t offset_high, uint8_t offset_low, uint8_t length,
        return (status_word[0] << 8) | status_word[1];
 }
 
+uint16_t sim_verify(char *pin)
+{
+       uint8_t txBuffer[8];
+       uint8_t status_word[2];
+
+       memset(txBuffer, 0xFF, 8);
+       memcpy(txBuffer, pin, strlen(pin));
+
+       if(calypso_sim_transceive(SIM_CLASS, SIM_VERIFY_CHV, 0x00, 0x01, 0x08, txBuffer,status_word, SIM_APDU_PUT) != 0)
+               return 0xFFFF;
+
+       return (status_word[0] << 8) | status_word[1];
+}
+
+uint16_t sim_run_gsm_algorith(uint8_t *data)
+{
+       uint8_t status_word[2];
+
+       if(calypso_sim_transceive(SIM_CLASS, SIM_RUN_GSM_ALGORITHM, 0x00, 0x00, 0x10, data, status_word, SIM_APDU_PUT) != 0)
+               return 0xFFFF;
+
+       printf("   ==> Status word: %x\n", (status_word[0] << 8) | status_word[1]);
+
+       if(status_word[0] != 0x9F || status_word[1] != 0x0C)
+               return (status_word[0] << 8) | status_word[1];
+
+       /* GET RESPONSE */
+
+       if(calypso_sim_transceive(SIM_CLASS, SIM_GET_RESPONSE, 0, 0, 0x0C, data ,status_word, SIM_APDU_GET) != 0)
+               return 0xFFFF;
+
+       return (status_word[0] << 8) | status_word[1];
+}
+
+
+/* FIXME: We need proper calibrated delay loops at some point! */
+void delay_us(unsigned int us)
+{
+       volatile unsigned int i;
+
+       for (i= 0; i < us*4; i++) { i; }
+}
+
+void delay_ms(unsigned int ms)
+{
+       volatile unsigned int i;
+       for (i= 0; i < ms*1300; i++) { i; }
+}
+
+
+
+
 /* Execute my (dexter's) personal test */
 void do_sim_test(void)
 {
@@ -171,7 +223,7 @@ void do_sim_test(void)
 
        uint8_t atr[20];
        uint8_t atrLength = 0;
-       
+
        memset(atr,0,sizeof(atr));
 
 
@@ -185,7 +237,7 @@ void do_sim_test(void)
 
        /* Initialize Sim-Controller driver */
        puts("Initializing driver:\n");
-       calypso_sim_init();
+       calypso_sim_init(NULL);
 
        /* Power up sim and display ATR */
        puts("Power up simcard:\n");
@@ -215,6 +267,9 @@ void do_sim_test(void)
        puts(" * Testing SELECT: Selecting DF_GSM\n");
        printf("   ==> Status word: %x\n", sim_select(SIM_DF_GSM));
 
+       puts(" * Testing PIN VERIFY\n");
+       printf("   ==> Status word: %x\n", sim_verify("1234"));
+
        puts(" * Testing SELECT: Selecting EF_IMSI\n");
        printf("   ==> Status word: %x\n", sim_select(SIM_EF_IMSI));
 
@@ -222,11 +277,18 @@ void do_sim_test(void)
        printf("   ==> Status word: %x\n", sim_status());
 
        memset(buffer,0,sizeof(buffer));
-       puts(" * Testing READ BINARY:\n");      
+       puts(" * Testing READ BINARY:\n");
        printf("   ==> Status word: %x\n", sim_readbinary(0,0,9,buffer));
        printf("       Data: ");
        myHexdump(buffer,9);
 
+       memset(buffer,0,sizeof(buffer));
+       memcpy(buffer,"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff",16);
+       puts(" * Testing RUN GSM ALGORITHM\n");
+       printf("   ==> Status word: %x\n", sim_run_gsm_algorith(buffer));
+       printf("       Result: ");
+       myHexdump(buffer,12);
+
        delay_ms(5000);
 
        calypso_sim_powerdown();
old mode 100755 (executable)
new mode 100644 (file)
index a539cf8..214d689
 #include <calypso/sim.h>
 #include <calypso/irq.h>
 
-static int sim_rx_character_count = 0; /* How many bytes have been received by calypso_sim_receive() */
-static int sim_tx_character_count = 0; /* How many bytes have been transmitted by calypso_sim_transmit() */
-static int sim_tx_character_length = 0;        /* How many bytes have to be transmitted by calypso_sim_transmit() */
+static void (*sim_wait_cb)(void) = NULL; /* called during waiting for SIM */
+static volatile uint8_t sim_ignore_waiting_char = 0; /* signal ignoring of NULL procedure byte */
+static volatile int sim_rx_character_count = 0;        /* How many bytes have been received by calypso_sim_receive() */
+static volatile int sim_rx_max_character_count = 0;    /* How many bytes have been received by calypso_sim_receive() */
+static volatile int sim_tx_character_count = 0;        /* How many bytes have been transmitted by calypso_sim_transmit() */
+static volatile int sim_tx_character_length = 0;       /* How many bytes have to be transmitted by calypso_sim_transmit() */
 static uint8_t *rx_buffer = 0;         /* RX-Buffer that is issued by calypso_sim_receive() */
 static uint8_t *tx_buffer = 0;         /* TX-Buffer that is issued by calypso_sim_transmit() */
 volatile static int rxDoneFlag = 0;    /* Used for rx synchronization instead of a semaphore in calypso_sim_receive() */
@@ -149,25 +152,25 @@ void calypso_sim_regdump(void)
        else
                puts("  |  |-REG_SIM_CONF1_CONFSCLKDIV = 0 ==> SIM clock frequency is 13/4 Mhz.\n");
        delay_ms(SIM_DEBUG_OUTPUTDELAY);
-    
+
        if(regVal & REG_SIM_CONF1_CONFSCLKLEV)
                puts("  |  |-REG_SIM_CONF1_CONFSCLKLEV = 1 ==> SIM clock idle level is high.\n");
        else
                puts("  |  |-REG_SIM_CONF1_CONFSCLKLEV = 0 ==> SIM clock idle level is low.\n");
        delay_ms(SIM_DEBUG_OUTPUTDELAY);
-              
+
        if(regVal & REG_SIM_CONF1_CONFETUPERIOD)
                puts("  |  |-REG_SIM_CONF1_CONFETUPERIOD = 1 ==> ETU period is 512/8*1/Fsclk.\n");
        else
                puts("  |  |-REG_SIM_CONF1_CONFETUPERIOD = 0 ==> ETU period is 372/8*1/Fsclk.\n");
        delay_ms(SIM_DEBUG_OUTPUTDELAY);
-       
+
        if(regVal & REG_SIM_CONF1_CONFBYPASS)
                puts("  |  |-REG_SIM_CONF1_CONFBYPASS = 1 ==> Hardware timers and start and stop sequences are bypassed.\n");
        else
                puts("  |  |-REG_SIM_CONF1_CONFBYPASS = 0 ==> Hardware timers and start and stop sequences are normal.\n");
        delay_ms(SIM_DEBUG_OUTPUTDELAY);
-          
+
        if(regVal & REG_SIM_CONF1_CONFSVCCLEV)
                puts("  |  |-REG_SIM_CONF1_CONFSVCCLEV = 1 ==> SVCC Level is high (Only valid when CONFBYPASS = 1).\n");
        else
@@ -305,7 +308,11 @@ void calypso_sim_regdump(void)
 int calypso_sim_powerup(uint8_t *atr)
 {
        /* Enable level shifters and voltage regulator */
+  #if 1  // 2.9V
        twl3025_reg_write(VRPCSIM, VRPCSIM_SIMLEN | VRPCSIM_RSIMEN | VRPCSIM_SIMSEL);
+  #else // 1.8V
+       twl3025_reg_write(VRPCSIM, VRPCSIM_SIMLEN | VRPCSIM_RSIMEN);
+  #endif
 #if (SIM_DEBUG == 1)
        puts(" * Power enabled!\n");
 #endif
@@ -326,7 +333,7 @@ int calypso_sim_powerup(uint8_t *atr)
 
        /* Catch ATR */
        if(atr != 0)
-               return calypso_sim_receive(atr);
+               return calypso_sim_receive(atr, 0);
        else
                return 0;
 }
@@ -383,18 +390,19 @@ int calypso_sim_reset(uint8_t *atr)
 
        /* Catch ATR */
        if(atr != 0)
-               return calypso_sim_receive(atr);
+               return calypso_sim_receive(atr, 0);
        else
                return 0;
 }
 
 /* Receive raw data through the sim interface */
-int calypso_sim_receive(uint8_t *data)
+int calypso_sim_receive(uint8_t *data, uint8_t len)
 {
        /* Prepare buffers and flags */
        rx_buffer = data;
        sim_rx_character_count = 0;
        rxDoneFlag = 0;
+       sim_rx_max_character_count = len;
 
        /* Switch I/O direction to input */
        writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFTXRX, REG_SIM_CONF1);
@@ -403,14 +411,17 @@ int calypso_sim_receive(uint8_t *data)
        writew(~(REG_SIM_MASKIT_MASK_SIM_RX | REG_SIM_MASKIT_MASK_SIM_WT), REG_SIM_MASKIT);
 
        /* Wait till rxDoneFlag is set */
-       while(rxDoneFlag == 0);
+       while(rxDoneFlag == 0)
+       {
+               if(sim_wait_cb) (*sim_wait_cb)();
+       }
 
        /* Disable all interrupt driven functions by masking all interrupts */
        writew(0xFF, REG_SIM_MASKIT);
 
        /* Hand back the number of bytes received */
        return sim_rx_character_count;
-       
+
        return;
 }
 
@@ -434,8 +445,11 @@ int calypso_sim_transmit(uint8_t *data, int length)
        tx_buffer++;
        sim_tx_character_count++;
 
-       /* Wait till rxDoneFlag is set */
-       while(txDoneFlag == 0);
+       /* Wait till xDoneFlag is set */
+       while(txDoneFlag == 0)
+       {
+               if(sim_wait_cb) (*sim_wait_cb)();
+       }
 
        /* Disable all interrupt driven functions by masking all interrupts */
        writew(0xFF, REG_SIM_MASKIT);
@@ -452,7 +466,7 @@ void sim_irq_handler(enum irq_nr irq)
 
        /* Display interrupt information */
 #if (SIM_DEBUG == 1)
-       puts("SIM-ISR: Interrupt caught: ");
+       puts("SIM-ISR: ");
 #endif
        if(regVal & REG_SIM_IT_SIM_NATR)
        {
@@ -481,30 +495,63 @@ void sim_irq_handler(enum irq_nr irq)
        if(regVal & REG_SIM_IT_SIM_TX)
        {
 #if (SIM_DEBUG == 1)
-               puts(" Waiting for character to transmit...\n");
+               puts(" Waiting for transmit...\n");
 #endif
                if(sim_tx_character_count >= sim_tx_character_length)
+               {
                        txDoneFlag = 1;
+               }
                else
                {
                        writew(*tx_buffer,REG_SIM_DTX);
                        tx_buffer++;
                        sim_tx_character_count++;
+
+       #if 1 /* Dieter: set to 0 to get problems with some cards */
+                       /* its essential to immediately switch to RX after TX is done */
+                       if(sim_tx_character_count >= sim_tx_character_length)
+                       {
+                               /* TODO: set a proper delay here, 4 is to
+                                  long if not debugging and no delay is too short */
+                               delay_ms(1);
+                               /* Switch I/O direction to input */
+                               writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFTXRX, REG_SIM_CONF1);
+                       }
+       #endif
                }
        }
 
        /* Used by: calypso_sim_receive() to receive the incoming data */
        if(regVal & REG_SIM_IT_SIM_RX)
        {
+               uint8_t ch = (uint8_t) (readw(REG_SIM_DRX) & 0xFF);
+               /* ignore NULL procedure byte */
+               if(ch == 0x60 && sim_ignore_waiting_char)
+               {
 #if (SIM_DEBUG == 1)
-               puts(" Waiting characters to be read...\n");
+                       puts(" 0x60 received...\n");
+#endif
+                       return;
+               }
+
+#if (SIM_DEBUG == 1)
+               printf(" Waiting for read (%02X)...\n", ch);
 #endif
                /* Increment character count - this is what calypso_sim_receive() hands back */
                sim_rx_character_count++;
 
                /* Read byte from rx-fifo and write it to the issued buffer */
-               *rx_buffer = (uint8_t) (readw(REG_SIM_DRX) & 0xFF);
+               *rx_buffer = ch;
                rx_buffer++;
+
+               /* to maximise SIM access speed, stop waiting after
+                  all the expected characters have been received. */
+               if(sim_rx_max_character_count && sim_rx_character_count >= sim_rx_max_character_count) {
+#if (SIM_DEBUG == 1)
+                       puts(" Max characters received!\n");
+#endif
+                       rxDoneFlag = 1;
+               }
        }
 }
 
@@ -518,7 +565,7 @@ int calypso_sim_transceive(uint8_t cla,             /* Class (in GSM context mostly 0xA0 *
                                uint8_t *status,        /* Status word (2 byte array, see note 1) */
                                uint8_t mode)           /* Mode of operation: 1=GET, 0=PUT */
 
-                               /* Note 1: You can use a null-pointer (0) if you are not interested in 
+                               /* Note 1: You can use a null-pointer (0) if you are not interested in
                                           the status word */
 {
        uint8_t transmissionBuffer[256];
@@ -543,8 +590,8 @@ int calypso_sim_transceive(uint8_t cla,             /* Class (in GSM context mostly 0xA0 *
 #if (SIM_DEBUG == 1)
                puts("SIM-T0: Case 1: No input, No Output (See also GSM 11.11 Page 34)\n");
 #endif
-               numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
-               
+               numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer, 2);
+
                if(numberOfReceivedBytes == 2)
                {
 #if (SIM_DEBUG == 1)
@@ -555,7 +602,7 @@ int calypso_sim_transceive(uint8_t cla,             /* Class (in GSM context mostly 0xA0 *
                        {
                                status[0] = transmissionBuffer[0];
                                status[1] = transmissionBuffer[1];
-                       }       
+                       }
 
                        return 0;
                }
@@ -575,7 +622,8 @@ int calypso_sim_transceive(uint8_t cla,             /* Class (in GSM context mostly 0xA0 *
                puts("SIM-T0: Case 2: No input / Output of known length (See also GSM 11.11 Page 34)\n");
 #endif
 
-               numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
+               /* TODO: waiting for one character is only OK if no error occurs */
+               numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer, 1);
 
                /* Error situation: The card has aborted, sends no data but a status word */
                if(numberOfReceivedBytes == 2)
@@ -588,11 +636,11 @@ int calypso_sim_transceive(uint8_t cla,           /* Class (in GSM context mostly 0xA0 *
                        {
                                status[0] = transmissionBuffer[0];
                                status[1] = transmissionBuffer[1];
-                       }                               
+                       }
 
                        return 0;
                }
-               /* Acknoledge byte received */
+               /* Acknowledge byte received */
                else if(numberOfReceivedBytes == 1)
                {
 #if (SIM_DEBUG == 1)
@@ -603,15 +651,21 @@ int calypso_sim_transceive(uint8_t cla,           /* Class (in GSM context mostly 0xA0 *
                        {
 #if (SIM_DEBUG == 1)
                                puts("SIM-T0: T0 Protocol error: Invalid ACK byte -- aborting!\n");
-#endif                         
+#endif
                                return -1;
                        }
 
                        /* Transmit body */
                        calypso_sim_transmit(data,p3le);
-                       
+
+                       /* Ignore waiting char for RUN GSM ALGORITHM */
+                       /* TODO: implement proper handling of the "Procedure Bytes"
+                          than this is no longer needed */
+                       if(ins == 0x88)
+                               sim_ignore_waiting_char = 1;
                        /* Receive status word */
-                       numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
+                       numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer, 2);
+                       sim_ignore_waiting_char = 0;
 
                        /* Check status word */
                        if(numberOfReceivedBytes == 2)
@@ -633,7 +687,7 @@ int calypso_sim_transceive(uint8_t cla,             /* Class (in GSM context mostly 0xA0 *
                        {
 #if (SIM_DEBUG == 1)
                                puts("SIM-T0: T0 Protocol error: Missing or invalid status word -- aborting!\n");
-#endif                         
+#endif
                                return -1;
                        }
                }
@@ -653,7 +707,7 @@ int calypso_sim_transceive(uint8_t cla,             /* Class (in GSM context mostly 0xA0 *
                puts("SIM-T0: Case 4: Input / No output (See also GSM 11.11 Page 34)\n");
 #endif
 
-               numberOfReceivedBytes = calypso_sim_receive(data);
+               numberOfReceivedBytes = calypso_sim_receive(data, p3le + 1 + 2);
 
                /* Error situation: The card has aborted, sends no data but a status word */
                if(numberOfReceivedBytes == 2)
@@ -667,7 +721,7 @@ int calypso_sim_transceive(uint8_t cla,             /* Class (in GSM context mostly 0xA0 *
                        {
                                status[0] = data[0];
                                status[1] = data[1];
-                       }                               
+                       }
 
                        return 0;
                }
@@ -683,7 +737,7 @@ int calypso_sim_transceive(uint8_t cla,             /* Class (in GSM context mostly 0xA0 *
                        {
 #if (SIM_DEBUG == 1)
                                puts("SIM-T0: T0 Protocol error: Invalid ACK byte -- aborting!\n");
-#endif                         
+#endif
                                return -1;
                        }
 
@@ -695,8 +749,8 @@ int calypso_sim_transceive(uint8_t cla,             /* Class (in GSM context mostly 0xA0 *
                        {
                                status[0] = data[p3le + 1];
                                status[1] = data[p3le + 2];
-                       }                               
-       
+                       }
+
                        /* Move data one position left to cut away the ACK-Byte */
                        memcpy(data,data+1,p3le);
 
@@ -727,14 +781,20 @@ int calypso_sim_transceive(uint8_t cla,           /* Class (in GSM context mostly 0xA0 *
 
 
 /* Initialize simcard interface */
-void calypso_sim_init(void)
+void calypso_sim_init(void (cb)(void))
 {
        /* Register IRQ handler and turn interrupts on */
 #if (SIM_DEBUG == 1)
        puts("SIM: Registering interrupt handler for simcard-interface\n");
 #endif
        irq_register_handler(IRQ_SIMCARD, &sim_irq_handler);
+  #if 1
        irq_config(IRQ_SIMCARD, 0, 0, 0xff);
+  #else
+       irq_config(IRQ_SIMCARD, 0, 0, 1);
+  #endif
        irq_enable(IRQ_SIMCARD);
+
+       sim_wait_cb = cb;
 }
 
index b2a2164..f0784e1 100755 (executable)
@@ -178,10 +178,10 @@ int calypso_sim_transceive(uint8_t cla,           /* Class (in GSM context mostly 0xA0 *
                                           the status word */
 
 /* Transmission of raw data */
-int calypso_sim_receive(uint8_t *data);                        /* Receive raw data through the sim interface */
+int calypso_sim_receive(uint8_t *data, uint8_t len);                   /* Receive raw data through the sim interface */
 int calypso_sim_transmit(uint8_t *data, int length);   /* Transmit raw data through the sim interface */
 
-void calypso_sim_init(void);                           /* Initialize simcard interface */
+void calypso_sim_init(void (cb)(void));                                /* Initialize simcard interface */
 
 
 /* Known Bugs:
index aef12a5..74b483a 100644 (file)
@@ -46,7 +46,7 @@
 
 /* the size we will allocate struct msgb* for HDLC */
 #define L3_MSG_HEAD 4
-#define L3_MSG_SIZE (sizeof(struct l1ctl_hdr)+sizeof(struct l1ctl_info_dl)+sizeof(struct l1ctl_data_ind) + L3_MSG_HEAD)
+#define L3_MSG_SIZE (sizeof(struct l1ctl_hdr)+sizeof(struct l1ctl_info_dl)+sizeof(struct l1ctl_voice_ind) + L3_MSG_HEAD)
 
 void l1_queue_for_l2(struct msgb *msg)
 {
@@ -462,6 +462,28 @@ static void l1ctl_rx_tch_mode_req(struct msgb *msg)
        l1ctl_tx_tch_mode_conf(tch_mode);
 }
 
+#include <calypso/sim.h>
+
+void sim_apdu(uint16_t len, uint8_t *data);
+
+static void l1ctl_sim_req(struct msgb *msg)
+{
+       uint16_t len = msg->len - sizeof(struct l1ctl_hdr);
+       uint8_t *data = msg->data + sizeof(struct l1ctl_hdr);
+
+#if 1 /* for debugging only */
+       {
+               int i;
+               printf("SIM Request (%u): ", len);
+               for (i = 0; i < len; i++)
+                       printf("%02x ", data[i]);
+               puts("\n");
+       }
+#endif
+
+   sim_apdu(len, data);
+}
+
 /* callback from SERCOMM when L2 sends a message to L1 */
 static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
 {
@@ -522,6 +544,9 @@ static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
        case L1CTL_TCH_MODE_REQ:
                l1ctl_rx_tch_mode_req(msg);
                break;
+       case L1CTL_SIM_REQ:
+               l1ctl_sim_req(msg);
+               break;
        }
 
 exit_msgbfree:
index 4c08e3e..f29ae2c 100644 (file)
@@ -274,6 +274,29 @@ static int l1s_tch_resp(__unused uint8_t p1, __unused uint8_t p2, uint16_t p3)
                traffic_buf = tch_sub ? dsp_api.ndb->a_dd_1 : dsp_api.ndb->a_dd_0;
 
                if (traffic_buf[0] & (1<<B_BLUD)) {
+
+                       if (!(dsp_api.ndb->a_dd_0[0] & (1<<B_BFI))) {
+                               int i,j;
+
+                               /* TCH/F data */
+                               struct msgb *msg = l1ctl_msgb_alloc(L1CTL_VOICE_IND);
+
+                               struct l1ctl_info_dl *dl = (struct l1ctl_info_dl *) msgb_put(msg, sizeof(*dl));
+                               struct l1ctl_voice_ind *vi = (struct l1ctl_voice_ind *) msgb_put(msg, sizeof(*vi));
+
+                               /* FIXME fill dl */
+
+                               for (j = 0,i = 3; j < 32; j+=2,i++) {
+                                       uint16_t w = dsp_api.ndb->a_dd_0[i];
+                                       vi->data[j  ] = (w >> 8) & 0xff;
+                                       vi->data[j+1] =  w & 0xff;
+                               }
+                               vi->data[32] = (dsp_api.ndb->a_dd_0[19] >> 8) & 0xff;
+
+
+                               l1_queue_for_l2(msg);
+                       }
+
                        /* Reset traffic buffer header in NDB (needed by DSP) */
                        traffic_buf[0] = 0;
                        traffic_buf[2] = 0xffff;
index 3397dc0..150205f 100644 (file)
@@ -189,6 +189,7 @@ static int last_timestamp;
 
 static inline void check_lost_frame(void)
 {
+       static int last_ts = -1;
        int diff, timestamp = hwtimer_read(1);
 
        if (last_timestamp < timestamp)
@@ -196,6 +197,22 @@ static inline void check_lost_frame(void)
 
        diff = last_timestamp - timestamp;
 
+       /* TS change compensation */
+       if (l1s.dedicated.type) {
+               if (l1s.dedicated.tn < last_ts) {
+                       int ediff = ((8 - last_ts + l1s.dedicated.tn) * TIMER_TICKS_PER_TDMA) >> 3;
+                       printf("TS Chg: %d -> %d | %d %d\n",
+                               last_ts, l1s.dedicated.tn, diff, ediff);
+
+       //              if (((ediff - 2) < diff) && ((ediff + 2) > diff)) {
+                               puts("ADV !\n");
+                               l1s.current_time = l1s.next_time;
+                               l1s_time_inc(&l1s.next_time, 1);
+       //              }
+               }
+               last_ts = l1s.dedicated.tn;
+       }
+
        /* allow for a bit of jitter */
        if (diff < TIMER_TICKS_PER_TDMA - TIMER_TICK_JITTER ||
            diff > TIMER_TICKS_PER_TDMA + TIMER_TICK_JITTER)