/*
ct_slot.c
Card Terminal Slot handling functions
This file is part of the Unix driver for Towitoko smartcard readers
Copyright (C) 2000 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 "ct_slot.h"
#include "ifd_towitoko.h"
#include "icc_sync.h"
#include "icc_async.h"
#include "protocol_sync.h"
#include "protocol_t0.h"
#include "protocol_t1.h"
#include "pps.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
/* Try first asynchronous init and if it fails try synchronous */
#undef ICC_PROBE_ASYNC_FIRST
/*
* Not exported functions declaration
*/
static void
CT_Slot_Clear (CT_Slot * slot);
/*
* Exported functions definition
*/
CT_Slot *
CT_Slot_New ()
{
CT_Slot *slot;
slot = (CT_Slot *) malloc (sizeof (CT_Slot));
if (slot != NULL)
CT_Slot_Clear (slot);
return slot;
}
char
CT_Slot_Init (CT_Slot * slot, IO_Serial * io, int sn)
{
slot->ifd = IFD_Towitoko_New();
if (slot->ifd == NULL)
return ERR_MEMORY;
if (IFD_Towitoko_Init (slot->ifd, io, sn) != IFD_TOWITOKO_OK)
{
IFD_Towitoko_Delete (slot->ifd);
slot->ifd = NULL;
return ERR_TRANS;
}
return OK;
}
char
CT_Slot_Check (CT_Slot * slot, int timeout, bool * card, bool * change)
{
BYTE status;
#ifdef HAVE_NANOSLEEP
struct timespec req_ts;
req_ts.tv_sec = 1;
req_ts.tv_nsec = 0;
#endif
/* Do first time check */
if (IFD_Towitoko_GetStatus (slot->ifd, &status) != IFD_TOWITOKO_OK)
return ERR_TRANS;
(*change) = IFD_TOWITOKO_CHANGE (status);
while ((timeout > 0) && (!IFD_TOWITOKO_CARD (status)))
{
timeout --;
#ifdef HAVE_NANOSLEEP
/* Sleep one second */
nanosleep (&req_ts,NULL);
#else
usleep (1000);
#endif
if (IFD_Towitoko_GetStatus (slot->ifd, &status) != IFD_TOWITOKO_OK)
return ERR_TRANS;
(*change) |= IFD_TOWITOKO_CHANGE (status);
}
(*card) = IFD_TOWITOKO_CARD (status);
return OK;
}
char
CT_Slot_Probe (CT_Slot * slot, BYTE * userdata, unsigned length)
{
PPS * pps;
BYTE buffer[PPS_MAX_LENGTH];
unsigned buffer_len = 0;
#ifndef ICC_PROBE_ASYNC_FIRST
/* Initiaice ICC */
slot->icc = ICC_Sync_New ();
if (slot->icc == NULL)
return ERR_MEMORY;
if (ICC_Sync_Init ((ICC_Sync *) slot->icc, slot->ifd) != ICC_SYNC_OK)
{
ICC_Sync_Delete ((ICC_Sync *) slot->icc);
/* Try asynchronous init */
slot->icc = ICC_Async_New ();
if (slot->icc == NULL)
return ERR_MEMORY;
if (ICC_Async_Init ((ICC_Async *) slot->icc, slot->ifd) != ICC_ASYNC_OK)
{
ICC_Async_Delete ((ICC_Async *) slot->icc);
/* ICC is not synchronous neither asynchronous */
slot->icc = NULL;
slot->icc_type = CT_SLOT_NULL;
/* return ERR_TRANS */
return OK;
}
/* Asynchronous card present */
slot->icc_type = CT_SLOT_ICC_ASYNC;
}
else
/* Syncronous card present */
slot->icc_type = CT_SLOT_ICC_SYNC;
#else
/* Initiaice ICC */
slot->icc = ICC_Async_New ();
if (slot->icc == NULL)
return ERR_MEMORY;
if (ICC_Async_Init (slot->icc, slot->ifd) != ICC_ASYNC_OK)
{
ICC_Async_Delete (slot->icc);
/* Try synchronous init */
slot->icc = ICC_Sync_New ();
if (slot->icc == NULL)
return ERR_MEMORY;
if (ICC_Sync_Init (slot->icc, slot->ifd) != ICC_SYNC_OK)
{
ICC_Sync_Delete (slot->icc);
/* ICC is not synchronous neither asynchronous */
slot->icc = NULL;
slot->icc_type = CT_SLOT_NULL;
return OK;
}
/* Synchronous card present */
slot->icc_type = CT_SLOT_ICC_SYNC;
}
else
/* Asyncronous card present */
slot->icc_type = CT_SLOT_ICC_ASYNC;
#endif
/* Initialise protocol */
if (slot->icc_type == CT_SLOT_ICC_ASYNC)
{
pps = PPS_New((ICC_Async *) slot->icc);
if (pps == NULL)
{
ICC_Async_Close ((ICC_Async *) slot->icc);
ICC_Async_Delete ((ICC_Async *) slot->icc);
slot->icc = NULL;
slot->icc_type = CT_SLOT_NULL;
return ERR_MEMORY;
}
/* Prepare PPS request */
if ((userdata != NULL) && (length > 0))
memcpy (buffer, userdata, buffer_len = MIN(length, PPS_MAX_LENGTH));
/* Do PPS */
if (PPS_Perform (pps, buffer, &buffer_len) != PPS_OK)
{
PPS_Delete (pps);
ICC_Async_Close ((ICC_Async *) slot->icc);
ICC_Async_Delete ((ICC_Async *) slot->icc);
slot->icc = NULL;
slot->icc_type = CT_SLOT_NULL;
slot->protocol_type = CT_SLOT_NULL;
return ERR_TRANS;
}
slot->protocol_type = (PPS_GetProtocolParameters (pps))->t;
slot->protocol = PPS_GetProtocol (pps);
PPS_Delete (pps);
}
else if (slot->icc_type == CT_SLOT_ICC_SYNC)
{
slot->protocol = Protocol_Sync_New ();
if (slot->protocol == NULL)
{
/* Delete ICC */
ICC_Sync_Close ((ICC_Sync *) slot->icc);
ICC_Sync_Delete ((ICC_Sync *) slot->icc);
slot->icc = NULL;
slot->icc_type = CT_SLOT_NULL;
return ERR_MEMORY;
}
if (Protocol_Sync_Init ((Protocol_Sync *) slot->protocol, (ICC_Sync *) slot->icc) != PROTOCOL_SYNC_OK)
{
/* Delete ICC */
ICC_Sync_Close ((ICC_Sync *) slot->icc);
ICC_Sync_Delete ((ICC_Sync *) slot->icc);
slot->icc = NULL;
slot->icc_type = CT_SLOT_NULL;
/* Delete protocol */
Protocol_Sync_Delete ((Protocol_Sync *) slot->protocol);
slot->protocol = NULL;
slot->protocol_type = CT_SLOT_NULL;
return ERR_TRANS;
}
slot->protocol_type = CT_SLOT_PROTOCOL_SYNC;
}
return OK;
}
char
CT_Slot_Release (CT_Slot * slot)
{
char ret;
ret = OK;
if (slot->protocol_type == CT_SLOT_PROTOCOL_SYNC)
{
if (Protocol_Sync_Close ((Protocol_Sync *) slot->protocol) != PROTOCOL_SYNC_OK)
ret = ERR_TRANS;
Protocol_Sync_Delete ((Protocol_Sync *) slot->protocol);
}
else if (slot->protocol_type == CT_SLOT_PROTOCOL_T0)
{
if (Protocol_T0_Close ((Protocol_T0 *) slot->protocol) != PROTOCOL_T0_OK)
ret = ERR_TRANS;
Protocol_T0_Delete ((Protocol_T0 *) slot->protocol);
}
else if (slot->protocol_type == CT_SLOT_PROTOCOL_T1)
{
if (Protocol_T1_Close ((Protocol_T1 *) slot->protocol) != PROTOCOL_T1_OK)
ret = ERR_TRANS;
Protocol_T1_Delete ((Protocol_T1 *) slot->protocol);
}
slot->protocol = NULL;
slot->protocol_type = CT_SLOT_NULL;
if (slot->icc_type == CT_SLOT_ICC_SYNC)
{
if (ICC_Sync_Close ((ICC_Sync *) slot->icc) != ICC_SYNC_OK)
ret = ERR_TRANS;
ICC_Sync_Delete ((ICC_Sync *) slot->icc);
}
else if (slot->icc_type == CT_SLOT_ICC_ASYNC)
{
if (ICC_Async_Close ((ICC_Async *) slot->icc) != ICC_ASYNC_OK)
ret = ERR_TRANS;
ICC_Async_Delete ((ICC_Async *) slot->icc);
}
slot->icc = NULL;
slot->icc_type = CT_SLOT_NULL;
return ret;
}
char
CT_Slot_Command (CT_Slot * slot, APDU_Cmd * cmd, APDU_Rsp ** rsp)
{
BYTE buffer[2];
char ret;
/* Synchronous protocol ICC */
if (slot->protocol_type == CT_SLOT_PROTOCOL_SYNC)
{
if (Protocol_Sync_Command ((Protocol_Sync *) slot->protocol, cmd, rsp) != PROTOCOL_SYNC_OK)
ret = ERR_TRANS;
else
ret = OK;
}
/* T=0 protocol ICC */
else if (slot->protocol_type == CT_SLOT_PROTOCOL_T0)
{
if (Protocol_T0_Command ((Protocol_T0 *) slot->protocol, cmd, rsp) != PROTOCOL_T0_OK)
ret = ERR_TRANS;
else
ret = OK;
}
/* T=1 protocol ICC */
else if (slot->protocol_type == CT_SLOT_PROTOCOL_T1)
{
if (Protocol_T1_Command ((Protocol_T1 *) slot->protocol, cmd, rsp) != PROTOCOL_T1_OK)
ret = ERR_TRANS;
else
ret = OK;
}
/* Card removed */
else if (slot->protocol_type == CT_SLOT_NULL)
{
buffer[0] = CTBCS_SW1_ICC_ERROR;
buffer[1] = CTBCS_SW2_ICC_ERROR;
(*rsp) = APDU_Rsp_New (buffer, 2);
ret = OK;
}
/* Other protocol */
else
{
(*rsp) = NULL;
ret = ERR_HTSI;
}
return ret;
}
int
CT_Slot_GetICCType (CT_Slot * slot)
{
return slot->icc_type;
}
void *
CT_Slot_GetICC (CT_Slot * slot)
{
return slot->icc;
}
void *
CT_Slot_GetAtr (CT_Slot * slot)
{
if (slot->icc_type == CT_SLOT_ICC_ASYNC)
return ((void *) ICC_Async_GetAtr((ICC_Async *) slot->icc));
else if (slot->icc_type == CT_SLOT_ICC_SYNC)
return ((void *) ICC_Sync_GetAtr((ICC_Sync *) slot->icc));
return NULL;
}
bool
CT_Slot_IsLast (CT_Slot * slot)
{
return (IFD_Towitoko_GetSlot(slot->ifd) >=
IFD_Towitoko_GetNumSlots(slot->ifd)-1);
}
void
CT_Slot_GetType (CT_Slot * slot, BYTE * buffer, int len)
{
IFD_Towitoko_GetDescription (slot->ifd, buffer, len);
}
char
CT_Slot_Close (CT_Slot * slot)
{
char ret;
ret = OK;
if (slot->protocol_type == CT_SLOT_PROTOCOL_SYNC)
{
if (Protocol_Sync_Close ((Protocol_Sync *) slot->protocol) != PROTOCOL_SYNC_OK)
ret = ERR_TRANS;
Protocol_Sync_Delete ((Protocol_Sync *) slot->protocol);
}
else if (slot->protocol_type == CT_SLOT_PROTOCOL_T0)
{
if (Protocol_T0_Close ((Protocol_T0 *) slot->protocol) != PROTOCOL_T0_OK)
ret = ERR_TRANS;
Protocol_T0_Delete ((Protocol_T0 *) slot->protocol);
}
else if (slot->protocol_type == CT_SLOT_PROTOCOL_T1)
{
if (Protocol_T1_Close ((Protocol_T1 *) slot->protocol) != PROTOCOL_T1_OK)
ret = ERR_TRANS;
Protocol_T1_Delete ((Protocol_T1 *) slot->protocol);
}
if (slot->icc_type == CT_SLOT_ICC_SYNC)
{
if (ICC_Sync_Close ((ICC_Sync *) slot->icc) != ICC_SYNC_OK)
ret = ERR_TRANS;
ICC_Sync_Delete ((ICC_Sync *) slot->icc);
}
else if (slot->icc_type == CT_SLOT_ICC_ASYNC)
{
if (ICC_Async_Close ((ICC_Async *) slot->icc) != ICC_ASYNC_OK)
ret = ERR_TRANS;
ICC_Async_Delete ((ICC_Async *) slot->icc);
}
if (slot->ifd != NULL)
{
if (IFD_Towitoko_Close (slot->ifd) != IFD_TOWITOKO_OK)
ret = ERR_TRANS;
IFD_Towitoko_Delete (slot->ifd);
}
CT_Slot_Clear (slot);
return ret;
}
void
CT_Slot_Delete (CT_Slot * slot)
{
free (slot);
}
/*
* Not exported functions definition
*/
static void
CT_Slot_Clear (CT_Slot * slot)
{
slot->ifd = NULL;
slot->icc = NULL;
slot->protocol = NULL;
slot->icc_type = CT_SLOT_NULL;
slot->protocol_type = CT_SLOT_NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1