/* * Turbo Programmer Utilities, turbo-prog-utils, www.bladox.com * * Copyright (C) 2004 BLADOX, s.r.o. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ #include <config.h> #include <tprog/tprog.h> #include <stdlib.h> #include <avr/interrupt.h> #include "sim.h" #include "uart.h" #include "clka.h" #define ME_CMD_SELECT 0xa4 #define ME_CMD_STATUS 0xf2 #define ME_CMD_READ_BINARY 0xb0 #define ME_CMD_UPDATE_BINARY 0xd6 #define ME_CMD_READ_RECORD 0xb2 #define ME_CMD_UPDATE_RECORD 0xdc #define ME_CMD_SEEK 0xa2 #define ME_CMD_INCREASE 0x32 #define ME_CMD_VERIFY_CHV 0x20 #define ME_CMD_CHANGE_CHV 0x24 #define ME_CMD_DISABLE_CHV 0x26 #define ME_CMD_ENABLE_CHV 0x28 #define ME_CMD_UNBLOCK_CHV 0x2c #define ME_CMD_INVALIDATE 0x04 #define ME_CMD_REHABILITATE 0x44 #define ME_CMD_RUN_GSM_ALGORITHM 0x88 #define ME_CMD_GET_RESPONSE 0xc0 #define ME_CMD_TERMINAL_PROFILE 0x10 #define ME_CMD_ENVELOPE 0xc2 #define ME_CMD_FETCH 0x12 #define ME_CMD_TERMINAL_RESPONSE 0x14 #define ME_CMD_SLEEP 0xfa #define NX_ATR_NONE 0 #define NX_ATR_TA 10 #define NX_ATR_TB 11 #define NX_ATR_TC 12 #define NX_ATR_TD 13 #define NX_ATR_TK 14 #define NX_ATR_TS 15 #define NX_ATR_T0 16 #define NX_ATR_TCK 17 #define ATR_MAX 16 //#define ATR_MAX 33 // defines structure of ATR response from card struct ATR { u8 buf[ATR_MAX + 1]; u8 pts; u8 card_TA1; u8 card_TC1; u8 card_TC2; }; //inverse convention (ATR starts with 0x3F (0x03 direct convention)) //to handle inverse convention we have to: //1)invert chars before transmitting and after receiving //2)swap bits in each chars - b1=b8, b2=b7, b3=b6, .., b8=b1 //3)use opposite parity extern u8 inverseConvention; b8 handleAtr (struct ATR *a) { u8 nx_atr = 0; u8 tk = 0, ta = 0, tb = 0, tc = 0, td = 0, t_proto = 0; u8 TK[16]; u8 nr_tk = 0; u8 i_round = 1; u8 i_si = 0; u16 i = 0; b8 res = 0; u8 looping; u8 wasFirstAtrChar = 0; u8 expectTCK; u8 otherProtocolThanT0; a->card_TA1 = 0; a->card_TC1 = 0; a->card_TC2 = 0; a->pts = 0; a->buf[0] = 0; nx_atr = NX_ATR_TS; expectTCK = 0; otherProtocolThanT0 = 0; looping = 1; inverseConvention = 0; while (looping == 1) { if ((uart_chars ()) != 0) { i_si = uart_get_char (); //check for inverse convention if ((i_si == 0x03) && (inverseConvention == 0) && (wasFirstAtrChar == 0)) { i_si = 0x3F; inverseConvention = 1; uart_change_parity (); } wasFirstAtrChar = 1; if (a->buf[0] < ATR_MAX) { a->buf[i + 1] = i_si; a->buf[0]++; } i++; switch (nx_atr) { case NX_ATR_TS: nx_atr = NX_ATR_T0; break; case NX_ATR_T0: ta = (i_si & 16) ? 1 : 0; tb = (i_si & 32) ? 1 : 0; tc = (i_si & 64) ? 1 : 0; td = (i_si & 128) ? 1 : 0; tk = (i_si & 15); nx_atr = 0; i_round = 1; if (ta && !nx_atr) nx_atr = NX_ATR_TA; if (tb && !nx_atr) nx_atr = NX_ATR_TB; if (tc && !nx_atr) nx_atr = NX_ATR_TC; if (td && !nx_atr) nx_atr = NX_ATR_TD; if (tk && !nx_atr) nx_atr = NX_ATR_TK; if (!nx_atr) nx_atr = NX_ATR_TCK; break; case NX_ATR_TA: if (i_round == 1) { a->card_TA1 = i_si; a->pts = i_si; } nx_atr = 0; if (tb && !nx_atr) nx_atr = NX_ATR_TB; if (tc && !nx_atr) nx_atr = NX_ATR_TC; if (td && !nx_atr) nx_atr = NX_ATR_TD; if (tk && !nx_atr) nx_atr = NX_ATR_TK; if (!nx_atr) nx_atr = NX_ATR_TCK; break; case NX_ATR_TB: nx_atr = 0; if (tc && !nx_atr) nx_atr = NX_ATR_TC; if (td && !nx_atr) nx_atr = NX_ATR_TD; if (tk && !nx_atr) nx_atr = NX_ATR_TK; if (!nx_atr) nx_atr = NX_ATR_TCK; break; case NX_ATR_TC: if (i_round == 1) a->card_TC1 = i_si; if (i_round == 2) a->card_TC2 = i_si; nx_atr = 0; if (td && !nx_atr) nx_atr = NX_ATR_TD; if (tk && !nx_atr) nx_atr = NX_ATR_TK; if (!nx_atr) nx_atr = NX_ATR_TCK; break; case NX_ATR_TD: ta = (i_si & 16) ? 1 : 0; tb = (i_si & 32) ? 1 : 0; tc = (i_si & 64) ? 1 : 0; td = (i_si & 128) ? 1 : 0; t_proto = (i_si & 15); if ((t_proto != 0) && (otherProtocolThanT0 == 0)) { otherProtocolThanT0 = 1; expectTCK = 1; } i_round++; nx_atr = 0; if (ta && !nx_atr) nx_atr = NX_ATR_TA; if (tb && !nx_atr) nx_atr = NX_ATR_TB; if (tc && !nx_atr) nx_atr = NX_ATR_TC; if (td && !nx_atr) nx_atr = NX_ATR_TD; if (tk && !nx_atr) nx_atr = NX_ATR_TK; if (!nx_atr) nx_atr = NX_ATR_TCK; break; case NX_ATR_TK: TK[nr_tk] = i_si; nr_tk++; if (tk != nr_tk) { nx_atr = NX_ATR_TK; } else { nx_atr = NX_ATR_TCK; if (expectTCK == 0) looping = 0; } break; case NX_ATR_TCK: nx_atr = 0; looping = 0; break; default: res = -1; } } } return res; } #define TO_SIM 0 #define FROM_SIM 1 u8 uart_get_char_blocking () { while (uart_chars () == 0); return uart_get_char (); } u16 sim (u8 ins, u8 p1, u8 p2, u8 p3, u8 * buf) { u16 len = p3; u16 i; u8 dir = TO_SIM; u8 x; u8 invins = ~ins; uart_send_char (0xA0); uart_send_char (ins); uart_send_char (p1); uart_send_char (p2); uart_send_char (p3); switch (ins) { /* //TO_SIM case ME_CMD_SELECT: case ME_CMD_UPDATE_BINARY: case ME_CMD_UPDATE_RECORD: case ME_CMD_SEEK: case ME_CMD_INCREASE: case ME_CMD_VERIFY_CHV: case ME_CMD_CHANGE_CHV: case ME_CMD_DISABLE_CHV: case ME_CMD_ENABLE_CHV: case ME_CMD_UNBLOCK_CHV: case ME_CMD_RUN_GSM_ALGORITHM: case ME_CMD_TERMINAL_PROFILE: case ME_CMD_ENVELOPE: case ME_CMD_TERMINAL_RESPONSE: break; */ //FROM_SIM case ME_CMD_STATUS: case ME_CMD_READ_BINARY: case ME_CMD_READ_RECORD: case ME_CMD_GET_RESPONSE: case ME_CMD_FETCH: dir = FROM_SIM; break; default: break; /* case ME_CMD_INVALIDATE: case ME_CMD_REHABILITATE: case ME_CMD_SLEEP: */ } if (len == 0 && !(ins == ME_CMD_INVALIDATE || ins == ME_CMD_REHABILITATE)) len = 0x100; i = 0; X1: x = uart_get_char_blocking (); if (x == 0x60) goto X1; if (x == invins) { if (dir == TO_SIM) uart_send_char (buf[i]); else buf[i] = uart_get_char_blocking (); i++; if (i < len) goto X1; else goto X2; } if (x == ins) goto X4; if ((x & 0xF0) == 0x90 || (x & 0xF0) == 0x60) goto X3; //6x xx or 9x xx X4: for (; i < len; i++) if (dir == TO_SIM) uart_send_char (buf[i]); else buf[i] = uart_get_char_blocking (); X2: if (dir == TO_SIM) i = 0; X5: x = uart_get_char_blocking (); //SW1 if (x == 0x60) goto X5; X3: buf[i] = x; i++; buf[i] = uart_get_char_blocking (); //SW2 i++; return i; } void atr () { struct ATR atrStruct; //set RST=0 cbi (SIM_RST_PORT, SIM_RST_PORT_PIN); sbi (SIM_RST_DDR, SIM_RST_DDR_DD); //delay 10ms delayMs (10); //SIM_IO_ENABLE //set pin to log.0 //(SIM_IO is disconnected) ext_cbi (EXT_SIM_IO_ENABLE_PORT, EXT_SIM_IO_ENABLE_PORT_PIN); //delay 10ms delayMs (10); //SIM_CLK_ENABLE /set pin to log.0 (active high) //(in is disconnected at first) cbi (SIM_CLK_ENABLE_PORT, SIM_CLK_ENABLE_PORT_PIN); //SIM_CLKA_ENABLE /set pin to log.0 (active high) //(in is disconnected at first) cbi (SIM_CLKA_ENABLE_PORT, SIM_CLKA_ENABLE_PORT_PIN); //delay 20ms delayMs (20); //SIM_VCC_ENABLE set pin to log.1 (active low) //SIM is disconnected at first sbi (SIM_VCC_ENABLE_PORT, SIM_VCC_ENABLE_PORT_PIN); //delay 50ms delayMs (50); //flush rx fifo while (uart_chars () != 0) uart_get_char (); //SIM_VCC_ENABLE set pin to log.0 (active low) cbi (SIM_VCC_ENABLE_PORT, SIM_VCC_ENABLE_PORT_PIN); //SIM_IO_ENABLE //set pin to log.1 //(SIM_IO is connected) ext_sbi (EXT_SIM_IO_ENABLE_PORT, EXT_SIM_IO_ENABLE_PORT_PIN); //set SIM_TX to input sbi (SIM_TXD_PORT, SIM_TXD_PORT_PIN); cbi (SIM_TXD_DDR, SIM_TXD_DDR_DD); //delay 1ms delayMs (1); //SIM_CLKA_ENABLE /set pin to log.1 (active high) //(connect clk to SIM now) sbi (SIM_CLKA_ENABLE_PORT, SIM_CLKA_ENABLE_PORT_PIN); //delay 1ms delayMs (1); //delay 30ms delayMs (30); //set RST=1 sbi (SIM_RST_PORT, SIM_RST_PORT_PIN); handleAtr (&atrStruct); usb_send (NO_ERROR, atrStruct.buf[0], &atrStruct.buf[1]); } void turbo_handler (u8 action, USB_Data * data) { u8 *buf = buf_A (); switch (action) { case ACTION_APP_VERSION: buf[0] = 2; buf[1] = 0; buf[2] = 0; usb_send (NO_ERROR, 3, buf); break; case ACTION_SIM_INIT: reg_action (ACTION_SIG_UART1_RECV); init_vars (); init_sim_port (); init_uart (); init_clka_timer (); usb_send (NO_ERROR, 0, NULL); break; case ACTION_SIM_CMD: { u8 ins, p1, p2, p3; u16 ret; u16 len; ins = data->buf[0]; p1 = data->buf[1]; p2 = data->buf[2]; p3 = data->buf[3]; ret = sim (ins, p1, p2, p3, &data->buf[4]); usb_send (NO_ERROR, ret, &data->buf[4]); } break; case ACTION_SIM_ATR: atr (); break; case ACTION_SIG_UART1_RECV: uart_irq (); break; default: break; } }
Copyright © 2004 BLADOX | Turbo Programmer version 2.0
|