/* 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 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 #include #include /* * 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; }