/*
icc_async.c
Asynchronous ICC's 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 "icc_async.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*
* Not exported constants definition
*/
#define ICC_ASYNC_MAX_TRANSMIT 255
#define ICC_ASYNC_BAUDRATE 9600
/*
* Not exported functions declaration
*/
static void ICC_Async_InvertBuffer (unsigned size, BYTE * buffer);
static void ICC_Async_Clear (ICC_Async * icc);
/*
* Exported functions definition
*/
ICC_Async *
ICC_Async_New (void)
{
ICC_Async *icc;
/* Allocate memory */
icc = (ICC_Async *) malloc (sizeof (ICC_Async));
if (icc != NULL)
ICC_Async_Clear (icc);
return icc;
}
int
ICC_Async_Init (ICC_Async * icc, IFD * ifd)
{
#ifndef ICC_TYPE_SYNC
/* LED Red */
if (IFD_Towitoko_SetLED (ifd, IFD_TOWITOKO_LED_RED) != IFD_TOWITOKO_OK)
return ICC_ASYNC_IFD_ERROR;
/* Initialize Baudrate */
if (IFD_Towitoko_SetBaudrate (ifd, ICC_ASYNC_BAUDRATE)!= IFD_TOWITOKO_OK)
return ICC_ASYNC_IFD_ERROR;
/* Activate ICC */
if (IFD_Towitoko_ActivateICC (ifd) != IFD_TOWITOKO_OK)
return ICC_ASYNC_IFD_ERROR;
/* Reset ICC */
if (IFD_Towitoko_ResetAsyncICC (ifd, &(icc->atr)) != IFD_TOWITOKO_OK)
{
icc->atr = NULL;
return ICC_ASYNC_IFD_ERROR;
}
/* Get ICC convention */
if (ATR_GetConvention (icc->atr, &(icc->convention)) != ATR_OK)
{
ATR_Delete (icc->atr);
icc->atr = NULL;
icc->convention = 0;
return ICC_ASYNC_ATR_ERROR;
}
#ifdef DEBUG_ICC
printf("ICC: Detected %s convention processor card\n",
(icc->convention == ATR_CONVENTION_DIRECT ? "direct" : "inverse"));
#endif
/* LED Green */
if (IFD_Towitoko_SetLED (ifd, IFD_TOWITOKO_LED_GREEN) != IFD_TOWITOKO_OK)
{
ATR_Delete (icc->atr);
icc->atr = NULL;
icc->convention = 0;
return ICC_ASYNC_IFD_ERROR;
}
/* Initialize member variables */
icc->baudrate = ICC_ASYNC_BAUDRATE;
icc->ifd = ifd;
return ICC_ASYNC_OK;
#else
return ICC_ASYNC_ATR_ERROR;
#endif
}
int
ICC_Async_SetTimings (ICC_Async * icc, ICC_Async_Timings * timings)
{
icc->timings.block_delay = timings->block_delay;
icc->timings.char_delay = timings->char_delay;
icc->timings.block_timeout = timings->block_timeout;
icc->timings.char_timeout = timings->char_timeout;
return ICC_ASYNC_OK;
}
int
ICC_Async_GetTimings (ICC_Async * icc, ICC_Async_Timings * timings)
{
timings->block_delay = icc->timings.block_delay;
timings->char_delay = icc->timings.char_delay;
timings->block_timeout = icc->timings.block_timeout;
timings->char_timeout = icc->timings.char_timeout;
return ICC_ASYNC_OK;
}
int
ICC_Async_SetBaudrate (ICC_Async * icc, unsigned long baudrate)
{
icc->baudrate = baudrate;
return ICC_ASYNC_OK;
}
int
ICC_Async_GetBaudrate (ICC_Async * icc, unsigned long * baudrate)
{
(*baudrate) = icc->baudrate;
return ICC_ASYNC_OK;
}
int
ICC_Async_BeginTransmission (ICC_Async * icc)
{
/* Setup parity for this ICC */
if (icc->convention == ATR_CONVENTION_INVERSE)
{
if (IFD_Towitoko_SetParity (icc->ifd, IFD_TOWITOKO_PARITY_ODD) != IFD_TOWITOKO_OK)
return ICC_ASYNC_IFD_ERROR;
}
/* Setup baudrate for this ICC */
if (IFD_Towitoko_SetBaudrate (icc->ifd, icc->baudrate)!= IFD_TOWITOKO_OK)
return ICC_ASYNC_IFD_ERROR;
return ICC_ASYNC_OK;
}
int
ICC_Async_Transmit (ICC_Async * icc, unsigned size, BYTE * data)
{
BYTE *buffer = NULL, *sent;
IFD_Timings timings;
if (icc->convention == ATR_CONVENTION_INVERSE)
{
buffer = (BYTE *) calloc(sizeof (BYTE), size);
memcpy (buffer, data, size);
ICC_Async_InvertBuffer (size, buffer);
sent = buffer;
}
else
sent = data;
timings.block_delay = icc->timings.block_delay;
timings.char_delay = icc->timings.char_delay;
if (IFD_Towitoko_Transmit (icc->ifd, &timings, size, sent) != IFD_TOWITOKO_OK)
return ICC_ASYNC_IFD_ERROR;
if (icc->convention == ATR_CONVENTION_INVERSE)
free (buffer);
return ICC_ASYNC_OK;
}
int
ICC_Async_Receive (ICC_Async * icc, unsigned size, BYTE * data)
{
IFD_Timings timings;
timings.block_timeout = icc->timings.block_timeout;
timings.char_timeout = icc->timings.char_timeout;
if (IFD_Towitoko_Receive (icc->ifd, &timings, size, data) != IFD_TOWITOKO_OK)
return ICC_ASYNC_IFD_ERROR;
if (icc->convention == ATR_CONVENTION_INVERSE)
ICC_Async_InvertBuffer (size, data);
return ICC_ASYNC_OK;
}
int
ICC_Async_Switch (ICC_Async * icc)
{
if (icc->baudrate > ICC_ASYNC_BAUDRATE)
{
if (IFD_Towitoko_Switch(icc->ifd) != IFD_TOWITOKO_OK)
return ICC_ASYNC_IFD_ERROR;
}
return ICC_ASYNC_OK;
}
int
ICC_Async_EndTransmission (ICC_Async * icc)
{
/* Restore parity */
if (icc->convention == ATR_CONVENTION_INVERSE)
{
if (IFD_Towitoko_SetParity (icc->ifd, IFD_TOWITOKO_PARITY_EVEN) != IFD_TOWITOKO_OK)
return ICC_ASYNC_IFD_ERROR;
}
return ICC_ASYNC_OK;
}
ATR *
ICC_Async_GetAtr (ICC_Async * icc)
{
return icc->atr;
}
IFD *
ICC_Async_GetIFD (ICC_Async * icc)
{
return icc->ifd;
}
int
ICC_Async_Close (ICC_Async * icc)
{
/* Dectivate ICC */
if (IFD_Towitoko_DeactivateICC (icc->ifd) != IFD_TOWITOKO_OK)
return ICC_ASYNC_IFD_ERROR;
/* LED Off */
if (IFD_Towitoko_SetLED (icc->ifd, IFD_TOWITOKO_LED_OFF) != IFD_TOWITOKO_OK)
return ICC_ASYNC_IFD_ERROR;
/* Delete atr */
ATR_Delete (icc->atr);
ICC_Async_Clear (icc);
return ICC_ASYNC_OK;
}
unsigned long
ICC_Async_GetClockRate (ICC_Async * icc)
{
return IFD_Towitoko_GetClockRate(icc->ifd);
}
void
ICC_Async_Delete (ICC_Async * icc)
{
free (icc);
}
/*
* Not exported functions definition
*/
static void
ICC_Async_InvertBuffer (unsigned size, BYTE * buffer)
{
int i;
for (i = 0; i < size; i++)
buffer[i] = ~(INVERT_BYTE (buffer[i]));
}
static void
ICC_Async_Clear (ICC_Async * icc)
{
icc->ifd = NULL;
icc->atr = NULL;
icc->baudrate = 0L;
icc->convention = 0;
icc->timings.block_delay = 0;
icc->timings.char_delay = 0;
icc->timings.block_timeout = 0;
icc->timings.char_timeout = 0;
}
syntax highlighted by Code2HTML, v. 0.9.1