/*
ifd_towitoko.c
This module provides IFD handling functions.
This file is part of the Unix driver for Towitoko smartcard readers
Copyright (C) 2000 2001 Carlos Prados <cprados@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "defines.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "ifd_towitoko.h"
#include "io_serial.h"
/*
* Not exported constants
*/
#define IFD_TOWITOKO_TIMEOUT 1000
#define IFD_TOWITOKO_DELAY 0
#define IFD_TOWITOKO_BAUDRATE 9600
#define IFD_TOWITOKO_PS 15
#define IFD_TOWITOKO_MAX_TRANSMIT 255
#define IFD_TOWITOKO_ATR_TIMEOUT 200
#define IFD_TOWITOKO_ATR_MIN_LENGTH 1
#define IFD_TOWITOKO_CLOCK_RATE (372L * 9600L)
#define HI(a) (((a) & 0xff00) >> 8)
#define LO(a) ((a) & 0x00ff)
/*
* Not exported functions declaration
*/
static int IFD_Towitoko_PrepareCommand (IFD * ifd, BYTE * command, BYTE size);
static BYTE IFD_Towitoko_Checksum (BYTE * cmd, unsigned size, BYTE init);
static int IFD_Towitoko_GetReaderInfo (IFD * ifd);
static unsigned IFD_Towitoko_NumTrials (BYTE b);
static void IFD_Towitoko_Clear (IFD * ifd);
/*
* Exported functions definition
*/
IFD *
IFD_Towitoko_New ()
{
IFD *ifd;
ifd = (IFD *) malloc (sizeof (IFD));
if (ifd != NULL)
IFD_Towitoko_Clear (ifd);
return ifd;
}
void
IFD_Towitoko_Delete (IFD * ifd)
{
free (ifd);
}
int
IFD_Towitoko_Init (IFD * ifd, IO_Serial * io, BYTE slot)
{
IO_Serial_Properties props;
int ret;
#ifdef DEBUG_IFD
printf ("IFD: Initialicing slot number %d\n", slot);
#endif
if ((slot != IFD_TOWITOKO_SLOT_A) && (slot != IFD_TOWITOKO_SLOT_B))
return IFD_TOWITOKO_PARAM_ERROR;
/* Default serial port settings */
props.input_bitrate = IFD_TOWITOKO_BAUDRATE;
props.output_bitrate = IFD_TOWITOKO_BAUDRATE;
props.bits = 8;
props.parity = IO_SERIAL_PARITY_EVEN;
props.stopbits = 2;
props.dtr = IO_SERIAL_HIGH;
props.rts = IO_SERIAL_HIGH;
if (!IO_Serial_SetProperties (io, &props))
return IFD_TOWITOKO_IO_ERROR;
/* Default ifd settings */
ifd->io = io;
ifd->slot = slot;
ifd->type = IFD_TOWITOKO_UNKNOWN;
ret = IFD_Towitoko_SetBaudrate (ifd, IFD_TOWITOKO_BAUDRATE);
if (ret != IFD_TOWITOKO_OK)
{
IFD_Towitoko_Clear (ifd);
return ret;
}
ret = IFD_Towitoko_SetParity (ifd, IFD_TOWITOKO_PARITY_EVEN);
if (ret != IFD_TOWITOKO_OK)
{
IFD_Towitoko_Clear (ifd);
return ret;
}
ret = IFD_Towitoko_GetReaderInfo (ifd);
if (ret != IFD_TOWITOKO_OK)
{
IFD_Towitoko_Clear (ifd);
return ret;
}
/* Kartenzwerg settings */
if (ifd->type == IFD_TOWITOKO_KARTENZWERG)
{
props.input_bitrate = IFD_TOWITOKO_BAUDRATE;
props.output_bitrate = IFD_TOWITOKO_BAUDRATE;
props.bits = 8;
props.dtr = IO_SERIAL_HIGH;
props.rts = IO_SERIAL_HIGH;
props.parity = IO_SERIAL_PARITY_NONE;
props.stopbits = 1;
if (!IO_Serial_SetProperties (ifd->io, &props))
{
IFD_Towitoko_Clear (ifd);
return IFD_TOWITOKO_IO_ERROR;
}
}
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_Close (IFD * ifd)
{
int ret;
#ifdef DEBUG_IFD
printf ("IFD: Closing slot number %d\n", ifd->slot);
#endif
ret = IFD_Towitoko_SetLED (ifd, IFD_TOWITOKO_LED_OFF);
if (ret != IFD_TOWITOKO_OK)
return ret;
IFD_Towitoko_Clear (ifd);
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_SetBaudrate (IFD * ifd, unsigned long baudrate)
{
BYTE status[1];
BYTE buffer[6] = { 0x6E, 0x00, 0x00, 0x00, 0x08, 0x00};
IO_Serial_Properties props;
#ifdef HAVE_NANOSLEEP
struct timespec req_ts;
#endif
if (IFD_Towitoko_GetMaxBaudrate (ifd) < baudrate)
{
#ifdef DEBUG_IFD
printf ("IFD: Tried to set unsupported baudrate: %lu", baudrate);
#endif
return IFD_TOWITOKO_PARAM_ERROR;
}
#ifdef DEBUG_IFD
printf ("IFD: Setting baudrate to %lu\n", baudrate);
#endif
/* Get current settings */
if (!IO_Serial_GetProperties (ifd->io, &props))
return IFD_TOWITOKO_IO_ERROR;
if (props.output_bitrate == baudrate)
return IFD_TOWITOKO_OK;
#if 1
/* Convert baudrate to a quantum magnitude */
if (baudrate <= 1200)
{
buffer[1] = 0x60;
buffer[3] = 0x07;
}
else if (baudrate <= 2400)
{
buffer[1] = 0x2E;
buffer[3] = 0x03;
}
else if (baudrate <= 4800)
{
buffer[1] = 0x17;
buffer[3] = 0x05;
}
else if (baudrate <= 6975)
{
buffer[1] = 0x0F;
buffer[3] = 0x01;
}
else if (baudrate <= 9600)
{
buffer[1] = 0x0B;
buffer[3] = 0x02;
}
else if (baudrate <= 14400)
{
buffer[1] = 0x07;
buffer[3] = 0x01;
}
else if (baudrate <= 19200)
{
buffer[1] = 0x05;
buffer[3] = 0x02;
}
else if (baudrate <= 28800)
{
buffer[1] = 0x03;
buffer[3] = 0x00;
}
else if (baudrate <= 38400)
{
buffer[1] = 0x02;
buffer[3] = 0x00;
}
else if (baudrate <= 57600)
{
buffer[1] = 0x01;
buffer[3] = 0x00;
}
else if (baudrate <= 115200L)
{
buffer[1] = 0x80;
buffer[3] = 0x00;
}
else
return IFD_TOWITOKO_PARAM_ERROR;
buffer[2] = buffer[1] ^ 0x5D;
IFD_Towitoko_PrepareCommand (ifd, buffer, 6);
/* Set ifd baudrate requested */
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 6, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
#endif
/* Set serial device bitrate */
props.output_bitrate = baudrate;
props.input_bitrate = baudrate;
if (!IO_Serial_SetProperties (ifd->io, &props))
return IFD_TOWITOKO_IO_ERROR;
/* Delay 150 ms until CHIPDRIVE is ready */
#ifdef HAVE_NANOSLEEP
req_ts.tv_sec = 0;
req_ts.tv_nsec = 150000000L;
nanosleep (&req_ts, NULL);
#else
usleep (150000L);
#endif
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_GetBaudrate (IFD * ifd, unsigned long *baudrate)
{
IO_Serial_Properties props;
/* Get current settings */
if (!IO_Serial_GetProperties (ifd->io, &props))
return IFD_TOWITOKO_IO_ERROR;
(*baudrate) = props.output_bitrate;
return IFD_TOWITOKO_OK;
}
extern int
IFD_Towitoko_SetParity (IFD * ifd, BYTE parity)
{
BYTE buffer[5] = { 0x6F, 0x00, 0x6A, 0x0F, 0x00 };
BYTE status[1];
IO_Serial_Properties props;
if (ifd->type == IFD_TOWITOKO_KARTENZWERG)
return IFD_TOWITOKO_UNSUPPORTED;
#ifdef DEBUG_IFD
printf ("IFD: Parity = %s\n",
parity == IFD_TOWITOKO_PARITY_ODD ? "Odd" :
parity == IFD_TOWITOKO_PARITY_EVEN ? "Even" : "Invalid");
#endif
if ((parity != IFD_TOWITOKO_PARITY_EVEN) &&
(parity != IFD_TOWITOKO_PARITY_ODD))
return IFD_TOWITOKO_PARAM_ERROR;
/* Get current settings */
if (!IO_Serial_GetProperties (ifd->io, &props))
return IFD_TOWITOKO_IO_ERROR;
/* Set serial device parity to even */
if (props.parity == IO_SERIAL_PARITY_ODD)
{
props.parity = IO_SERIAL_PARITY_EVEN;
if (!IO_Serial_SetProperties (ifd->io, &props))
return IFD_TOWITOKO_IO_ERROR;
}
/* Set ifd parity as requested */
buffer[1] = parity;
IFD_Towitoko_PrepareCommand (ifd, buffer, 5);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 5, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
/*
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
*/
/* Set serial device parity */
if ((parity == IFD_TOWITOKO_PARITY_ODD) &&
(props.parity == IO_SERIAL_PARITY_EVEN))
{
props.parity = IO_SERIAL_PARITY_ODD;
if (!IO_Serial_SetProperties (ifd->io, &props))
return IFD_TOWITOKO_IO_ERROR;
}
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_SetLED (IFD * ifd, BYTE color)
{
BYTE status[1];
BYTE buffer[5] = { 0x6F, 0x00, 0x6A, 0x0F, 0x00 };
#ifdef DEBUG_IFD
printf ("IFD: LED = %s\n",
color == IFD_TOWITOKO_LED_RED ? "Red" :
color == IFD_TOWITOKO_LED_GREEN ? "Green" :
color == IFD_TOWITOKO_LED_YELLOW ? "Yellow" :
color == IFD_TOWITOKO_LED_OFF ? "Off" : "Invalid Color");
#endif
if ((color != IFD_TOWITOKO_LED_RED) &&
(color != IFD_TOWITOKO_LED_GREEN) &&
(color != IFD_TOWITOKO_LED_YELLOW) && (color != IFD_TOWITOKO_LED_OFF))
return IFD_TOWITOKO_PARAM_ERROR;
buffer[1] = color;
IFD_Towitoko_PrepareCommand (ifd, buffer, 5);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 5, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_GetStatus (IFD * ifd, BYTE * result)
{
BYTE buffer[2] = { 0x03, 0x07 };
BYTE status[2];
IFD_Towitoko_PrepareCommand (ifd, buffer, 2);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 2, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 2, status))
{
/*
* First read can exceed timeout if card has just
* been inserted or removed
*/
IFD_Towitoko_PrepareCommand (ifd, buffer, 2);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 2, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 2, status))
return IFD_TOWITOKO_IO_ERROR;
}
(*result) = status[0];
#ifdef DEBUG_IFD
printf ("IFD: Status = %s / %s\n",
IFD_TOWITOKO_CARD(status[0])? "card": "no card",
IFD_TOWITOKO_CHANGE(status[0])? "change": "no change");
#endif
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_ActivateICC (IFD * ifd)
{
BYTE status[1];
BYTE buffer[3] = { 0x60, 0x0F, 0x9C };
IFD_Towitoko_PrepareCommand (ifd, buffer, 3);
#ifdef DEBUG_IFD
printf ("IFD: Activating card\n");
#endif
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 3, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_DeactivateICC (IFD * ifd)
{
BYTE status[1];
BYTE buffer[3] = { 0x61, 0x0F, 0x98 };
IFD_Towitoko_PrepareCommand (ifd, buffer, 3);
#ifdef DEBUG_IFD
printf ("IFD: Deactivating card\n");
#endif
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 3, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_ResetAsyncICC (IFD * ifd, ATR ** atr)
{
BYTE buffer1[5] = { 0x80, 0x6F, 0x00, 0x05, 0x76 };
BYTE buffer2[5] = { 0xA0, 0x6F, 0x00, 0x05, 0x74 };
#ifndef IFD_TOWITOKO_STRICT_ATR_CHECK
BYTE atr_buffer[ATR_MAX_SIZE];
unsigned atr_length;
#endif
int i, parity, ret;
if (ifd->type == IFD_TOWITOKO_KARTENZWERG)
return IFD_TOWITOKO_UNSUPPORTED;
buffer1[4] = IFD_Towitoko_Checksum (buffer1, 4, ifd->slot);
buffer2[4] = IFD_Towitoko_Checksum (buffer2, 4, ifd->slot);
#ifdef DEBUG_IFD
printf ("IFD: Resetting card:\n");
#endif
#ifndef IFD_TOWITOKO_CONVENTION_INVERSE
parity = IFD_TOWITOKO_PARITY_EVEN;
#else
parity = IFD_TOWITOKO_PARITY_ODD;
ret = IFD_Towitoko_SetParity (ifd, parity);
if (ret != IFD_TOWITOKO_OK)
return ret;
#endif
ret = IFD_TOWITOKO_IO_ERROR;
do
{
for (i = 0; i < 2; i++)
{
/* Try active-low reset */
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 5, buffer2))
break;
(*atr) = ATR_New ();
#ifndef IFD_TOWITOKO_STRICT_ATR_CHECK
/* Read form input until it returns timeout */
for (atr_length = 0; atr_length < ATR_MAX_SIZE; atr_length++)
{
if (!IO_Serial_Read
(ifd->io, IFD_TOWITOKO_ATR_TIMEOUT, 1,
atr_buffer + atr_length))
break;
}
if (atr_length >= IFD_TOWITOKO_ATR_MIN_LENGTH)
{
/* Try to parse the ATR */
ATR_InitFromArray ((*atr), atr_buffer, atr_length + 1);
ret = IFD_TOWITOKO_OK;
break;
}
#else
if (ATR_InitFromStream ((*atr), ifd->io, IFD_TOWITOKO_ATR_TIMEOUT) == ATR_OK)
{
ret = IFD_TOWITOKO_OK;
break;
}
#endif
ATR_Delete (*atr);
(*atr) = NULL;
/* Try active-high reset */
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 5, buffer1))
break;
(*atr) = ATR_New ();
#ifndef IFD_TOWITOKO_STRICT_ATR_CHECK
/* Read form input until it returns timeout */
for (atr_length = 0; atr_length < ATR_MAX_SIZE; atr_length++)
{
if (!IO_Serial_Read
(ifd->io, IFD_TOWITOKO_ATR_TIMEOUT, 1,
atr_buffer + atr_length))
break;
}
if (atr_length >= IFD_TOWITOKO_ATR_MIN_LENGTH)
{
/* Try to parse the ATR */
ATR_InitFromArray ((*atr), atr_buffer, atr_length + 1);
ret = IFD_TOWITOKO_OK;
break;
}
#else
if (ATR_InitFromStream ((*atr), ifd->io, IFD_TOWITOKO_ATR_TIMEOUT) == ATR_OK)
{
ret = IFD_TOWITOKO_OK;
break;
}
#endif
ATR_Delete (*atr);
(*atr) = NULL;
}
/* Succesfully retrive ATR */
if (ret == IFD_TOWITOKO_OK)
{
if (parity == IFD_TOWITOKO_PARITY_ODD)
{
parity = IFD_TOWITOKO_PARITY_EVEN;
ret = IFD_Towitoko_SetParity (ifd, parity);
}
}
/* Switch parity */
else
{
#ifndef IFD_TOWITOKO_CONVENTION_DIRECT
parity = ((parity == IFD_TOWITOKO_PARITY_EVEN) ?
IFD_TOWITOKO_PARITY_ODD : IFD_TOWITOKO_PARITY_EVEN);
IFD_Towitoko_SetParity (ifd, parity);
#endif
}
}
while (parity != IFD_TOWITOKO_PARITY_EVEN);
return ret;
}
int
IFD_Towitoko_Transmit (IFD * ifd, IFD_Timings * timings, unsigned size, BYTE * buffer)
{
BYTE header[6] = {0x6F, 0x00, 0x05, 0x00, 0xFE, 0xF8};
unsigned block_delay, char_delay, sent=0, to_send = 0;
IO_Serial_Properties props;
bool s = FALSE;
if (ifd->type == IFD_TOWITOKO_KARTENZWERG)
return IFD_TOWITOKO_UNSUPPORTED;
#ifdef DEBUG_IFD
printf ("IFD: Transmit: ");
for (sent = 0; sent < size; sent++)
printf ("%X ", buffer[sent]);
printf ("\n");
#endif
/* Get current baudrate */
if (!IO_Serial_GetProperties (ifd->io, &props))
return IFD_TOWITOKO_IO_ERROR;
s = (props.output_bitrate > IFD_TOWITOKO_BAUDRATE);
/* Calculate delays */
char_delay = IFD_TOWITOKO_DELAY + timings->char_delay;
block_delay = IFD_TOWITOKO_DELAY + timings->block_delay;
for (sent = 0; sent < size; sent = sent + to_send)
{
/* Calculate number of bytes to send */
to_send = MIN(size, IFD_TOWITOKO_MAX_TRANSMIT);
/* Send header */
header[1] = (BYTE) to_send;
IFD_Towitoko_PrepareCommand (ifd, header, 4);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, (s?6:4), header))
return IFD_TOWITOKO_IO_ERROR;
/* Send data */
if ((sent == 0) && (block_delay != char_delay))
{
if (!IO_Serial_Write (ifd->io, block_delay, 1, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Write (ifd->io, char_delay, to_send-1, buffer+1))
return IFD_TOWITOKO_IO_ERROR;
}
else
{
if (!IO_Serial_Write (ifd->io, char_delay, to_send, buffer+sent))
return IFD_TOWITOKO_IO_ERROR;
}
}
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_Receive (IFD * ifd, IFD_Timings * timings, unsigned size, BYTE * buffer)
{
unsigned char_timeout, block_timeout;
#ifdef DEBUG_IFD
int i;
#endif
if (ifd->type == IFD_TOWITOKO_KARTENZWERG)
return IFD_TOWITOKO_UNSUPPORTED;
/* Calculate timeouts */
char_timeout = IFD_TOWITOKO_TIMEOUT + timings->char_timeout;
block_timeout = IFD_TOWITOKO_TIMEOUT + timings->block_timeout;
if (block_timeout != char_timeout)
{
/* Read first byte using block timeout */
if (!IO_Serial_Read (ifd->io, block_timeout, 1, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (size > 1)
{
/* Read remaining data bytes using char timeout */
if (!IO_Serial_Read (ifd->io, char_timeout, size - 1, buffer + 1))
return IFD_TOWITOKO_IO_ERROR;
}
}
else
{
/* Read all data bytes with the same timeout */
if (!IO_Serial_Read (ifd->io, char_timeout, size, buffer))
return IFD_TOWITOKO_IO_ERROR;
}
#ifdef DEBUG_IFD
printf ("IFD: Receive: ");
for (i = 0; i < size; i++)
printf ("%X ", buffer[i]);
printf ("\n");
#endif
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_Switch (IFD * ifd)
{
IO_Serial_Properties props;
BYTE buffer[1] = {0xF8};
if (!IO_Serial_GetProperties (ifd->io, &props))
return IFD_TOWITOKO_IO_ERROR;
if (props.output_bitrate > IFD_TOWITOKO_BAUDRATE)
{
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 1, buffer))
return IFD_TOWITOKO_IO_ERROR;
#ifdef DEBUG_IFD
printf ("IFD: Switching\n");
#endif
}
return IFD_TOWITOKO_OK;
}
extern int IFD_Towitoko_ResetSyncICC (IFD * ifd, ATR_Sync ** atr)
{
BYTE buffer[5] = {0x70, 0x80, 0x62, 0x0F, 0x00};
BYTE atr_buffer[8], status[1];
IFD_Towitoko_PrepareCommand (ifd, buffer, 5);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 5, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
if (IFD_Towitoko_ReadBuffer (ifd, 8, atr_buffer) != IFD_TOWITOKO_OK)
return IFD_TOWITOKO_IO_ERROR;
if (atr_buffer[0] != 0xFF)
{
(*atr) = ATR_Sync_New ();
if ((*atr) != NULL)
ATR_Sync_Init ((*atr), atr_buffer, ATR_SYNC_SIZE);
}
else
(*atr) = NULL;
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_SetReadAddress (IFD * ifd, int icc_type, unsigned short address)
{
BYTE status[1];
BYTE i2cShort[10] = { 0x7C, 0x64, 0x41, 0x00, 0x00, 0x64, 0x40, 0x00, 0x0F, 0x00 };
BYTE i2cLong[11] = { 0x7C, 0x64, 0x42, 0xA0, 0x00, 0x00, 0x64, 0x40, 0xA1, 0x0F, 0x00 };
BYTE w2[9] = { 0x70, 0x64, 0x42, 0x30, 0x00, 0x00, 0x65, 0x0F, 0x00 };
BYTE w3[10] = { 0x70, 0xA0, 0x42, 0x00, 0x00, 0x00, 0x80, 0x50, 0x0F, 0x00 };
if (icc_type == IFD_TOWITOKO_I2C_SHORT)
{
#ifdef DEBUG_IFD
printf ("IFD: I2C short set read address: %d\n", address);
#endif
i2cShort[3] = (HI (address) << 1) | 0xA0;
i2cShort[4] = LO (address);
i2cShort[7] = (HI (address) << 1) | 0xA0 | 0x01;
IFD_Towitoko_PrepareCommand (ifd, i2cShort, 10);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 10, i2cShort))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else if (icc_type == IFD_TOWITOKO_I2C_LONG)
{
#ifdef DEBUG_IFD
printf ("IFD: I2C long set read address: %d\n", address);
#endif
i2cLong[4] = HI (address);
i2cLong[5] = LO (address);
IFD_Towitoko_PrepareCommand (ifd, i2cLong, 11);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 11, i2cLong))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else if (icc_type == IFD_TOWITOKO_2W)
{
#ifdef DEBUG_IFD
printf ("IFD: 2W set read address: %d\n", address);
#endif
w2[4] = LO (address);
IFD_Towitoko_PrepareCommand (ifd, w2, 9);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 9, w2))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else if (icc_type == IFD_TOWITOKO_3W)
{
#ifdef DEBUG_IFD
printf ("IFD: 3W set read address: %d\n", address);
#endif
w3[3] = (HI (address) << 6) | 0x0E;
w3[4] = LO (address);
IFD_Towitoko_PrepareCommand (ifd, w3, 10);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 10, w3))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else
return IFD_TOWITOKO_PARAM_ERROR;
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_SetWriteAddress (IFD * ifd, int icc_type, unsigned short address, BYTE pagemode)
{
BYTE i2cShort1[10] = { 0x7C, 0x64, 0x41, 0xA0, 0x00, 0x64, 0x40, 0xA1, 0x0F, 0x36 };
BYTE i2cShort2[3] = { 0x7E, 0x10, 0xDA };
BYTE i2cShort3[8] = { 0x7E, 0x66, 0x6E, 0x00, 0x00, 0x10, 0x0F, 0x00 };
BYTE i2cLong1[11] = { 0x7C, 0x64, 0x42, 0xA0, 0x00, 0x00, 0x64, 0x40, 0xA1, 0x0F, 0x0B };
BYTE i2cLong2[3] = { 0x7E, 0x10, 0xDA };
BYTE i2cLong3[8] = { 0x7F, 0x66, 0x6E, 0x00, 0x00, 0xA0, 0x0F, 0x00 };
BYTE w2[7] = { 0x72, 0x6E, 0x00, 0x38, 0x03, 0x0F, 0x00 };
BYTE w3[8] = { 0x73, 0x67, 0x6E, 0x00, 0x00, 0x02, 0x0F, 0x5F };
BYTE status[2];
if (icc_type == IFD_TOWITOKO_I2C_SHORT)
{
#ifdef DEBUG_IFD
printf ("IFD: I2C short set write address: %d\n", address);
#endif
IFD_Towitoko_PrepareCommand (ifd, i2cShort1, 10);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 10, i2cShort1))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
IFD_Towitoko_PrepareCommand (ifd, i2cShort2, 3);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 3, i2cShort2))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 2, status))
return IFD_TOWITOKO_IO_ERROR;
i2cShort3[3] = LO (address);
i2cShort3[4] = (HI (address) << 1) | 0xA0;
i2cShort3[5] = pagemode;
IFD_Towitoko_PrepareCommand (ifd, i2cShort3, 8);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 8, i2cShort3))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else if (icc_type == IFD_TOWITOKO_I2C_LONG)
{
#ifdef DEBUG_IFD
printf ("IFD: I2C long set write address: %d\n", address);
#endif
IFD_Towitoko_PrepareCommand (ifd, i2cLong1, 11);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 11, i2cLong1))
return IFD_TOWITOKO_CHK_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
IFD_Towitoko_PrepareCommand (ifd, i2cLong2, 3);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 3, i2cLong2))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 2, status))
return IFD_TOWITOKO_IO_ERROR;
i2cLong3[3] = LO (address);
i2cLong3[4] = HI (address);
IFD_Towitoko_PrepareCommand (ifd, i2cLong3, 8);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 8, i2cLong3))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else if (icc_type == IFD_TOWITOKO_2W)
{
#ifdef DEBUG_IFD
printf ("IFD: 2W set write address: %d\n", address);
#endif
w2[2] = LO (address);
IFD_Towitoko_PrepareCommand (ifd, w2, 7);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 7, w2))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else if (icc_type == IFD_TOWITOKO_3W)
{
#ifdef DEBUG_IFD
printf ("IFD: 3W set write address: %d\n", address);
#endif
w3[3] = LO (address);
w3[4] = (HI (address) << 6) | 0x33;
IFD_Towitoko_PrepareCommand (ifd, w3, 8);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 8, w3))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else
return IFD_TOWITOKO_PARAM_ERROR;
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_ReadBuffer (IFD * ifd, unsigned length, BYTE * data)
{
BYTE buffer[2], status[1];
unsigned blocks_length, pointer;
buffer[0] = ((BYTE) (IFD_TOWITOKO_PS - 1)) | 0x10;
blocks_length = (length / IFD_TOWITOKO_PS) * IFD_TOWITOKO_PS;
for (pointer = 0; pointer < blocks_length; pointer += IFD_TOWITOKO_PS)
{
IFD_Towitoko_PrepareCommand (ifd, buffer, 2);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 2, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT,
IFD_TOWITOKO_PS, data + pointer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
}
if ((length % IFD_TOWITOKO_PS) != 0)
{
buffer[0] = ((BYTE) ((length % IFD_TOWITOKO_PS) - 1)) | 0x10;
IFD_Towitoko_PrepareCommand (ifd, buffer, 2);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 2, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT,
length % IFD_TOWITOKO_PS, data + pointer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
}
#ifdef DEBUG_IFD
printf ("IFD: Read Memory: ");
for (pointer = 0; pointer < length; pointer++)
printf ("%X ", data[pointer]);
printf ("\n");
#endif
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_WriteBuffer (IFD * ifd, unsigned length, BYTE * data)
{
BYTE buffer[IFD_TOWITOKO_PS + 2], status[1];
unsigned blocks_length, remaining_length, pointer;
buffer[0] = 0x4E;
blocks_length = (length / IFD_TOWITOKO_PS) * IFD_TOWITOKO_PS;
for (pointer = 0; pointer < blocks_length; pointer += IFD_TOWITOKO_PS)
{
memcpy (buffer + 1, data + pointer, IFD_TOWITOKO_PS);
IFD_Towitoko_PrepareCommand (ifd, buffer, IFD_TOWITOKO_PS + 2);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, IFD_TOWITOKO_PS + 2, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
remaining_length = length % IFD_TOWITOKO_PS;
if (remaining_length != 0)
{
buffer[0] = ((BYTE) ((remaining_length) - 1)) | 0x40;
memcpy (buffer + 1, data + pointer, remaining_length);
buffer[remaining_length + 1] = 0x0F;
IFD_Towitoko_PrepareCommand (ifd, buffer, remaining_length + 3);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, remaining_length + 3, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
#ifdef DEBUG_IFD
printf ("IFD: Write Memory: ");
for (pointer = 0; pointer < length; pointer++)
printf ("%X ", data[pointer]);
printf ("\n");
#endif
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_ReadErrorCounter (IFD * ifd, int icc_type, unsigned *trials)
{
BYTE w21[9] = { 0x70, 0x64, 0x42, 0x31, 0x00, 0x00, 0x65, 0x0F, 0x80 };
BYTE w22[2] = { 0x13, 0x27 };
BYTE w31[10] = { 0x70, 0xA0, 0x42, 0xCE, 0xFD, 0xFD, 0x80, 0x50, 0x0F, 0x17 };
BYTE w32[2] = { 0x10, 0x21 };
BYTE status[5];
if (icc_type == IFD_TOWITOKO_2W)
{
IFD_Towitoko_PrepareCommand (ifd, w21, 9);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 9, w21))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
IFD_Towitoko_PrepareCommand (ifd, w22, 2);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 2, w22))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 5, status))
return IFD_TOWITOKO_IO_ERROR;
(*trials) = IFD_Towitoko_NumTrials (status[0]);
#ifdef DEBUG_IFD
printf ("IFD: Read Error Counter 2W: %d\n", *trials);
#endif
}
else if (icc_type == IFD_TOWITOKO_3W)
{
IFD_Towitoko_PrepareCommand (ifd, w31, 10);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 10, w31))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
IFD_Towitoko_PrepareCommand (ifd, w32, 2);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 2, w32))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 2, status))
return IFD_TOWITOKO_IO_ERROR;
(*trials) = IFD_Towitoko_NumTrials (status[0]);
#ifdef DEBUG_IFD
printf ("IFD: Read Error Counter 3W: %d\n", *trials);
#endif
}
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_EnterPin (IFD * ifd, int icc_type, BYTE * pin, unsigned trial)
{
BYTE w21[7] = { 0x72, 0x6E, 0x00, 0x39, 0x03, 0x0F, 0xB5 };
BYTE w22[4] = { 0x40, 0x00, 0x0F, 0x00 };
BYTE w23[6] = { 0x42, 0x00, 0x00, 0x00, 0x0F, 0x00 };
BYTE w31[8] = { 0x73, 0x67, 0x6E, 0xFD, 0xF2, 0x02, 0x0F, 0x8C };
BYTE w32[4] = { 0x40, 0x00, 0x0F, 0x00 };
BYTE status[1];
if (icc_type == IFD_TOWITOKO_2W)
{
#ifdef DEBUG_IFD
printf ("IFD: 2W enter pin: %X %X %X\n", pin[0], pin[1], pin[2]);
#endif
IFD_Towitoko_PrepareCommand (ifd, w21, 7);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 7, w21))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w22[1] = (trial == 3) ? 0x06 : (trial == 2) ? 0x04 : 0x00;
IFD_Towitoko_PrepareCommand (ifd, w22, 4);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 4, w22))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w21[2] = 0x01;
w21[3] = 0x33;
IFD_Towitoko_PrepareCommand (ifd, w21, 7);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 7, w21))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
memcpy (w23 + 1, pin, IFD_TOWITOKO_PIN_SIZE);
IFD_Towitoko_PrepareCommand (ifd, w23, 6);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 6, w23))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
w21[2] = 0x00;
w21[3] = 0x39;
IFD_Towitoko_PrepareCommand (ifd, w21, 7);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 7, w21))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w22[1] = 0xFF;
IFD_Towitoko_PrepareCommand (ifd, w22, 4);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 4, w22))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else if (icc_type == IFD_TOWITOKO_3W)
{
#ifdef DEBUG_IFD
printf ("IFD: 3W enter pin: %X %X\n", pin[0], pin[1]);
#endif
IFD_Towitoko_PrepareCommand (ifd, w31, 8);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 8, w31))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w32[1] = (trial == 8) ? 0xFE :
(trial == 7) ? 0xFC :
(trial == 6) ? 0xF8 :
(trial == 5) ? 0xF0 :
(trial == 4) ? 0xE0 :
(trial == 3) ? 0xC0 : (trial == 2) ? 0x80 : 0x00;
IFD_Towitoko_PrepareCommand (ifd, w32, 4);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 4, w32))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w31[3] = 0xFE;
w31[4] = 0xCD;
IFD_Towitoko_PrepareCommand (ifd, w31, 8);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 8, w31))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w32[1] = pin[0];
IFD_Towitoko_PrepareCommand (ifd, w32, 4);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 4, w32))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w31[3] = 0xFF;
IFD_Towitoko_PrepareCommand (ifd, w31, 8);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 8, w31))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w32[1] = pin[1];
IFD_Towitoko_PrepareCommand (ifd, w32, 4);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 4, w32))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w31[3] = 0xFD;
w31[4] = 0xF3;
IFD_Towitoko_PrepareCommand (ifd, w31, 8);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 8, w31))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w32[1] = 0xFF;
IFD_Towitoko_PrepareCommand (ifd, w32, 4);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 4, w32))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else
return IFD_TOWITOKO_PARAM_ERROR;
return IFD_TOWITOKO_OK;
}
int
IFD_Towitoko_ChangePin (IFD * ifd, int icc_type, BYTE * pin)
{
BYTE w21[7] = { 0x72, 0x6E, 0x01, 0x39, 0x03, 0x0F, 0xA5 };
BYTE w22[6] = { 0x42, 0x00, 0x00, 0x00, 0x0F, 0x00 };
BYTE w31[8] = { 0x73, 0x67, 0x6E, 0xFE, 0xF3, 0x02, 0x0F, 0xB4 };
BYTE w32[4] = { 0x40, 0x00, 0x0F, 0x00 };
BYTE status[1];
if (icc_type == IFD_TOWITOKO_2W)
{
#ifdef DEBUG_IFD
printf ("IFD: 2W change pin: %X %X %X\n", pin[0], pin[1], pin[2]);
#endif
IFD_Towitoko_PrepareCommand (ifd, w21, 7);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 7, w21))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w22[1] = pin[0];
w22[2] = pin[1];
w22[3] = pin[2];
IFD_Towitoko_PrepareCommand (ifd, w22, 6);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 6, w22))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else if (icc_type == IFD_TOWITOKO_3W)
{
#ifdef DEBUG_IFD
printf ("IFD: 3W change pin: %X %X\n", pin[0], pin[1]);
#endif
IFD_Towitoko_PrepareCommand (ifd, w31, 8);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 8, w31))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w32[1] = pin[0];
IFD_Towitoko_PrepareCommand (ifd, w32, 4);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 4, w32))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w31[3] = 0xFF;
IFD_Towitoko_PrepareCommand (ifd, w31, 8);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 8, w31))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
w32[1] = pin[1];
IFD_Towitoko_PrepareCommand (ifd, w32, 4);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 4, w32))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 1, status))
return IFD_TOWITOKO_IO_ERROR;
if (status[0] != 0x01)
return IFD_TOWITOKO_CHK_ERROR;
}
else
return IFD_TOWITOKO_PARAM_ERROR;
return IFD_TOWITOKO_OK;
}
BYTE
IFD_Towitoko_GetType (IFD * ifd)
{
return ifd->type;
}
void
IFD_Towitoko_GetDescription (IFD * ifd, BYTE * desc, unsigned length)
{
char buffer[3];
if (ifd->type == IFD_TOWITOKO_CHIPDRIVE_EXT_II)
memcpy (desc,"CE2",MIN(length,3));
else if (ifd->type == IFD_TOWITOKO_CHIPDRIVE_EXT_I)
memcpy (desc,"CE1",MIN(length,3));
else if (ifd->type == IFD_TOWITOKO_CHIPDRIVE_INT)
memcpy (desc,"CDI",MIN(length,3));
else if (ifd->type == IFD_TOWITOKO_CHIPDRIVE_MICRO)
memcpy (desc,"CDM",MIN(length,3));
else if (ifd->type == IFD_TOWITOKO_KARTENZWERG_II)
memcpy (desc,"KZ2",MIN(length,3));
else if (ifd->type == IFD_TOWITOKO_KARTENZWERG)
memcpy (desc,"KZ1",MIN(length,3));
else
memcpy (desc,"UNK",MIN(length,3));
snprintf (buffer, 3, "%02X", ifd->firmware);
if (length > 3)
memcpy (desc+3, buffer, MIN(length-3,2));
}
BYTE
IFD_Towitoko_GetFirmware (IFD * ifd)
{
return ifd->firmware;
}
BYTE
IFD_Towitoko_GetSlot (IFD * ifd)
{
return ifd->slot;
}
unsigned
IFD_Towitoko_GetNumSlots (IFD * ifd)
{
if (ifd->type == IFD_TOWITOKO_CHIPDRIVE_EXT_II)
return 2;
return 1;
}
unsigned long
IFD_Towitoko_GetClockRate (IFD * ifd)
{
return IFD_TOWITOKO_CLOCK_RATE;
}
unsigned long
IFD_Towitoko_GetMaxBaudrate (IFD * ifd)
{
return 115200L;
}
/*
* Not exported funcions definition
*/
static int
IFD_Towitoko_PrepareCommand (IFD * ifd, BYTE * command, BYTE size)
{
IO_Serial_Properties props;
BYTE buffer[1], initial;
if (!IO_Serial_GetProperties (ifd->io, &props))
return IFD_TOWITOKO_IO_ERROR;
if (props.output_bitrate >= 115200L)
{
buffer[0] = size - 1;
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 1, buffer))
return IFD_TOWITOKO_IO_ERROR;
initial = IFD_Towitoko_Checksum(buffer, 1, ifd->slot);
}
else
initial = ifd->slot;
command[size-1] = IFD_Towitoko_Checksum(command, size-1, initial);
return IFD_TOWITOKO_OK;
}
static BYTE
IFD_Towitoko_Checksum (BYTE * command, unsigned size, BYTE initial)
{
BYTE checksum, x7;
unsigned i;
checksum = initial;
for (i = 0; i < size; i++)
{
checksum = checksum ^ command[i];
x7 = (checksum & 0x80) >> 7;
checksum = checksum << 1;
checksum = !x7 == 0x01 ? checksum | 0x01 : checksum & 0xFE;
}
return checksum;
}
static int
IFD_Towitoko_GetReaderInfo (IFD * ifd)
{
BYTE status[3];
BYTE buffer[2] = { 0x00, 0x01};
buffer[1] = IFD_Towitoko_Checksum (buffer, 1, ifd->slot);
if (!IO_Serial_Write (ifd->io, IFD_TOWITOKO_DELAY, 2, buffer))
return IFD_TOWITOKO_IO_ERROR;
if (!IO_Serial_Read (ifd->io, IFD_TOWITOKO_TIMEOUT, 3, status))
return IFD_TOWITOKO_IO_ERROR;
ifd->type = status[0];
ifd->firmware = status[1];
#ifdef DEBUG_IFD
printf ("IFD: Reader type = %s\n",
status[0] == IFD_TOWITOKO_CHIPDRIVE_EXT_II ? "Chipdrive Extern II" :
status[0] == IFD_TOWITOKO_CHIPDRIVE_EXT_I ? "Chipdrive Extern I" :
status[0] == IFD_TOWITOKO_CHIPDRIVE_INT ? "Chipdrive Intern" :
status[0] == IFD_TOWITOKO_CHIPDRIVE_MICRO ? "Chipdrive Micro" :
status[0] == IFD_TOWITOKO_KARTENZWERG_II ? "Kartenzwerg II" :
status[0] == IFD_TOWITOKO_KARTENZWERG ? "Kartenzwerg" : "Unknown");
#endif
return IFD_TOWITOKO_OK;
}
static unsigned
IFD_Towitoko_NumTrials (BYTE b)
{
unsigned i, count = 0;
for (i = 0; i < 8; i++)
{
count += ((b & 0x01) == 0x01) ? 1 : 0;
b >>= 1;
}
return count;
}
static void
IFD_Towitoko_Clear (IFD * ifd)
{
ifd->io = NULL;
ifd->slot = 0x00;
ifd->type = 0x00;
ifd->firmware = 0x00;
}
syntax highlighted by Code2HTML, v. 0.9.1