asedriveiiie-3.7/0000755000175000017500000000000011447406620014327 5ustar rousseaurousseauasedriveiiie-3.7/asedriveiiie-serial/0000700000175000017500000000000011441415531020227 5ustar rousseaurousseauasedriveiiie-3.7/asedriveiiie-serial/T1Protocol.h0000755000175000017500000000361711265303424022433 0ustar rousseaurousseau#ifndef __T1PROTOCOL_H #define __T1PROTOCOL_H typedef unsigned char uchar; /***************************************************************************** * *****************************************************************************/ #define T1_BLOCK_MAX_SIZE 259 #define T1_BLOCK_INF_MAX_SIZE 254 #define ATHENA_IFSC_MAX_SIZE 254 /* PCBs */ #define T1_BLOCK_I 0x00 #define T1_BLOCK_R 0x80 #define T1_BLOCK_S 0xC0 #define T1_BLOCK_S_RESYNCH_REQ 0xC0 #define T1_BLOCK_S_RESYNCH_RES 0xE0 #define T1_BLOCK_S_IFS_REQ 0xC1 #define T1_BLOCK_S_IFS_RES 0xE1 #define T1_BLOCK_S_ABORT_REQ 0xC2 #define T1_BLOCK_S_ABORT_RES 0xE2 #define T1_BLOCK_S_WTX_REQ 0xC3 #define T1_BLOCK_S_WTX_RES 0xE3 #define T1_BLOCK_S_VPP_ERR 0xE4 /***************************************************************************** * *****************************************************************************/ #define PROTOCOL_T1_OK 0 /* Command OK */ #define PROTOCOL_T1_ICC_ERROR -2000 /* ICC comunication error */ #define PROTOCOL_T1_ERROR -2001 /* T=1 Protocol Error */ #define T1_ABORT_RECEIVED -2002 #define T1_RESYNCH_RECEIVED -2003 #define T1_VPP_ERROR_RECEIVED -2004 #define PROTOCOL_T1_SEND_I_BLOCK 1 #define PROTOCOL_T1_SEND_R_BLOCK 2 #define PROTOCOL_T1_SEND_S_BLOCK 3 typedef struct { uchar data[T1_BLOCK_MAX_SIZE]; int len; } T1Block; typedef struct { int ifsc; /* Information field size for the ICC */ int edc; /* Type of error detection code */ uchar ns; /* Send sequence number */ uchar nsCard; /* Send sequence number of the card */ T1Block sendBlock, recBlock; } T1Protocol; #endif asedriveiiie-3.7/asedriveiiie-serial/ReaderCommands.c0000755000175000017500000010143711441415065023304 0ustar rousseaurousseau#include "Ase.h" /***************************************************************************** * *****************************************************************************/ //#define ASE_PACKET_TYPE(pid, cnt, dst) (pid | cnt << 2 | dst) #define ASE_PACKET_TYPE(pid, cnt, dst) (pid | dst) #define ASE_STOP_BYTE(cnt, dst) (0x60 | cnt << 2 | dst) #define T0_DATA_CHUNK_SIZE 28 #define T1_DATA_CHUNK_SIZE 32 /***************************************************************************** * *****************************************************************************/ static void GetDefaultReaderParams (reader* globalData, struct card_params* params) { params->protocol = 0; params->N = 0x03; params->CWT[0] = 0x00; params->CWT[1] = 0x25/*0x85*/; params->CWT[2] = 0x85/*0xF0*/; params->BWT[0] = 0x00; params->BWT[1] = 0x3A/*0x38*/; params->BWT[2] = 0x34/*0xA4*/; /* 372 */ params->A = 0x01; params->B = 0x74; params->freq = 0x02; } /***************************************************************************** * *****************************************************************************/ /* returns 0 on success */ int cardCommandInit (reader* globalData, char socket, char needToBePoweredOn) { if (!globalData->cards[(int)socket].status) { return ASE_READER_NO_CARD_ERROR; } if (needToBePoweredOn && globalData->cards[(int)socket].status != 2) { return ASE_READER_CARD_NOT_POWERED_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int readerCommandInit (reader* globalData, char needToBeStarted) { if (needToBeStarted && !globalData->readerStarted) { return ASE_ERROR_COMMAND; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static void lock_mutex (reader* globalData) { int retVal; #ifdef ASE_DEBUG /* syslog(LOG_INFO, " Trying...");*/ #endif retVal = pthread_mutex_lock(&(globalData->semaphore)); if (retVal != 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "Error! - in pthread_mutex_lock\n"); #endif } #ifdef ASE_DEBUG /* syslog(LOG_INFO, "Entering mutex\n");*/ #endif } /***************************************************************************** * *****************************************************************************/ static void unlock_mutex (reader* globalData) { int retVal; #ifdef ASE_DEBUG /* syslog(LOG_INFO, " Trying...");*/ #endif retVal = pthread_mutex_unlock(&(globalData->semaphore)); if (retVal != 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "Error! - in pthread_mutex_unlock\n"); #endif } #ifdef ASE_DEBUG /* syslog(LOG_INFO, "Leaving mutex\n");*/ #endif } /***************************************************************************** * *****************************************************************************/ int ReaderStartup (reader* globalData, char* response, int* len) { char cmd[4]; int retVal, i, retryTimes = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReaderStartup - Enter\n"); #endif if (globalData->readerStarted) { return ASE_ERROR_COMMAND; } globalData->readerStarted = 0; globalData->commandCounter = 1; globalData->cards[0].status = globalData->cards[0].ceei = globalData->cards[0].atr.length = 0; globalData->cards[1].status = globalData->cards[1].ceei = globalData->cards[1].atr.length = 0; globalData->cards[0].cwt = globalData->cards[1].cwt = 1500000; /* 1.5 sec */ /* init mutex */ retVal = pthread_mutex_init(&(globalData->semaphore), NULL); if (retVal != 0) return ASE_ERROR_COMMAND; //?????????? if ((retVal = readerCommandInit(globalData, 0))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x10; cmd[2] = 0x00; cmd[3] = cmd[0] ^ cmd[1] ^ cmd[2]; do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, 0, cmd2, 4, response, len, 1); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, 0, cmd, 4, response, len, 1); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); if (retVal < 0) { return retVal; } globalData->readerStarted = 1; /* copy response to the ASE data memory field */ /* first byte is communication data ??? */ for (i = 1 ; i < (*len) ; ++i) globalData->dataMemory[i - 1] = response[i]; #ifdef ASE_DEBUG syslog(LOG_INFO, " ReaderStartup - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int ReaderFinish (reader* globalData) { char cmd[4], ack; int retVal, actual, retryTimes = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReaderFinish - Enter\n"); #endif if ((retVal = readerCommandInit(globalData, 1))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x11; cmd[2] = 0x0; cmd[3] = cmd[0] ^ cmd[1] ^ cmd[2]; do { lock_mutex(globalData); retVal = sendControlCommand(globalData, 0, cmd, 4, &ack, &actual, 0); unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (ack != 0x20) { return parseStatus(ack); } globalData->readerStarted = 0; #ifdef ASE_DEBUG syslog(LOG_INFO, " ReaderFinish - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int GetStatus (reader* globalData, char* response, int* len) { char cmd[4]; int retVal, retryTimes = 2; /* syslog(LOG_INFO, "\n GetStatus - Enter\n"); */ if ((retVal = readerCommandInit(globalData, 1))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x16; cmd[2] = 0x0; cmd[3] = cmd[0] ^ cmd[1] ^ cmd[2]; do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, 0, cmd2, 4, response, len, 1); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, 0, cmd, 4, response, len, 1); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (response[0] & 0x01) { if (!(globalData->cards[0].status)) /* only if not powered on */ globalData->cards[0].status = 1; } else globalData->cards[0].status = 0; if (response[0] & 0x02) { if (!(globalData->cards[1].status)) /* only if not powered on */ globalData->cards[1].status = 1; } else globalData->cards[1].status = 0; /* syslog(LOG_INFO, " GetStatus - Exit\n"); */ return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int SetCardParameters (reader* globalData, char socket, struct card_params params) { char cmd[15], ack; int retVal, i, actual, retryTimes = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SetCardParameters - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 0))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x15; cmd[2] = 0x0B; cmd[3] = params.protocol; cmd[4] = params.N; cmd[5] = params.CWT[0]; cmd[6] = params.CWT[1]; cmd[7] = params.CWT[2]; cmd[8] = params.BWT[0]; cmd[9] = params.BWT[1]; cmd[10] = params.BWT[2]; cmd[11] = params.A; cmd[12] = params.B; cmd[13] = params.freq; cmd[14] = cmd[0]; for (i = 1 ; i < 14 ; i++) cmd[14] ^= cmd[i]; do { lock_mutex(globalData); retVal = sendControlCommand(globalData, socket, cmd, 15, &ack, &actual, 0); unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (ack != 0x20) { return parseStatus(ack); } globalData->cards[(int)socket].cardParams = params; #ifdef ASE_DEBUG syslog(LOG_INFO, " SetCardParameters - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int CardPowerOn (reader* globalData, char socket, uchar cardType, uchar voltage) { char cmd[6], response[300]; int retVal, len, retryTimes = 2; ATR* atr = &(globalData->cards[(int)socket].atr); #ifdef ASE_DEBUG syslog(LOG_INFO, "\n CardPowerOn - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 0))) return retVal; /* GetDefaultReaderParams(globalData, ¶ms); retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return retVal; } */ cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x20; cmd[2] = 0x02; cmd[3] = cardType; cmd[4] = voltage; cmd[5] = cmd[0] ^ cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4]; /* CPU cards -> an open response should be receievd */ if (cardType == 0x00 || cardType == 0x01) { do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, response, &len, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, cmd, 6, response, &len, 0); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } retVal = ParseATR(globalData, socket, response, len); } /* 2/3BUS memory cards -> a close response should be received */ else if (cardType == 0x11 || cardType == 0x12) { memset(atr, 0x00, sizeof(ATR)); do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, response, &len, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, cmd, 6, response, &len, 0); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (retVal == ASE_OK) { if (len) { memcpy(atr->data, response, len); atr->length = len; } } } /* X/I2C memory cards -> an acknowledgement should be received */ else { memset(atr, 0x00, sizeof(ATR)); do { lock_mutex(globalData); retVal = sendControlCommand(globalData, socket, cmd, 6, response, &len, 0); unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } } if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " CardPowerOn - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int CPUCardReset (reader* globalData, char socket) { char cmd[4], response[300]; int retVal, len, retryTimes = 2; struct card_params params; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n CPUCardReset - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; GetDefaultReaderParams(globalData, ¶ms); retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return retVal; } cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x22; cmd[2] = 0x00; cmd[3] = cmd[0] ^ cmd[1] ^ cmd[2]; do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, response, &len, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, cmd, 4, response, &len, 0); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } retVal = ParseATR(globalData, socket, response, len); if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " CPUCardReset - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int CardPowerOff (reader* globalData, char socket) { char cmd[4], ack; int retVal, actual, retryTimes = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n CardPowerOff - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x21; cmd[2] = 0x0; cmd[3] = cmd[0] ^ cmd[1] ^ cmd[2]; do { lock_mutex(globalData); retVal = sendControlCommand(globalData, socket, cmd, 4, &ack, &actual, 0); unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (ack != 0x20) { return parseStatus(ack); } /* if the card is present, change the status to powered off */ if (globalData->cards[(int)socket].status) globalData->cards[(int)socket].status = 1; #ifdef ASE_DEBUG syslog(LOG_INFO, " CardPowerOff - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ /* on == 0x01, off == 0x00 */ int ChangeLedState (reader* globalData, char on) { char cmd[5], ack; int retVal, actual, retryTimes = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ChangeLedState - Enter\n"); #endif if ((retVal = readerCommandInit(globalData, 1))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x17; cmd[2] = 0x01; cmd[3] = on; cmd[4] = cmd[0] ^ cmd[1] ^ cmd[2] ^ cmd[3]; do { lock_mutex(globalData); retVal = sendControlCommand(globalData, 0, cmd, 5, &ack, &actual, 1); unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (ack != 0x20) { return parseStatus(ack); } #ifdef ASE_DEBUG syslog(LOG_INFO, " ChangeLedState - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int PPSTransact (reader* globalData, char socket, char* buffer, int len, char* outBuf, int* outBufLen) { int retVal; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n PPSTransact - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 0))) return retVal; retVal = CardCommand(globalData, socket, 0x43, (unsigned char*)buffer, len, (unsigned char*)outBuf, outBufLen); if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " PPSTransact - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int MemoryCardTransact (reader* globalData, char socket, char cmdType, uchar command, ushort address, uchar len, uchar* data, char* outBuf, int* outBufLen) { char cmd[BULK_BUFFER_SIZE]; uchar checksum, readByte; int retVal, i, actual; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n MemoryCardTransact - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x25; cmd[2] = 5 + (cmdType == 0 ? len : 0); cmd[3] = cmdType; cmd[4] = command; cmd[5] = (address >> 8) & 0xFF; cmd[6] = address & 0xFF; cmd[7] = len; checksum = cmd[0] ^ cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5] ^ cmd[6] ^ cmd[7]; i = 0; if (cmdType == 0) { for (; i < len ; ++i) { cmd[i + 8] = data[i]; checksum ^= cmd[i + 8]; } } cmd[i + 8] = checksum; lock_mutex(globalData); /* send the command */ retVal = writeToReader(globalData, cmd, cmd[2] + 4, &actual); if (retVal < 0) { return retVal; } checksum = 0; /* read the Ack control byte or the close response packet type */ retVal = readResponse(globalData, socket, 1, (char*)&readByte, &actual, 1000000); if (retVal < 0) { unlock_mutex(globalData); return retVal; } while ((readByte & 0xF0) != 0x10) { if ((readByte & 0xF0) == 0x20) { if (readByte != 0x20) { unlock_mutex(globalData); return parseStatus(readByte); } else break; } else if (isEvent(readByte)) { #ifdef ASE_DEBUG syslog(LOG_INFO, "MemoryCardTransact - Event 0x%x%x.\n", (readByte & 0xF0) >> 4, readByte & 0x0F); #endif parseEvent(globalData, socket, readByte); } retVal = readResponse(globalData, socket, 1, (char*)(&readByte), &actual, 1000000); if (retVal < 0) { unlock_mutex(globalData); return retVal; } } checksum ^= readByte; /* if readByte == 0x2x */ if ((readByte & 0xF0) == 0x20) { if (readByte != 0x20) { /* *outBufLen = 0; */ unlock_mutex(globalData); return parseStatus(readByte); } } /* ths response is a close response */ else if ((readByte & 0xF0) == 0x10) { if (readByte != 0x10) { unlock_mutex(globalData); return parseStatus(readByte); } /* read data length */ retVal = readResponse(globalData, socket, 1, (char*)&readByte, &actual, 1000000); if (retVal < 0) { unlock_mutex(globalData); return retVal; } checksum ^= readByte; /* read data */ retVal = readResponse(globalData, socket, readByte, outBuf, outBufLen, 1000000); if (retVal < 0 || (*outBufLen) != readByte) { unlock_mutex(globalData); return retVal; } for (i = 0 ; i < *outBufLen ; ++i) checksum ^= outBuf[i]; /* read the checksum */ retVal = readResponse(globalData, socket, 1, (char*)&readByte, &actual, 1000000); if (retVal < 0) { unlock_mutex(globalData); return retVal; } if (checksum != readByte) { unlock_mutex(globalData); return ASE_ERROR_CHECKSUM; } } unlock_mutex(globalData); #ifdef ASE_DEBUG syslog(LOG_INFO, " MemoryCardTransact - Exit\n\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int T0Read (reader* globalData, char socket, uchar* buffer, int len, uchar* outBuf, int* outBufLen) { int retVal; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n T0Read - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; retVal = CardCommand(globalData, socket, 0x41, buffer, len, outBuf, outBufLen); if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " T0Read - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int T0Write (reader* globalData, char socket, uchar* buffer, int len, uchar* outBuf, int* outBufLen) { int retVal; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n T0Write - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; retVal = CardCommand(globalData, socket, 0x40, buffer, len, outBuf, outBufLen); if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " T0Write - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int T1CPUCardTransact (reader* globalData, char socket, char* buffer, int len, char* outBuf, int* outBufLen) { int retVal; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n T1CPUCardTransact - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; retVal = CardCommand(globalData, socket, 0x42, (unsigned char*)buffer, len, (unsigned char*)outBuf, outBufLen); if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " T1CPUCardTransact - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int CardCommand (reader* globalData, char socket, char command, uchar* buffer, int len, uchar* outBuf, int* outBufLen) { char cmd[BULK_BUFFER_SIZE]; uchar checksum; int retVal = ASE_OK, i, retryTimes = 2; /* short format */ if (len <= 255) { cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = command; cmd[2] = (uchar)len; checksum = cmd[0] ^ cmd[1] ^ cmd[2]; i = 0; for (; i < len ; ++i) { cmd[i + 3] = buffer[i]; checksum ^= cmd[i + 3]; } cmd[i + 3] = checksum; do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, (char*)outBuf, outBufLen, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, cmd, len + 4, (char*)outBuf, outBufLen, 0); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); } /* long format */ else { cmd[0] = ASE_PACKET_TYPE(0xD0, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = command; cmd[2] = (len >> 8) & 0xFF; cmd[3] = len & 0xFF; checksum = cmd[0] ^ cmd[1] ^ cmd[2] ^ cmd[3]; i = 0; for (; i < len ; ++i) { cmd[i + 4] = buffer[i]; checksum ^= cmd[i + 4]; } cmd[i + 4] = checksum; do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, (char*)outBuf, outBufLen, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, cmd, len + 5, (char*)outBuf, outBufLen, 0); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); } if (retVal < 0) { return retVal; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int SendIOCTL (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuf, int *outBufLen) { char ack = 0x00; int retVal, actual, retryTimes = 2, sendLen = *outBufLen; int dataLen, i; unsigned char cs = 0; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SendIOCTL - Enter sendLen = %d\n", sendLen); #endif if ((retVal = readerCommandInit(globalData, 1))) return retVal; // verify that inBuf has a valid reader command structure (including checksum) if (inBuf[0] != 0x50) return ASE_READER_PID_ERROR; // inBuf[1] is the command dataLen = inBuf[2]; if (dataLen != (inBufLen - 4 /*PID+CMD+LEN+CKM*/)) return ASE_READER_LEN_ERROR; for (i = 0 ; i < inBufLen ; ++i) cs ^= inBuf[i]; if (cs) return ASE_READER_CS_ERROR; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SendIOCTL - cmd struct ok\n"); #endif do { lock_mutex(globalData); if (sendLen == 2) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SendIOCTL - ControlCommand\n"); #endif retVal = sendControlCommand(globalData, 0, (char*)inBuf, inBufLen, &ack, &actual, 1); } else { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SendIOCTL - CloseResponseCommand retVal = %0x\n", retVal); #endif /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, (char*)outBuf, outBufLen, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, (char*)inBuf, inBufLen, (char*)outBuf, outBufLen, 0); } } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SendIOCTL - retVal = %0x ack = %0x *outBufLen = %d\n", retVal, ack, *outBufLen); #endif // if during the 3 tries the command failed, return an error status if (retVal < 0) { // general error outBuf[0] = 0x6F; outBuf[1] = 0x00; *outBufLen = 2; return retVal; } if (sendLen == 2 && ack != 0x20) { // general error outBuf[0] = 0x6F; outBuf[1] = 0x00; return parseStatus(ack); } // success if (sendLen == 2) { outBuf[0] = 0x90; outBuf[1] = 0x00; } else { outBuf[(*outBufLen)++] = 0x90; outBuf[(*outBufLen)++] = 0x00; } #ifdef ASE_DEBUG syslog(LOG_INFO, " SendIOCTL - Exit\n"); #endif return ASE_OK; } asedriveiiie-3.7/asedriveiiie-serial/ChangeLog0000755000175000017500000000074211265303424022022 0ustar rousseaurousseauasedriveiiie-serial-3.6: ===================== - IFDHSetProtocolParameters does nothing when the protocol need not be changed. asedriveiiie-serial-3.5: ===================== - removed ifdhandler.h and added IFDHANDLERv2 to Makefile in order to support pcsc-lite-1.4.0 and above. asedriveiiieserial-3.4: ===================== - corrected installation scripts asedriveiiieserial-3.3: ===================== - add support for devices on the USB bus (e.g. a serial to usb adaptor) asedriveiiie-3.7/asedriveiiie-serial/configure0000755000175000017500000000273411265303424022157 0ustar rousseaurousseau#!/bin/sh cd `dirname $0` USAGE=0 PREFIX=/usr USBDROPDIR= BUILD= PCSC_HEADERS= PCSC_LIBS= for p in $*; do v=${p#*=} case "$p" in --help) USAGE=1 ;; --prefix=*) PREFIX="$v" ;; --with-pcsc-drivers-dir=*) USBDROPDIR="$v" ;; --with-pcsc-headers=*) PCSC_HEADERS="$v" ;; --with-pcsc-libs=*) PCSC_LIBS="$v" ;; --build=*) BUILD="$v" ;; esac done if [ ${USAGE} != 0 ]; then echo -e "usage $0" echo -e "\t--help\t\t\tThis help." echo -e "\t--build=arch\t\tSet build architacture (gcc prefix), default empty." echo -e "\t--prefix=dir\t\tSet installation prefix, default /usr." echo -e "\t--with-pcsc-drivers-dir=dir\tSet pcsc drivers directory." echo -e "\t--with-pcsc-headers=dir\t\tSet manual pcsc headers directory." echo -e "\t--with-pcsc-libs=dir\t\tSet manual pcsc library dir." exit 1 fi if [ -z "$USBDROPDIR" ]; then USBDROPDIR=`pkg-config libpcsclite --variable=usbdropdir` fi if [ -z "$USBDROPDIR" ]; then echo "Cannot find pcsc drivers directory" exit 1 fi if [ -z "$PCSC_HEADERS" ]; then CFLAGS="$CFLAGS `pkg-config libpcsclite --cflags`" else CFLAGS="$CFLAGS -I${PCSC_HEADERS}" fi if [ -z "$PCSC_LIBS" ]; then LDFLAGS="$LDFLAGS `pkg-config libpcsclite --libs`" else LDFLAGS="$LDFLAGS -L${PCSC_LIBS} -lpcsclite" fi echo "PREFIX=${PREFIX}" > Makefile.inc echo "USBDROPDIR=${USBDROPDIR}" >> Makefile.inc echo "BUILD=${BUILD}" >> Makefile.inc echo "CFLAGS=${CFLAGS}" >> Makefile.inc echo "LDFLAGS=${LDFLAGS}" >> Makefile.inc exit 0 asedriveiiie-3.7/asedriveiiie-serial/README0000755000175000017500000000531611441365041021131 0ustar rousseaurousseau*************************************************************** Title : README Hardware: ASEDrive IIIe Serial Smartcard Reader Company : Athena Smartcard Solutions, http://www.athena-scs.com Version : 3.7 LICENSE : See file LICENSE Required: gcc 2.7 or higher, Linux kernel 2.4.x or higher *************************************************************** What you need: ================ Get the latest version of PCSC Lite by David Corcoran. You can get the latest version of PCSC Lite from: http://www.linuxnet.com/middle.html Follow the instructions and install it on your computer. Installing the ASEDrive IIIe Serial driver: =========================================== To complie this package from a Linux prompt use the following: # ./configure # make # make install The driver installs itself to /usr/local/pcsc/drivers by default. To change this edit the Makefile and the etc/reader.conf file. This will create a shared library called libAseSerial.so which is the library used to talk to the IFD Handler interface. To install this reader into the PCSC/Lite Architecture simply edit the etc/reader.conf file included in the package and set the LIBRARY_PATH to the location of the shared library. An example reader.conf is provided in this package in the etc directory. Also, set the CHANNELID to the approprate serial port desired. Use the following values for CHANNELID: COM1 0x0103F8 COM2 0x0102F8 COM3 0x0103E8 COM4 0x0102E8 For devices on the USB bus (e.g. a serial to usb adaptor) use: /dev/ttyUSB0 0x800000 /dev/ttyUSB1 0x800001 /dev/ttyUSB2 0x800002 /dev/ttyUSB3 0x800003 DEVICENAME and FRIENDLYNAME should already be set and should not be modified. When finished, simply copy the reader.conf file to /etc on your system. NOTE: If a /etc/reader.conf file already exists on your system, simply append the contents of the edited file to the end of the exisiting one. Starting and testing: ======================= To start the pcsc daemon you'll need root privileges. # /usr/local/pcsc/bin/pcscd You should be able to communicate with the reader by now. There is a small test program called "testpcsc" that comes with the pcsc-lite package. Refer to the pcsc-lite's README for compilation instructions. This program tries to connect to the selected reader and to get the ATR. Notes: ======== - To see the driver's debug messages, add -DASE_DEBUG to CC in the Makefile and recompile. Note that the messages are written to the system log (usually: /var/log/messages). Questions: ============ For questions, please email at: support@athena-scs.com asedriveiiie-3.7/asedriveiiie-serial/atr.h0000755000175000017500000000277411265303424021216 0ustar rousseaurousseau#ifndef __ATR_H #define __ATR_H /***************************************************************************** * *****************************************************************************/ #define MAX_ATR_SIZE 33 #define UNKNOWN_PROTOCOL 20 #define SPECIFIC_MODE 1 #define NEGOTIABLE_MODE 2 #define ATR_MAX_SIZE 33 /* Maximum size of ATR byte array */ #define ATR_MAX_HISTORICAL 15 /* Maximum number of historical bytes */ #define ATR_MAX_PROTOCOLS 7 /* Maximun number of protocols */ #define ATR_MAX_IB 4 /* Maximum number of interface bytes per protocol */ #define ATR_PROTOCOL_TYPE_T0 0 /* Protocol type T=0 */ #define ATR_PROTOCOL_TYPE_T1 1 /* Protocol type T=1 */ #define ATR_PROTOCOL_TYPE_T2 2 /* Protocol type T=2 */ #define ATR_PROTOCOL_TYPE_T3 3 /* Protocol type T=3 */ #define ATR_PROTOCOL_TYPE_T14 14 /* Protocol type T=14 */ #define ATR_PROTOCOL_TYPE_T15 15 /* Protocol type T=15 */ #define ATR_PROTOCOL_TYPE_RAW 16 /* Memory Cards Raw Protocol */ /***************************************************************************** * *****************************************************************************/ typedef struct { unsigned char data[MAX_ATR_SIZE]; unsigned length; unsigned char TS; unsigned char T0; struct { unsigned char value; char present; } ib[ATR_MAX_PROTOCOLS][ATR_MAX_IB], TCK; int pn; /* protocol number */ unsigned char hb[ATR_MAX_HISTORICAL]; int hbn; } ATR; #endif asedriveiiie-3.7/asedriveiiie-serial/LinuxDefines.h0000755000175000017500000000313111265303424023011 0ustar rousseaurousseau#ifndef __Linux_Defines_h_ #define __Linux_Defines_h_ #define BOOL unsigned short #define bool unsigned short #define HANDLE unsigned long /* #ifndef BOOL typedef unsigned short BOOL; #endif typedef BOOL bool; typedef unsigned short USHORT; typedef unsigned char UCHAR; typedef UCHAR BYTE; typedef unsigned char* PUCHAR; typedef char* STR; typedef unsigned long ULONG; typedef short BOOLEAN; typedef ULONG RESPONSECODE; typedef ULONG* PULONG; typedef ULONG DWORD; typedef void* PVOID; typedef ULONG HANDLE; */ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef NULL #define NULL 0x0000 #endif /********************************************/ #ifndef MAX_BUFFER_SIZE #define MAX_BUFFER_SIZE 264 #endif #define MAX_ATR_SIZE 33 #define STATUS_SUCCESS 0x0000 #define STATUS_UNSUCCESSFUL 0x0001 #define STATUS_IO_TIMEOUT 0x0002 #define STATUS_DATA_ERROR 0x0004 #define STATUS_UNRECOGNIZED_MEDIA 0x0008 #define STATUS_BUFFER_TOO_SMALL 0x0010 #define STATUS_DEVICE_PROTOCOL_ERROR 0x0020 /***************************************************************************** * *****************************************************************************/ /* Packet IDs */ #define READER_ACK 0x20 #define READER_CLOSE_RESPONSE 0x10 #define READER_LONG_CLOSE_RESPONSE 0x90 #define HOST_COMMAND 0x50 #define HOST_LONG_COMMAND 0xD0 #endif asedriveiiie-3.7/asedriveiiie-serial/etc/0000700000175000017500000000000011447406536021015 5ustar rousseaurousseauasedriveiiie-3.7/asedriveiiie-serial/etc/reader.conf.in0000755000175000017500000000041111265303424023532 0ustar rousseaurousseau# Configuration file for pcsc-lite # # ASEDriveIIIe Serial Reader FRIENDLYNAME "ASEDrive IIIe Serial Reader on COM1" DEVICENAME /dev/null LIBPATH %PCSC_DRIVERS_DIR%/ifd-ASEDriveIIIe-Serial/libASESerial.so CHANNELID 0x0103F8 # End of file asedriveiiie-3.7/asedriveiiie-serial/MemoryCards.h0000755000175000017500000000625311265303424022651 0ustar rousseaurousseau#ifndef __MEMEORY_CARDS_H #define __MEMEORY_CARDS_H /***************************************************************************** * *****************************************************************************/ #define MAIN_MEM 0 #define PROTECTED_MEM 1 #define PROTOCOL_MEM_2BUS 0 #define PROTOCOL_MEM_3BUS 1 #define PROTOCOL_MEM_I2C 2 #define PROTOCOL_MEM_XI2C 3 #define MEM_CARD_MAIN_MEM_MODE 1 #define MEM_CARD_PROT_MEM_MODE 2 typedef struct { char memType; char protocolType; } MemCard; /***************************************************************************** * *****************************************************************************/ #define MEM_CARD_OK 0 #define MEM_CARD_ERROR_CMD_STRUCT -3000 #define MEM_CARD_ERROR_APDU -3001 #define MEM_CARD_COMM_ERROR -3002 #define MEM_CARD_BLOCKED -3003 #define MEM_CARD_PROTOCOL_NOT_SUPPORTED -3004 #define MEM_CARD_INVALID_PARAMETER -3005 #define MEM_CARD_ILLEGAL_ADDRESS -3006 #define MEM_CARD_BAD_MODE -3007 #define MEM_CARD_VERIFY_FAILED -3008 #define MEM_CARD_NOT_VERIFIED -3009 #define MEM_CARD_WRONG_LENGTH -3010 #define MEM_CARD_WRONG_CLASS -3011 #define MEM_CARD_WRONG_INST -3012 #define MEM_CARD_FILE_NOT_FOUND -3013 #define MEM_CARD_WRITE_FAILED -3014 /***************************************************************************** * *****************************************************************************/ #define APDU_INS_SELECT 0xA4 #define APDU_INS_VERIFY 0x20 #define APDU_INS_CHANGE_PASSWORD 0x24 #define APDU_INS_READ_BINARY 0xB0 #define APDU_INS_WRITE_BINARY 0xD6 /***************************************************************************** * *****************************************************************************/ /* 2 Card commands definitions */ #define _2BUS_READ_DATA 0x30 #define _2BUS_UPDATE_DATA 0x38 #define _2BUS_READ_PBIT 0x34 #define _2BUS_PROTECT_DATA_COND 0x3C #define _2BUS_READ_SECURITY_MEM 0x31 #define _2BUS_UPDATE_SECURITY_MEM 0x39 #define _2BUS_COMPARE_VERIFICATION 0x33 /* 3 Card commands definitions */ #define _3BUS_UPDATE_AND_PROTECT 0x31 #define _3BUS_UPDATE_DATA 0x33 #define _3BUS_WRITE_PBIT_COND 0x30 #define _3BUS_READ_DATA 0x0E #define _3BUS_READ_DATA_AND_PBIT 0x0C #define _3BUS_WRITE_ERROR_COUNTER 0x32 #define _3BUS_VERIFY_PSC 0x0D /* 2 BUS Addresses */ #define _2BUS_MAX_ADDRESS 255 #define _2BUS_MAX_PROTECTED_ADDRESS 31 #define _2BUS_ERROR_COUNTER_ADDRESS 0 #define _2BUS_PSC_CODE_1_ADDRESS 1 #define _2BUS_PSC_CODE_2_ADDRESS 2 #define _2BUS_PSC_CODE_3_ADDRESS 3 #define _2BUS_PSC_SIZE 3 /* 3 BUS Addresses */ #define _3BUS_MAX_ADDRESS 1020 /* 1KByte card - 3 bytes */ #define _3BUS_ERROR_COUNTER_ADDRESS 1021 #define _3BUS_PSC_CODE_1_ADDRESS 1022 #define _3BUS_PSC_CODE_2_ADDRESS 1023 #define _3BUS_PSC_SIZE 2 #define _23BUS_ATR_SIZE 4 #define _23BUS_COMMAND_SIZE 3 #endif asedriveiiie-3.7/asedriveiiie-serial/MemoryCards.c0000755000175000017500000010652611265303424022650 0ustar rousseaurousseau#include "Ase.h" /***************************************************************************** * *****************************************************************************/ #define MEM_CARD_READ_CHUNK_SIZE 29 #define MEM_CARD_WRITE_CHUNK_SIZE 23 /***************************************************************************** * *****************************************************************************/ static void AddSW1SW2 (int status, uchar* outBuf, int* outBufLen, uchar moreInfo) { switch (status) { case ASE_OK: outBuf[*outBufLen] = 0x90; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_COMM_ERROR: /* command failed */ case MEM_CARD_INVALID_PARAMETER: /* wrong file in select */ outBuf[*outBufLen] = 0x69; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_ILLEGAL_ADDRESS: outBuf[*outBufLen] = 0x6B; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_BAD_MODE: outBuf[*outBufLen] = 0x68; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_BLOCKED: outBuf[*outBufLen] = 0x69; (*outBufLen)++; outBuf[*outBufLen] = 0x83; (*outBufLen)++; break; case MEM_CARD_WRONG_LENGTH: outBuf[*outBufLen] = 0x67; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_WRONG_CLASS: outBuf[*outBufLen] = 0x6E; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_WRONG_INST: outBuf[*outBufLen] = 0x6D; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_FILE_NOT_FOUND: outBuf[*outBufLen] = 0x6A; (*outBufLen)++; outBuf[*outBufLen] = 0x82; (*outBufLen)++; break; case MEM_CARD_WRITE_FAILED: outBuf[*outBufLen] = 0x62; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_VERIFY_FAILED: outBuf[*outBufLen] = 0x63; (*outBufLen)++; outBuf[*outBufLen] = (0xC0 | moreInfo); (*outBufLen)++; break; default: outBuf[*outBufLen] = 0x6F; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; } } ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// // 2BUS cards functions ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// /***************************************************************************** * *****************************************************************************/ static int _2BUSExecInCommand (reader* globalData, uchar socket, uchar cmdCode, ushort address, uchar len, uchar* outBuffer, int *outBufLen) { int retVal, actual = 0; retVal = MemoryCardTransact(globalData, socket, 1, cmdCode, address, len, NULL, (char*)outBuffer, &actual); *outBufLen += actual; if (retVal < 0 || actual != len) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _2BUSExecOutCommand (reader* globalData, uchar socket, uchar cmdCode, ushort address, uchar* data, uchar len, uchar* outBuffer, int *outBufLen) { int retVal; retVal = MemoryCardTransact(globalData, socket, 0, cmdCode, address, len, data, (char*)outBuffer, outBufLen); if (retVal < 0) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static void ArrangeBitsIntoBytes(uchar* bitsBuff, uchar* buff, ushort address, int len) { int bytesLen = (address + len + 7) / 8; unsigned char buffIndex = 0; unsigned char bitsCount = 0; unsigned char i, j; for (i = 0; i < bytesLen; i++) { for (j = 0; j < 8; j++) { if (bitsCount++ < address) continue; buff[buffIndex++] = ((bitsBuff[i] >> j) & 0x1); if (buffIndex >= len) return; } } } /***************************************************************************** * *****************************************************************************/ static int _2BUSReadData(reader* globalData, uchar socket, ushort address, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0, actual; ushort maxAddress = 0; uchar cmdCode = 0, mode = globalData->cards[(int)socket].memCard.memType; uchar thisRead; ushort readLen = len; uchar bitsBuff[4]; /* for 2 bus cards, 32 protected bits */ uchar* readBuff = outBuffer; switch (mode) { case MEM_CARD_MAIN_MEM_MODE: if (address > _2BUS_MAX_ADDRESS) { retVal = MEM_CARD_ILLEGAL_ADDRESS; } else { maxAddress = _2BUS_MAX_ADDRESS; cmdCode = _2BUS_READ_DATA; } break; case MEM_CARD_PROT_MEM_MODE: if (address > _2BUS_MAX_PROTECTED_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _2BUS_MAX_PROTECTED_ADDRESS; cmdCode = _2BUS_READ_PBIT; /* address is DON'T CARE in this case */ readLen = 4; /* 4 bytes is 32 protections bits */ readBuff = bitsBuff; } break; default: retVal = MEM_CARD_BAD_MODE; break; } if (retVal == ASE_OK) { /* check if we are not trying to read too much */ if (/*mode != MEM_CARD_PROT_MEM_MODE &&*/ len > (maxAddress - address + 1)) retVal = MEM_CARD_WRONG_LENGTH; else { if (mode == MEM_CARD_PROT_MEM_MODE) retVal = _2BUSExecInCommand(globalData, socket, cmdCode, address, readLen, readBuff, &actual); else { while (counter < len && retVal == ASE_OK) { thisRead = (readLen > MEM_CARD_READ_CHUNK_SIZE ? MEM_CARD_READ_CHUNK_SIZE : readLen); retVal = _2BUSExecInCommand(globalData, socket, cmdCode, address + counter, thisRead, outBuffer + counter, outBufLen); counter += thisRead; readLen -= thisRead; } } if (retVal == ASE_OK) { *outBufLen = len; /* Put each bit into one memory byte at the user's buffer */ if (mode == MEM_CARD_PROT_MEM_MODE) ArrangeBitsIntoBytes(bitsBuff, outBuffer, address, *outBufLen); } } } /* if command failed, clean the output buffer */ if (retVal < 0) *outBufLen = 0; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _2BUSWriteData(reader* globalData, uchar socket, ushort address, uchar* data, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0, writeLen = len; ushort maxAddress = 0; uchar cmdCode = 0, thisWrite; uchar mode = globalData->cards[(int)socket].memCard.memType; switch (mode) { case MEM_CARD_MAIN_MEM_MODE: if (address > _2BUS_MAX_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _2BUS_MAX_ADDRESS; cmdCode = _2BUS_UPDATE_DATA; } break; case MEM_CARD_PROT_MEM_MODE: if (address > _2BUS_MAX_PROTECTED_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _2BUS_MAX_PROTECTED_ADDRESS; cmdCode = _2BUS_PROTECT_DATA_COND; } break; default: retVal = MEM_CARD_BAD_MODE; break; } if (retVal == ASE_OK) { /* check if we are not trying to write too much */ if (len > (maxAddress - address + 1)) { retVal = MEM_CARD_WRONG_LENGTH; } else { while (counter < len && retVal == ASE_OK) { thisWrite = (writeLen > MEM_CARD_WRITE_CHUNK_SIZE ? MEM_CARD_WRITE_CHUNK_SIZE : writeLen); retVal = _2BUSExecOutCommand(globalData, socket, cmdCode, address + counter, data + counter, thisWrite, outBuffer, outBufLen); counter += thisWrite; writeLen -= thisWrite; } } } if (retVal < 0) retVal = MEM_CARD_WRITE_FAILED; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _2BUSVerifyPSC(reader* globalData, uchar socket, uchar* password, int len, uchar* outBuffer, int *outBufLen) { uchar errorCounter[4]; uchar dataToWrite, i, attempts, newAttempts; int retVal = ASE_OK, actual; if (len != _2BUS_PSC_SIZE) { AddSW1SW2(MEM_CARD_INVALID_PARAMETER, outBuffer, outBufLen, 0); return retVal; } /* Read Error Counter - address has no effect in this command */ actual = 4; retVal = _2BUSExecInCommand(globalData, socket, _2BUS_READ_SECURITY_MEM, 0, 4, errorCounter, &actual); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Count number of erased bits */ attempts = 0; for (i = 1; i != 0x08; i <<= 1) { if (errorCounter[0] & i) attempts++; } /* Check if the card is already blocked */ if (attempts == 0) { AddSW1SW2(MEM_CARD_BLOCKED, outBuffer, outBufLen, 0); return ASE_OK; } /* find an erased bit - only 3 bits in counter */ for (i = 1; i != 0x08; i <<= 1) { if (errorCounter[0] & i) { dataToWrite = (~i & errorCounter[0]); break; } } /* Write the erased bit */ retVal = _2BUSExecOutCommand(globalData, socket, _2BUS_UPDATE_SECURITY_MEM, _2BUS_ERROR_COUNTER_ADDRESS, &dataToWrite, 1, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Verify PSC data */ retVal = _2BUSExecOutCommand(globalData, socket, _2BUS_COMPARE_VERIFICATION, _2BUS_PSC_CODE_1_ADDRESS, password, _2BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Try to clear the error counter */ dataToWrite = 0xff; retVal = _2BUSExecOutCommand(globalData, socket, _2BUS_UPDATE_SECURITY_MEM, _2BUS_ERROR_COUNTER_ADDRESS, &dataToWrite, 1, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Read Error Counter - address has no effect in this command */ actual = 4; retVal = _2BUSExecInCommand(globalData, socket, _2BUS_READ_SECURITY_MEM, 0, 4, errorCounter, &actual); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Count number of erased bits */ newAttempts = 0; for (i = 1; i != 0x08; i <<= 1) { if (errorCounter[0] & i) newAttempts++; } if (newAttempts < attempts) AddSW1SW2(MEM_CARD_VERIFY_FAILED, outBuffer, outBufLen, newAttempts); else AddSW1SW2(ASE_OK, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _2BUSChangePSC (reader* globalData, uchar socket, uchar* password, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK; if (len != 2 * _2BUS_PSC_SIZE) { AddSW1SW2(MEM_CARD_INVALID_PARAMETER, outBuffer, outBufLen, 0); return retVal; } retVal = _2BUSVerifyPSC(globalData, socket, password, _2BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { return ASE_OK; } if (*outBufLen >= 2 && outBuffer[*outBufLen - 2] == 0x90 && outBuffer[*outBufLen - 1] == 0x00) { /* verification has succeeded - try to change the password */ retVal = _2BUSExecOutCommand(globalData, socket, _2BUS_UPDATE_SECURITY_MEM, _2BUS_PSC_CODE_1_ADDRESS, password + 3, _2BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { *outBufLen = 0; /* replace the 9000 of the Verify command */ AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } } return ASE_OK; } ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// // 3BUS cards functions ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// /***************************************************************************** * *****************************************************************************/ static int _3BUSExecInCommand (reader* globalData, uchar socket, uchar mode, uchar cmdCode, ushort address, uchar len, uchar* outBuffer, int *outBufLen) { int retVal, actual = 0; if (mode == MEM_CARD_MAIN_MEM_MODE) retVal = MemoryCardTransact(globalData, socket, 1, cmdCode, address, len, NULL, (char*)outBuffer, &actual); else retVal = MemoryCardTransact(globalData, socket, 2, cmdCode, address, len, NULL, (char*)outBuffer, &actual); *outBufLen += actual; if (retVal < 0 || actual != len) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _3BUSExecOutCommand (reader* globalData, uchar socket, uchar cmdCode, ushort address, uchar* data, uchar len, uchar* outBuffer, int *outBufLen) { int retVal; retVal = MemoryCardTransact(globalData, socket, 0, cmdCode, address, len, data, (char*)outBuffer, outBufLen); if (retVal < 0) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _3BUSReadData(reader* globalData, uchar socket, ushort address, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0, actual, i; ushort maxAddress = 0; uchar cmdCode = 0, mode = globalData->cards[(int)socket].memCard.memType; uchar thisRead; ushort readLen = len; uchar temp[600]; switch (mode) { case MEM_CARD_MAIN_MEM_MODE: if (address > _3BUS_MAX_ADDRESS) { retVal = MEM_CARD_ILLEGAL_ADDRESS; } else { maxAddress = _3BUS_MAX_ADDRESS; cmdCode = _3BUS_READ_DATA; } break; case MEM_CARD_PROT_MEM_MODE: if (address > _3BUS_MAX_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _3BUS_MAX_ADDRESS; cmdCode = _3BUS_READ_DATA_AND_PBIT; readLen *= 2; /* we are reading 9 bits for each prot. bit stored in two bytes */ } break; default: retVal = MEM_CARD_BAD_MODE; break; } if (retVal == ASE_OK) { /* check if we are not trying to read too much */ if (len > (maxAddress - address + 1)) retVal = MEM_CARD_WRONG_LENGTH; else { if (mode == MEM_CARD_PROT_MEM_MODE) { int chunk = ((MEM_CARD_READ_CHUNK_SIZE % 2) ? (MEM_CARD_READ_CHUNK_SIZE - 1) : MEM_CARD_READ_CHUNK_SIZE); while (counter < 2 * len && retVal == ASE_OK) { thisRead = (readLen > chunk ? chunk : readLen); retVal = _3BUSExecInCommand(globalData, socket, mode, cmdCode, address + counter, thisRead, temp + counter, &actual); counter += thisRead; readLen -= thisRead; } /* remove the data bytes */ for (i = 0 ; i < len ; ++i) outBuffer[i] = temp[1 + i * 2]; } else { while (counter < len && retVal == ASE_OK) { thisRead = (readLen > MEM_CARD_READ_CHUNK_SIZE ? MEM_CARD_READ_CHUNK_SIZE : readLen); retVal = _3BUSExecInCommand(globalData, socket, mode, cmdCode, address + counter, thisRead, outBuffer + counter, outBufLen); counter += thisRead; readLen -= thisRead; } } *outBufLen = len; } } /* if command failed, clean the output buffer */ if (retVal < 0) *outBufLen = 0; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _3BUSWriteData(reader* globalData, uchar socket, ushort address, uchar* data, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0, writeLen = len; ushort maxAddress = 0; uchar cmdCode = 0, thisWrite; uchar mode = globalData->cards[(int)socket].memCard.memType; switch (mode) { case MEM_CARD_MAIN_MEM_MODE: if (address > _3BUS_MAX_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _3BUS_MAX_ADDRESS; cmdCode = _3BUS_UPDATE_DATA; } break; case MEM_CARD_PROT_MEM_MODE: if (address > _3BUS_MAX_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _3BUS_MAX_ADDRESS; cmdCode = _3BUS_WRITE_PBIT_COND; } break; default: retVal = MEM_CARD_BAD_MODE; break; } if (retVal == ASE_OK) { /* check if we are not trying to write too much */ if (len > (maxAddress - address + 1)) { retVal = MEM_CARD_WRONG_LENGTH; } else { while (counter < len && retVal == ASE_OK) { thisWrite = (writeLen > MEM_CARD_WRITE_CHUNK_SIZE ? MEM_CARD_WRITE_CHUNK_SIZE : writeLen); retVal = _3BUSExecOutCommand(globalData, socket, cmdCode, address + counter, data + counter, thisWrite, outBuffer, outBufLen); counter += thisWrite; writeLen -= thisWrite; } } } if (retVal < 0) retVal = MEM_CARD_WRITE_FAILED; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _3BUSVerifyPSC(reader* globalData, uchar socket, uchar* password, int len, uchar* outBuffer, int *outBufLen) { uchar errorCounter, dataToWrite, i, attempts, newAttempts; int retVal = ASE_OK, actual; if (len != _3BUS_PSC_SIZE) { AddSW1SW2(MEM_CARD_INVALID_PARAMETER, outBuffer, outBufLen, 0); return retVal; } /* Read Error Counter - address has no effect in this command */ retVal = _3BUSExecInCommand(globalData, socket, MEM_CARD_MAIN_MEM_MODE, _3BUS_READ_DATA, _3BUS_ERROR_COUNTER_ADDRESS, 1, &errorCounter, &actual); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Count number of erased bits */ attempts = 0; for (i = 1; i != 0; i <<= 1) { if (errorCounter & i) attempts++; } /* Check if the card is already blocked */ if (attempts == 0) { AddSW1SW2(MEM_CARD_BLOCKED, outBuffer, outBufLen, 0); return ASE_OK; } /* find an erased bit - only 3 bits in counter */ for (i = 1; i != 0; i <<= 1) { if (errorCounter & i) { dataToWrite = (~i & errorCounter); break; } } /* Write the erased bit */ retVal = _3BUSExecOutCommand(globalData, socket, _3BUS_WRITE_ERROR_COUNTER, _3BUS_ERROR_COUNTER_ADDRESS, &dataToWrite, 1, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Verify PSC data */ retVal = _3BUSExecOutCommand(globalData, socket, _3BUS_VERIFY_PSC, _3BUS_PSC_CODE_1_ADDRESS, password, _3BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Try to clear the error counter */ dataToWrite = 0xff; retVal = _3BUSExecOutCommand(globalData, socket, _3BUS_UPDATE_DATA, _3BUS_ERROR_COUNTER_ADDRESS, &dataToWrite, 1, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Read Error Counter - address has no effect in this command */ retVal = _3BUSExecInCommand(globalData, socket, MEM_CARD_MAIN_MEM_MODE, _3BUS_READ_DATA, _3BUS_ERROR_COUNTER_ADDRESS, 1, &errorCounter, &actual); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Count number of erased bits */ newAttempts = 0; for (i = 1; i != 0; i <<= 1) { if (errorCounter & i) newAttempts++; } if (newAttempts < attempts) AddSW1SW2(MEM_CARD_VERIFY_FAILED, outBuffer, outBufLen, newAttempts); else AddSW1SW2(ASE_OK, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _3BUSChangePSC (reader* globalData, uchar socket, uchar* password, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK; if (len != 2 * _3BUS_PSC_SIZE) { AddSW1SW2(MEM_CARD_INVALID_PARAMETER, outBuffer, outBufLen, 0); return retVal; } retVal = _3BUSVerifyPSC(globalData, socket, password, _3BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { return ASE_OK; } if (*outBufLen >= 2 && outBuffer[*outBufLen - 2] == 0x90 && outBuffer[*outBufLen - 1] == 0x00) { /* verification has succeeded - try to change the password */ retVal = _3BUSExecOutCommand(globalData, socket, _3BUS_UPDATE_DATA, _3BUS_PSC_CODE_1_ADDRESS, password + 2, _3BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { *outBufLen = 0; /* replace the 9000 of the Verify command */ AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } } return ASE_OK; } ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// // X/I2C cards functions ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// /***************************************************************************** * *****************************************************************************/ static int I2CExecInCommand (reader* globalData, uchar socket, uchar cmdCode, ushort address, uchar len, uchar* outBuffer, int *outBufLen) { int retVal, actual = 0; retVal = MemoryCardTransact(globalData, socket, 1, cmdCode, address, len, NULL, (char*)outBuffer, &actual); *outBufLen += actual; if (retVal < 0) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int I2CExecOutCommand (reader* globalData, uchar socket, uchar cmdCode, ushort address, uchar* data, uchar len, uchar* outBuffer, int *outBufLen) { int retVal; retVal = MemoryCardTransact(globalData, socket, 0, cmdCode, address, len, data, (char*)outBuffer, outBufLen); if (retVal < 0) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int I2CReadData(reader* globalData, uchar socket, ushort address, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0; uchar cmdCode = 0; uchar thisRead; ushort readLen = len; cmdCode = 0xA0; while (counter < len && retVal == ASE_OK) { thisRead = (readLen > MEM_CARD_READ_CHUNK_SIZE ? MEM_CARD_READ_CHUNK_SIZE : readLen); retVal = I2CExecInCommand(globalData, socket, cmdCode, address + counter, thisRead, outBuffer + counter, outBufLen); counter += thisRead; readLen -= thisRead; } if (retVal == ASE_OK) *outBufLen = len; else *outBufLen = 0; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int I2CWriteData(reader* globalData, uchar socket, ushort address, uchar* data, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0, writeLen = len; uchar cmdCode = 0, thisWrite; cmdCode = 0xA0; while (counter < len && retVal == ASE_OK) { thisWrite = (writeLen > MEM_CARD_WRITE_CHUNK_SIZE ? MEM_CARD_WRITE_CHUNK_SIZE : writeLen); retVal = I2CExecOutCommand(globalData, socket, cmdCode, address + counter, data + counter, thisWrite, outBuffer, outBufLen); counter += thisWrite; writeLen -= thisWrite; } if (retVal < 0) retVal = MEM_CARD_WRITE_FAILED; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int VerifyAPDUValidStructure(uchar* inBuf, int inBufLen) { int lc, dataLen; if (inBufLen <= 3) return MEM_CARD_ERROR_CMD_STRUCT; /* APDU case 1 */ if (inBufLen == 4) return ASE_OK; /* APDU case 2 */ if (inBufLen == 5) return ASE_OK; /* APDU case 3 + 4 (len > 5 here) */ lc = inBuf[4]; if (lc == 0x00) /* lc should be positive */ return MEM_CARD_ERROR_CMD_STRUCT; dataLen = inBufLen - 5; /* dataLen is equal to lc in case 3 and equal to lc+1 in case 4 */ if (dataLen != lc && dataLen != (lc + 1)) return MEM_CARD_ERROR_CMD_STRUCT; return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int SendMemoryCommand (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen) { uchar INS = inBuf[1]; ushort address; char cardType = globalData->cards[(int)socket].memCard.protocolType; int retVal = ASE_OK; *outBufLen = 0; /* check if the class is valid */ if (inBuf[0] != 0x00) { AddSW1SW2(MEM_CARD_WRONG_CLASS, outBuffer, outBufLen, 0); return retVal; } switch (INS) { case APDU_INS_SELECT: switch (cardType) { case PROTOCOL_MEM_2BUS: case PROTOCOL_MEM_3BUS: if (inBuf[5] == 0x3F && inBuf[6] == 0x00) globalData->cards[(int)socket].memCard.memType = MEM_CARD_MAIN_MEM_MODE; else if (inBuf[5] == 0x3F && inBuf[6] == 0x01) globalData->cards[(int)socket].memCard.memType = MEM_CARD_PROT_MEM_MODE; else AddSW1SW2(MEM_CARD_FILE_NOT_FOUND, outBuffer, outBufLen, 0); break; case PROTOCOL_MEM_I2C: case PROTOCOL_MEM_XI2C: if (inBuf[5] == 0x3F && inBuf[6] == 0x00) globalData->cards[(int)socket].memCard.memType = MEM_CARD_MAIN_MEM_MODE; else AddSW1SW2(MEM_CARD_FILE_NOT_FOUND, outBuffer, outBufLen, 0); break; default: AddSW1SW2(MEM_CARD_COMM_ERROR, outBuffer, outBufLen, 0); break; } break; case APDU_INS_VERIFY: switch (cardType) { case PROTOCOL_MEM_2BUS: retVal = _2BUSVerifyPSC(globalData, socket, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_3BUS: retVal = _3BUSVerifyPSC(globalData, socket, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_I2C: case PROTOCOL_MEM_XI2C: default: AddSW1SW2(MEM_CARD_COMM_ERROR, outBuffer, outBufLen, 0); break; } break; case APDU_INS_CHANGE_PASSWORD: switch (cardType) { case PROTOCOL_MEM_2BUS: retVal = _2BUSChangePSC(globalData, socket, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_3BUS: retVal = _3BUSChangePSC(globalData, socket, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_I2C: case PROTOCOL_MEM_XI2C: default: AddSW1SW2(MEM_CARD_COMM_ERROR, outBuffer, outBufLen, 0); break; } break; case APDU_INS_READ_BINARY: address = (inBuf[2] << 8) | inBuf[3]; switch (cardType) { case PROTOCOL_MEM_2BUS: /* if p3==0 then we should read 256 bytes */ retVal = _2BUSReadData(globalData, socket, address, (inBuf[4] == 0 ? 256 : inBuf[4]), outBuffer, outBufLen); break; case PROTOCOL_MEM_3BUS: retVal = _3BUSReadData(globalData, socket, address, (inBuf[4] == 0 ? 256 : inBuf[4]), outBuffer, outBufLen); break; case PROTOCOL_MEM_I2C: case PROTOCOL_MEM_XI2C: retVal = I2CReadData(globalData, socket, address, (inBuf[4] == 0 ? 256 : inBuf[4]), outBuffer, outBufLen); break; default: AddSW1SW2(MEM_CARD_COMM_ERROR, outBuffer, outBufLen, 0); break; } break; case APDU_INS_WRITE_BINARY: address = (inBuf[2] << 8) | inBuf[3]; switch (cardType) { case PROTOCOL_MEM_2BUS: retVal = _2BUSWriteData(globalData, socket, address, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_3BUS: retVal = _3BUSWriteData(globalData, socket, address, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_I2C: case PROTOCOL_MEM_XI2C: retVal = I2CWriteData(globalData, socket, address, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; default: AddSW1SW2(MEM_CARD_COMM_ERROR, outBuffer, outBufLen, 0); break; } break; default: AddSW1SW2(MEM_CARD_WRONG_INST, outBuffer, outBufLen, 0); break; } return retVal; } /***************************************************************************** * *****************************************************************************/ int MemoryCardCommand (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen) { int retVal; retVal = VerifyAPDUValidStructure(inBuf, inBufLen); if (retVal < 0) { return MEM_CARD_ERROR_CMD_STRUCT; /* no SW1/SW2 here */ } retVal = SendMemoryCommand(globalData, socket, inBuf, inBufLen, outBuffer, outBufLen); if (retVal < 0) { return retVal; } return ASE_OK; } asedriveiiie-3.7/asedriveiiie-serial/atr.c0000755000175000017500000003116511441413665021212 0ustar rousseaurousseau#include "Ase.h" /***************************************************************************** * *****************************************************************************/ #define ATR_INTERFACE_BYTE_TA 0 /* Interface byte TAi */ #define ATR_INTERFACE_BYTE_TB 1 /* Interface byte TBi */ #define ATR_INTERFACE_BYTE_TC 2 /* Interface byte TCi */ #define ATR_INTERFACE_BYTE_TD 3 /* Interface byte TDi */ /***************************************************************************** * *****************************************************************************/ static int fi[16] = { 372, 372, 558, 744, 1116, 1488, 1860, 1, 1, 512, 768, 1024, 1536, 2048, 1, 1 }; static int di[16] = { 1, 1, 2, 4, 8, 16, 32, 1, 12, 20, 1, 1, 1, 1, 1, 1 }; static long fs[16] = {4000000, 5000000, 6000000, 8000000, 12000000, 16000000, 20000000, 0, 0, 5000000, 7500000, 10000000, 15000000, 20000000, 0, 0}; /*static int num_ib[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };*/ /* number of interface bytes */ /***************************************************************************** * *****************************************************************************/ int ParseATR (reader* globalData, char socket, char data[], int len) { uchar TDi; int pointer = 0, pn = 0, i; ATR* atr = &(globalData->cards[(int)socket].atr); memset(atr, 0x00, sizeof(ATR)); /* Store T0 and TS */ if (len < 1) return ASE_ERROR_ATR; atr->TS = data[0]; atr->data[pointer] = atr->TS; if (atr->TS == 0x03) atr->TS = 0x3F; if ((atr->TS != 0x3B) && (atr->TS != 0x3F)) return ASE_ERROR_ATR; if (len < 2) return ASE_ERROR_ATR; atr->T0 = data[1]; TDi = atr->T0; pointer = 1; atr->data[pointer] = atr->T0; /* Store number of historical bytes */ atr->hbn = TDi & 0x0F; /* TCK is not present by default */ (atr->TCK).present = 0; /* Extract interface bytes */ while (1) { /* Check TAi is present */ if (TDi & 0x10) { pointer++; if (len < pointer) return ASE_ERROR_ATR; atr->ib[pn][ATR_INTERFACE_BYTE_TA].value = data[pointer]; atr->ib[pn][ATR_INTERFACE_BYTE_TA].present = 1; atr->data[pointer] = atr->ib[pn][ATR_INTERFACE_BYTE_TA].value; } else atr->ib[pn][ATR_INTERFACE_BYTE_TA].present = 0; /* Check TBi is present */ if (TDi & 0x20) { pointer++; if (len < pointer) return ASE_ERROR_ATR; atr->ib[pn][ATR_INTERFACE_BYTE_TB].value = data[pointer]; atr->ib[pn][ATR_INTERFACE_BYTE_TB].present = 1; atr->data[pointer] = atr->ib[pn][ATR_INTERFACE_BYTE_TB].value; } else atr->ib[pn][ATR_INTERFACE_BYTE_TB].present = 0; /* Check TCi is present */ if (TDi & 0x40) { pointer++; if (len < pointer) return ASE_ERROR_ATR; atr->ib[pn][ATR_INTERFACE_BYTE_TC].value = data[pointer]; atr->ib[pn][ATR_INTERFACE_BYTE_TC].present = 1; atr->data[pointer] = atr->ib[pn][ATR_INTERFACE_BYTE_TC].value; } else atr->ib[pn][ATR_INTERFACE_BYTE_TC].present = 0; /* Read TDi if present */ if (TDi & 0x80) { pointer++; if (len < pointer) return ASE_ERROR_ATR; atr->ib[pn][ATR_INTERFACE_BYTE_TD].value = data[pointer]; TDi = atr->ib[pn][ATR_INTERFACE_BYTE_TD].value; atr->ib[pn][ATR_INTERFACE_BYTE_TD].present = 1; atr->data[pointer] = atr->ib[pn][ATR_INTERFACE_BYTE_TD].value; (atr->TCK).present = ((TDi & 0x0F) != ATR_PROTOCOL_TYPE_T0); if (pn >= ATR_MAX_PROTOCOLS) return ASE_ERROR_ATR; pn++; } else { atr->ib[pn][ATR_INTERFACE_BYTE_TD].present = 0; break; } } /* Store number of protocols */ atr->pn = pn + 1; /* Store historical bytes */ for (i = 0; i < (atr->hbn); i++) { pointer++; if (len < pointer) return ASE_ERROR_ATR; atr->hb[i] = data[pointer]; atr->data[pointer] = atr->hb[i]; } /* Store TCK */ if ((atr->TCK).present) { pointer++; if (len < pointer) return ASE_ERROR_ATR; (atr->TCK).value = data[pointer]; atr->data[pointer] = atr->TCK.value; } atr->length = pointer + 1; return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int GetCurrentMode (ATR* atr) { /* TA2 */ if (atr->ib[1][ATR_INTERFACE_BYTE_TA].present) { return SPECIFIC_MODE; } else return NEGOTIABLE_MODE; } /***************************************************************************** * *****************************************************************************/ int CapableOfChangingMode (ATR* atr) { if (atr->ib[1][ATR_INTERFACE_BYTE_TA].present) /* TA2 */ return ((atr->ib[1][ATR_INTERFACE_BYTE_TA].value) & 0x80) == 0; else return 0; } /***************************************************************************** * *****************************************************************************/ uchar GetSpecificModeProtocol (ATR* atr) { if (GetCurrentMode(atr) == SPECIFIC_MODE) return ((atr->ib[1][ATR_INTERFACE_BYTE_TA].value) & 0x0F); else return UNKNOWN_PROTOCOL; } /***************************************************************************** * *****************************************************************************/ static int UseDefaultBaudrateInSpecificMode (ATR* atr) { if (GetCurrentMode(atr) == SPECIFIC_MODE) return ((atr->ib[1][ATR_INTERFACE_BYTE_TA].value) & 0x10); /* if b5=1 default */ else return 0; } /***************************************************************************** * *****************************************************************************/ float GetFToDFactor (int F, int D) { return (float)(fi[F]) / (float)(di[D]); } /***************************************************************************** * *****************************************************************************/ float GetDToFFactor (int F, int D) { return (float)(di[D]) / (float)(fi[F]); } /***************************************************************************** * *****************************************************************************/ uchar GetFi (ATR* atr) { if (UseDefaultBaudrateInSpecificMode(atr)) return 0; else if (atr->ib[0][ATR_INTERFACE_BYTE_TA].present) return (atr->ib[0][ATR_INTERFACE_BYTE_TA].value & 0xF0) >> 4; else return 1; /* 372 */ } /***************************************************************************** * *****************************************************************************/ long GetMaxFreq (ATR* atr) { return fs[GetFi(atr)]; } /***************************************************************************** * *****************************************************************************/ uchar GetDi (ATR* atr) { if (UseDefaultBaudrateInSpecificMode(atr)) return 1; else if (atr->ib[0][ATR_INTERFACE_BYTE_TA].present) return (atr->ib[0][ATR_INTERFACE_BYTE_TA].value & 0x0F); else return 1; /* 1 */ } /***************************************************************************** * *****************************************************************************/ uchar GetN (ATR* atr) { if (atr->ib[0][ATR_INTERFACE_BYTE_TC].present) return (atr->ib[0][ATR_INTERFACE_BYTE_TC].value); else return 0; } /***************************************************************************** * *****************************************************************************/ uchar GetWI (ATR* atr) { if (atr->ib[1][ATR_INTERFACE_BYTE_TC].present) return (atr->ib[1][ATR_INTERFACE_BYTE_TC].value); else return 10; } /***************************************************************************** * *****************************************************************************/ uchar GetFirstOfferedProtocol (ATR* atr) { /* only in NEGOTIABLE_MODE */ if (atr->ib[0][ATR_INTERFACE_BYTE_TD].present) return (atr->ib[0][ATR_INTERFACE_BYTE_TD].value) & 0x0F; else return ATR_PROTOCOL_TYPE_T0; } /***************************************************************************** * *****************************************************************************/ uchar GetT1IFSC (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=1 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T1) { /* return TA(i+1) if present */ if (atr->ib[i + 1][ATR_INTERFACE_BYTE_TA].present) return atr->ib[i + 1][ATR_INTERFACE_BYTE_TA].value; else return 32; /* default */ } } return 32; } /***************************************************************************** * *****************************************************************************/ uchar GetT1CWI (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=1 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T1) { /* return TA(i+1) if present */ if (atr->ib[i + 1][ATR_INTERFACE_BYTE_TB].present) return (atr->ib[i + 1][ATR_INTERFACE_BYTE_TB].value & 0x0F); else return 13; /* default */ } } return 13; } /***************************************************************************** * *****************************************************************************/ uchar GetT1BWI (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=1 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T1) { /* return TA(i+1) if present */ if (atr->ib[i + 1][ATR_INTERFACE_BYTE_TB].present) return ((atr->ib[i + 1][ATR_INTERFACE_BYTE_TB].value & 0xF0) >> 4); else return 4; /* default */ } } return 4; } /***************************************************************************** * *****************************************************************************/ uchar GetT1EDC (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=1 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T1) { /* return TA(i+1) if present */ if (atr->ib[i + 1][ATR_INTERFACE_BYTE_TC].present) return (atr->ib[i + 1][ATR_INTERFACE_BYTE_TC].value & 0x01); else return 0; /* default - LRC */ } } return 0; } /***************************************************************************** * *****************************************************************************/ int IsT1Available (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=1 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T1) { return 1; } } return 0; } /***************************************************************************** * *****************************************************************************/ uchar GetClassIndicator (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=15 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T15) { /* return TA(i+1) if present */ if (atr->ib[i + 1][ATR_INTERFACE_BYTE_TA].present) return (atr->ib[i + 1][ATR_INTERFACE_BYTE_TA].value & 0x3F); else return 1; /* default - only class A (5V) supported */ } } return 1; /* default - only class A (5V) supported */ } asedriveiiie-3.7/asedriveiiie-serial/LICENSE0000755000175000017500000000257711265303424021265 0ustar rousseaurousseauCopyright (c) 2002 Athena Smartcard Solutions All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. asedriveiiie-3.7/asedriveiiie-serial/DriverIO.c0000755000175000017500000001410411265303424022074 0ustar rousseaurousseau#include "Ase.h" /***************************************************************************** * *****************************************************************************/ /* reader status */ #define STS_PID_OK 0x00 #define STS_PID_ERROR 0x01 #define STS_CNT_ERROR 0x02 #define STS_TRUNC_ERROR 0x03 #define STS_LEN_ERROR 0x04 #define STS_UNKNOWN_CMD_ERROR 0x05 #define STS_TIMEOUT_ERROR 0x06 #define STS_CS_ERROR 0x07 #define STS_INVALID_PARAM_ERROR 0x08 #define STS_CMD_FAILED_ERROR 0x09 #define STS_NO_CARD_ERROR 0x0A #define STS_CARD_NOT_POWERED_ERROR 0x0B #define STS_COMM_ERROR 0x0C #define STS_EXTRA_WAITING_TIME 0x0D #define STS_RETRY_FAILED 0x0E /* Card events */ #define EID_CARD1_NOT_PRESENT 0x01 #define EID_CARD1_INSERTED 0x02 #define EID_CARD2_NOT_PRESENT 0x05 #define EID_CARD2_INSERTED 0x06 #define EID_CARD3_NOT_PRESENT 0x09 #define EID_CARD3_INSERTED 0x0A #define EID_CARD4_NOT_PRESENT 0x0D #define EID_CARD4_INSERTED 0x0E /***************************************************************************** * *****************************************************************************/ /* returns 0 if no error, status code otherwise */ int parseStatus (uchar ackByte) { int retVal; if ((ackByte & 0xF0) != 0x20) retVal = ASE_READER_INVALID_STATUS_BYTE; else { ackByte &= 0x0F; switch (ackByte) { case STS_PID_ERROR: retVal = ASE_READER_PID_ERROR; break; case STS_CNT_ERROR: retVal = ASE_READER_CNT_ERROR; break; case STS_TRUNC_ERROR: retVal = ASE_READER_TRUNC_ERROR; break; case STS_LEN_ERROR: retVal = ASE_READER_LEN_ERROR; break; case STS_UNKNOWN_CMD_ERROR: retVal = ASE_READER_UNKNOWN_CMD_ERROR; break; case STS_TIMEOUT_ERROR: retVal = ASE_READER_TIMEOUT_ERROR; break; case STS_CS_ERROR: retVal = ASE_READER_CS_ERROR; break; case STS_INVALID_PARAM_ERROR: retVal = ASE_READER_INVALID_PARAM_ERROR; break; case STS_CMD_FAILED_ERROR: retVal = ASE_READER_CMD_FAILED_ERROR; break; case STS_NO_CARD_ERROR: retVal = ASE_READER_NO_CARD_ERROR; break; case STS_CARD_NOT_POWERED_ERROR: retVal = ASE_READER_CARD_NOT_POWERED_ERROR; break; case STS_COMM_ERROR: retVal = ASE_READER_COMM_ERROR; break; case STS_EXTRA_WAITING_TIME: retVal = ASE_READER_EXTRA_WAITING_TIME; break; case STS_RETRY_FAILED: retVal = ASE_READER_RETRY_FAILED; break; default: retVal = 0; break; } } #ifdef ASE_DEBUG if (retVal) syslog(LOG_INFO, "parseStatus: Error! status = %d\n", ackByte); #endif return retVal; } /***************************************************************************** * *****************************************************************************/ int isEvent (uchar event) { if (event == EID_CARD1_NOT_PRESENT || event == EID_CARD2_NOT_PRESENT || event == EID_CARD1_INSERTED || event == EID_CARD2_INSERTED || event == EID_CARD3_NOT_PRESENT || event == EID_CARD4_NOT_PRESENT || event == EID_CARD3_INSERTED || event == EID_CARD4_INSERTED) return 1; return 0; } /***************************************************************************** * *****************************************************************************/ /* returns 0 if not an error, error code otherwise. change global data status if neccesary */ int parseEvent (reader* globalData, char socket, uchar event) { uchar skn; #ifdef ASE_DEBUG syslog(LOG_INFO, "=============> Event = 0x%x%x <===============\n", PRINT_CHAR(event)); #endif skn = (event & 0x0C) >> 2; globalData->cards[skn].status = ((event & 0x01) ? 0 : 1); /* if the card is out and the socket number is the one we use, return an error indication */ if ((event & 0x01) && (skn == socket)) return ASE_READER_NO_CARD_ERROR; return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int writeToReader (reader* globalData, char* data, int len, int* actual) { *actual = IO_Write(globalData, len, (unsigned char*)data); #ifdef ASE_DEBUG syslog(LOG_INFO, "writeToReader: wrote %d bytes. data = ", *actual); int i; for (i = 0 ; i < *actual ; ++i) syslog(LOG_INFO, "0x%x%x ", PRINT_CHAR(data[i])); syslog(LOG_INFO, "\n"); #endif if (*actual != len) { #ifdef ASE_DEBUG syslog(LOG_INFO, "writeToReader - Error! len = %d, actual = %d\n", len, *actual); #endif return ASE_ERROR_WRITE; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ /* returns 0 on success; negative value otherwise */ int readResponse (reader* globalData, char socket, int num, char* outBuf, int* outBufLen, unsigned long timeout/*, int startOfResponse*/) { int len; int remain = num; *outBufLen = 0; len = IO_Read(globalData, timeout, remain, (unsigned char*)(&(outBuf[*outBufLen]))); (*outBufLen) = (*outBufLen) + len; if (num == *outBufLen) /* all data arrived */ return ASE_OK; else { /* part of the data is missing */ #ifdef ASE_DEBUG syslog(LOG_INFO, "readResponse - Error! read only %d out of %d bytes\n", *outBufLen, num); #endif return ASE_ERROR_DATA_INCOMPLETE; } } asedriveiiie-3.7/asedriveiiie-serial/CommandTypes.c0000755000175000017500000002607511441415015023022 0ustar rousseaurousseau#include "Ase.h" /* ASE reader generic command types */ #define ASE_LONG_RESPONSE_PID 0x90 #define ASE_RESPONSE_PID 0x10 #define ASE_ACK_PID 0x20 #define ASE_LONG_RESPONSE_WITH_STATUS_PID 0xF0 #define ASE_RESPONSE_WITH_STATUS_PID 0x70 /***************************************************************************** * *****************************************************************************/ //#define ASE_PACKET_TYPE(pid, cnt, dst) (pid | cnt << 2 | dst) #define ASE_PACKET_TYPE(pid, cnt, dst) (pid | dst) /***************************************************************************** * *****************************************************************************/ /* returns 0 on success, negative number otherwise */ int checkValidity (int retVal, int len, int actual, const char* message) { if (retVal < 0 || actual != len) { #ifdef ASE_DEBUG syslog(LOG_INFO, "%s Error = %d\n", message, retVal); #endif return retVal; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static void cleanResponseBuffer (reader* globalData) { IO_CleanReadBuffer(globalData); } /***************************************************************************** * *****************************************************************************/ /* returns 0 on success, negative number otherwise outBuf should be large enough to contain the close response */ int sendCloseResponseCommand (reader* globalData, char socket, char* cmd, int len, char* outBuf, int* outBufLen, char ignoreEvents) { int retVal, actual, i, readLen, retryTimes = 5, withStatus = 0; uchar oneByte, cs, readcs; long cwt = (globalData->cards[(int)socket].cwt > 0 ? globalData->cards[(int)socket].cwt : 1000); /* send the command */ retVal = writeToReader(globalData, cmd, len, &actual); if (checkValidity(retVal, len, actual, "sendCloseResponseCommand - Error! in command write.\n")) { cleanResponseBuffer(globalData); return retVal; } /* read the close response */ /* set the timeout for the packet header */ cwt = MAX(cwt * 260, globalData->cards[(int)socket].bwt); cwt += 200000; // delta of 0.2 seconds /* read packet header and verify it's ok */ retVal = readResponse(globalData, socket, 1, (char*)(&oneByte), &actual, cwt); if (checkValidity(retVal, 1, actual, "sendCloseResponseCommand - Error! in packet header read.\n")) { cleanResponseBuffer(globalData); return retVal; } /* loop until we get the start of a response or an error has occured */ while (oneByte != ASE_LONG_RESPONSE_PID && oneByte != ASE_RESPONSE_PID && oneByte != ASE_RESPONSE_WITH_STATUS_PID && oneByte != ASE_LONG_RESPONSE_WITH_STATUS_PID && retryTimes) { /* check if it's an acknowledgment */ if (oneByte & ASE_ACK_PID) { if (parseStatus(oneByte) != ASE_READER_EXTRA_WAITING_TIME) { #ifdef ASE_DEBUG syslog(LOG_INFO, "sendCloseResponseCommand - Status 0x%x%x.\n", (oneByte & 0xF0) >> 4, oneByte & 0x0F); #endif cleanResponseBuffer(globalData); return parseStatus(oneByte); } else retryTimes = 5; } /* check if it's an event */ else if (isEvent(oneByte)) { /* this is an event and it's concerning the current card */ parseEvent(globalData, socket, oneByte); #ifdef ASE_DEBUG syslog(LOG_INFO, "sendCloseResponseCommand - Event 0x%x%x.\n", (oneByte & 0xF0) >> 4, oneByte & 0x0F); #endif retryTimes = 5; } /* this must be an error -> send a retry command */ else { char cmdTmp[4]; cmdTmp[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmdTmp[1] = 0x44; cmdTmp[2] = 0x0; cmdTmp[3] = cmdTmp[0] ^ cmdTmp[1] ^ cmdTmp[2]; retVal = writeToReader(globalData, cmdTmp, 4, &actual); if (checkValidity(retVal, 4, actual, "sendControlCommand - Error! in command write.\n")) { cleanResponseBuffer(globalData); return retVal; } // retryTimes = 5; } /* read packet header and verify it's ok */ retVal = readResponse(globalData, socket, 1, (char*)(&oneByte), &actual, cwt); if (checkValidity(retVal, 1, actual, "sendCloseResponseCommand - Error! in packet header read.\n")) { cleanResponseBuffer(globalData); return retVal; } retryTimes--; } if (retryTimes == 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "sendCloseResponseCommand - Error! retryTimes is 0.\n"); #endif return ASE_ERROR_RESEND_COMMAND; } cs = oneByte; /* set the timeout for the length */ cwt = 100000; // 0.1 sec /* check if a status byte appears at the end of the response */ if (oneByte == ASE_LONG_RESPONSE_WITH_STATUS_PID || oneByte == ASE_RESPONSE_WITH_STATUS_PID) withStatus = 1; /* this is a response header, so read its length */ if (oneByte == ASE_LONG_RESPONSE_PID || oneByte == ASE_LONG_RESPONSE_WITH_STATUS_PID) { /* long response */ retVal = readResponse(globalData, socket, 1, (char*)(&oneByte), &actual, cwt); if (checkValidity(retVal, 1, actual, "sendCloseResponseCommand - Error! in packet header read.\n")) { cleanResponseBuffer(globalData); return retVal; } cs ^= oneByte; readLen = (oneByte << 8); readLen &= 0xFF00; retVal = readResponse(globalData, socket, 1, (char*)(&oneByte), &actual, cwt); if (checkValidity(retVal, 1, actual, "sendCloseResponseCommand - Error! in packet header read.\n")) { cleanResponseBuffer(globalData); return retVal; } cs ^= oneByte; readLen |= (oneByte & 0xFF); } else { /* short response */ retVal = readResponse(globalData, socket, 1, (char*)(&oneByte), &actual, cwt); if (checkValidity(retVal, 1, actual, "sendCloseResponseCommand - Error! in packet header read.\n")) { cleanResponseBuffer(globalData); return retVal; } cs ^= oneByte; readLen = oneByte; } /* set the timeout for the data */ cwt = 100000 * (readLen + 1); // 0.1 sec per byte /***!!!!!!!!!!!!!!!!!!!!***************************************/ /* read data + checksum */ retVal = readResponse(globalData, socket, readLen + 1, outBuf, outBufLen, cwt); if (checkValidity(retVal, readLen + 1, *outBufLen, "sendCloseResponseCommand - Error! in data read.\n")) { cleanResponseBuffer(globalData); return retVal; } readcs = outBuf[*outBufLen - 1]; (*outBufLen)--; for (i = 0 ; i < *outBufLen ; ++i) cs ^= outBuf[i]; /* check the status byte provided */ if (withStatus) { /* remove the last byte of outBuf and check the status */ (*outBufLen)--; if (outBuf[*outBufLen] != ASE_ACK_PID) { /* read the checksum */ /*retVal = readResponse(globalData, socket, 1, &oneByte, &actual, cwt);*/ /* return error according to the status byte */ cleanResponseBuffer(globalData); return parseStatus(outBuf[*outBufLen]); } } /* read the checksum */ /* retVal = readResponse(globalData, socket, 1, &oneByte, &actual); if (checkValidity(retVal, 1, actual, "sendCloseResponseCommand - Error! in checksum read.\n")) { cleanResponseBuffer(globalData); return retVal; } */ if (cs != readcs) { #ifdef ASE_DEBUG syslog(LOG_INFO, "sendCloseResponseCommand - Error! invalid checksum.\n"); #endif cleanResponseBuffer(globalData); return ASE_ERROR_CHECKSUM; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ /* returns 0 on success, negative number otherwise outBuf will contain the ACK/NAK byte sent as response */ int sendControlCommand (reader* globalData, char socket, char* cmd, int len, char* outBuf, int* outBufLen, char ignoreEvents) { int retVal, actual, retryTimes = 5; unsigned long cwt = (globalData->cards[(int)socket].cwt > 0 ? globalData->cards[(int)socket].cwt : 1000); #ifdef ASE_DEBUG uchar oneByte; #endif /* send the command */ retVal = writeToReader(globalData, cmd, len, &actual); if (checkValidity(retVal, len, actual, "sendControlCommand - Error! in command write.\n")) { cleanResponseBuffer(globalData); return retVal; } /* read the Ack control byte */ /* set the timeout for the packet header */ // cwt = MAX(cwt * 260, globalData->cards[(int)socket].bwt); cwt = 3000000; // 3 sec retVal = readResponse(globalData, socket, 1, outBuf, outBufLen, cwt); if (checkValidity(retVal, 1, *outBufLen, "sendControlCommand - Error! in ack read.\n")) { cleanResponseBuffer(globalData); return retVal; } /* loop until we get an OK acknowledgement */ while (outBuf[0] != ASE_ACK_PID && retryTimes) { /* check if it's an acknowledgment */ if (outBuf[0] & ASE_ACK_PID) { if (parseStatus(outBuf[0]) != ASE_READER_EXTRA_WAITING_TIME) { #ifdef ASE_DEBUG syslog(LOG_INFO, "sendControlCommand - Error! Status 0x%x%x.\n", (oneByte & 0xF0) >> 4, oneByte & 0x0F); #endif cleanResponseBuffer(globalData); return parseStatus(outBuf[0]); } else retryTimes = 5; } /* check if it's an event */ else if (isEvent((uchar)(outBuf[0]))) { parseEvent(globalData, socket, outBuf[0]); retryTimes = 5; } /* this must be an error -> send a retry command */ else { char cmdTmp[4]; cmdTmp[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmdTmp[1] = 0x44; cmdTmp[2] = 0x0; cmdTmp[3] = cmdTmp[0] ^ cmdTmp[1] ^ cmdTmp[2]; retVal = writeToReader(globalData, cmdTmp, 4, &actual); if (checkValidity(retVal, 4, actual, "sendControlCommand - Error! in command write.\n")) { cleanResponseBuffer(globalData); return retVal; } // retryTimes = 5; } /* read packet header and verify it's ok */ retVal = readResponse(globalData, socket, 1, outBuf, outBufLen, cwt); if (checkValidity(retVal, 1, *outBufLen, "sendControlCommand - Error! in ack read.\n")) { cleanResponseBuffer(globalData); return retVal; } retryTimes--; } return ASE_OK; } asedriveiiie-3.7/asedriveiiie-serial/Ase.h0000755000175000017500000002504011441413733021130 0ustar rousseaurousseau#ifndef __ASE_H #define __ASE_H #include #include #include #include #include #include #include #include #include //#include #include #include #include #include //#include #include #include "LinuxDefines.h" #include "atr.h" #include "T1Protocol.h" #include "MemoryCards.h" //#define ASE_DEBUG /***************************************************************************** * IOCTL *****************************************************************************/ #define ASE_IOCTL_CLASS 0xF0 #define ASE_IOCTL_XI2C_INS 0xA0 #define ASE_IOCTL_CLOCK_INS 0xB0 // for sending raw reader ioctls #define ASE_IOCTL_RAW_CLASS 0xFF #define ASE_IOCTL_RAW_INS 0xA0 /***************************************************************************** * *****************************************************************************/ #define LEFT_NIBBLE(c) ((c & 0xF0) >> 4) #define RIGHT_NIBBLE(c) (c & 0x0F) #define PRINT_CHAR(c) LEFT_NIBBLE(c), RIGHT_NIBBLE(c) #ifndef MIN #define MIN(a, b) (a > b ? b : a) #endif #ifndef MAX #define MAX(a, b) (a > b ? a : b) #endif #define ASE_READER_ETU_DELTA 150 /***************************************************************************** * *****************************************************************************/ #define BULK_BUFFER_SIZE 300 #define EVENT_BUFFER_SIZE 16 #define RESPONSE_BUFFER_SIZE 4096 #define MAX_SOCKET_NUM 4 #define ASE_DATA_MEMORY_SIZE 64 #define READER_FIDI_TABLE_SIZE 100 #define BUFFER_SIZE 8192 /***************************************************************************** * *****************************************************************************/ struct card_params { uchar protocol; uchar N; uchar CWT[3]; uchar BWT[3]; uchar A; uchar B; uchar freq; float fTod; }; typedef struct { int status; /* 0 - absent, 1 - inserted, 2 - powered on */ int ceei; ATR atr; long cwt; /* max time in microseconds to wait between characters */ long bwt; /* max time in microseconds to wait to first character (in T=0, equals to cwt) */ T1Protocol T1; struct card_params cardParams; uchar FiDi; char activeProtocol; MemCard memCard; } card; typedef struct { HANDLE handle; unsigned char baud; unsigned char bits; int stopbits; char parity; long blocktime; } ioport; typedef struct { // int fd; ioport io; char dataMemory[ASE_DATA_MEMORY_SIZE]; int readerStarted; /* 1 - started, 0 - not yet */ char commandCounter; card cards[MAX_SOCKET_NUM]; pthread_mutex_t semaphore; } reader; /***************************************************************************** * *****************************************************************************/ /* return codes */ #define ASE_OK 0 #define ASE_ERROR_DATA_INCOMPLETE -1 #define ASE_ERROR_IOCTL_RESPONSE -2 #define ASE_ERROR_IOCTL_EVENT -3 #define ASE_ERROR_READ -4 #define ASE_ERROR_WRITE -5 #define ASE_ERROR_TIMEOUT -6 #define ASE_ERROR_COMMAND -7 #define ASE_ERROR_CHECKSUM -8 #define ASE_ERROR_RESPONSE_INCORRECT -9 #define ASE_ERROR_OVERHEATING -10 #define ASE_ERROR_ATR -11 #define ASE_ERROR_PARITY -12 #define ASE_ERROR_FIFO_OVERRUN -13 #define ASE_ERROR_FRAMING -14 #define ASE_ERROR_EARLY_ANSWER -15 #define ASE_ERROR_RESEND_COMMAND -16 #define ASE_READER_PID_ERROR -110 #define ASE_READER_CNT_ERROR -111 #define ASE_READER_TRUNC_ERROR -112 #define ASE_READER_LEN_ERROR -113 #define ASE_READER_UNKNOWN_CMD_ERROR -114 #define ASE_READER_TIMEOUT_ERROR -115 #define ASE_READER_CS_ERROR -116 #define ASE_READER_INVALID_PARAM_ERROR -117 #define ASE_READER_CMD_FAILED_ERROR -118 #define ASE_READER_NO_CARD_ERROR -119 #define ASE_READER_CARD_NOT_POWERED_ERROR -120 #define ASE_READER_COMM_ERROR -121 #define ASE_READER_EXTRA_WAITING_TIME -122 #define ASE_READER_NOT_CPU_CARD -123 #define ASE_READER_NO_MATCHING_PARAMS -124 #define ASE_READER_CARD_REJECTED -125 #define ASE_READER_INVALID_STATUS_BYTE -126 #define ASE_READER_RETRY_FAILED -127 /***************************************************************************** * externs *****************************************************************************/ extern int ParseATR (reader* globalData, char socket, char data[], int len); extern int GetCurrentMode (ATR* atr); extern int CapableOfChangingMode (ATR* atr); extern uchar GetSpecificModeProtocol (ATR* atr); extern uchar GetFi (ATR* atr); extern uchar GetDi (ATR* atr); extern uchar GetN (ATR* atr); extern uchar GetWI (ATR* atr); extern long GetMaxFreq (ATR* atr); extern uchar GetFirstOfferedProtocol (ATR* atr); extern float GetFToDFactor (int F, int D); extern float GetDToFFactor (int F, int D); extern uchar GetT1IFSC (ATR* atr); extern uchar GetT1CWI (ATR* atr); extern uchar GetT1BWI (ATR* atr); extern uchar GetT1EDC (ATR* atr); extern int IsT1Available (ATR* atr); extern uchar GetClassIndicator (ATR* atr); extern int parseStatus (uchar ackByte); extern int isEvent (uchar event); extern int parseEvent (reader* globalData, char socket, uchar event); extern int readResponse (reader* globalData, char socket, int num, char* outBuf, int* outBufLen, unsigned long timeout/*, int startOfResponse*/); extern int writeToReader (reader* globalData, char* data, int len, int* actual); extern int checkValidity (int retVal, int len, int actual, const char* message); extern int sendCloseResponseCommand (reader* globalData, char socket, char* cmd, int len, char* outBuf, int* outBufLen, char ignoreEvents); extern int sendControlCommand (reader* globalData, char socket, char* cmd, int len, char* outBuf, int* outBufLen, char ignoreEvents); extern int cardCommandInit (reader* globalData, char socket, char needToBePoweredOn); extern int readerCommandInit (reader* globalData, char needToBeStarted); extern int ReaderStartup (reader* globalData, char* response, int* len); extern int ReaderFinish (reader* globalData); extern int GetStatus (reader* globalData, char* response, int* len); extern int SetCardParameters (reader* globalData, char socket, struct card_params params); extern int CardPowerOn (reader* globalData, char socket, uchar cardType, uchar voltage); extern int CPUCardReset (reader* globalData, char socket); extern int CardPowerOff (reader* globalData, char socket); extern int ChangeLedState (reader* globalData, char on); extern int PPSTransact (reader* globalData, char socket, char* buffer, int len, char* outBuf, int* outBufLen); extern int CardCommand (reader* globalData, char socket, char command, uchar* buffer, int len, uchar* outBuf, int* outBufLen); /* extern int T0CPUCardTransact (reader* globalData, char socket, char* buffer, int len, char* outBuf, int* outBufLen, openResponseProccessor orp, unsigned long arg); */ extern int T1CPUCardTransact (reader* globalData, char socket, char* buffer, int len, char* outBuf, int* outBufLen); extern int MemoryCardTransact (reader* globalData, char socket, char cmdType, uchar command, ushort address, uchar len, uchar* data, char* outBuf, int* outBufLen); /* the protocol is not NULL if a PPS is required to switch to it.*/ extern int InitCard (reader* globalData, char socket, char coldReset, char* protocol); /* outBuf will contain the SW1/SW2 as well */ extern int T0Read (reader* globalData, char socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen); extern int T0Write (reader* globalData, char socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen); extern int T1InitProtocol (reader* globalData, char socket, char setIFSD); extern int T1Command (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen); extern int MemoryCardCommand (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen); extern int SendIOCTL (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen); bool IO_InitializePort( /* Initialize the card reader port. */ reader* globalData, int baud, /* Baud rate to set port to */ int bits, /* Bytesize: 5, 6, 7 or 8 */ char par, /* Parity: 'E' even, 'O' odd, 'N' none */ char* port /* Name of port, or (char *)0L for dialog */ ); int IO_Read( /* Read up to 256 bytes from the port */ reader* globalData, unsigned long timeout, int readsize, /* Number of bytes to read */ unsigned char *response /* Bytes read */ ); int IO_Write( reader* globalData, int writesize, unsigned char* c /* Bytes to be written */ ); bool /* True for success, false otherwise */ IO_Close( /* On a Mac, gotta close the port */ reader* globalData ); HANDLE IO_ReturnHandle( /* Returns the current handle */ reader* globalData ); int IO_UpdateReturnBlock( /* Returns the current blocking time */ reader* globalData, int blocktime /* The updated blocking time */ ); int IO_ReturnBaudRate( /* Return the current baudrate */ reader* globalData ); char IO_ReturnParity( reader* globalData /* Return the current parity */ ); char IO_UpdateParity( reader* globalData, char parity ); int IO_ReturnStopBits( reader* globalData /* Return stop bits */ ); int IO_UpdateStopBits( reader* globalData, int stopbits ); bool /* True for sucess, false otherwise */ IO_FlushBuffer( /* Flush buffer to card reader */ reader* globalData ); void IO_CleanReadBuffer( /* Removes all data arrived but not read yet */ reader* globalData ); #endif asedriveiiie-3.7/asedriveiiie-serial/T1Protocol.c0000755000175000017500000006563211441364417022440 0ustar rousseaurousseau#include "Ase.h" static int SendSBlock (reader* globalData, uchar socket, uchar control, uchar data); /***************************************************************************** * *****************************************************************************/ static uchar T1BlockGetType (T1Block* block) { if ((block->data[1] & 0x80) == T1_BLOCK_I) return T1_BLOCK_I; return (block->data[1] & 0xC0); } static int T1ErrorFreeRBlock (T1Block* block) { return ((block->data[1] & 0x0F) == 0); } static uchar T1BlockGetNS (T1Block* block) { return ((block->data[1] >> 6) & 0x01); } static uchar T1BlockGetMore (T1Block* block) { return ((block->data[1] >> 5) & 0x01); } static uchar T1BlockGetNR (T1Block* block) { return ((block->data[1] >> 4) & 0x01); } static int T1BlockGetLen (T1Block* block) { return block->data[2]; } static uchar* T1BlockGetInf (T1Block* block) { if (block->len < 5) return NULL; return block->data + 3; } /***************************************************************************** * *****************************************************************************/ static void LRC(char* data, int len, uchar* edc) { int i; *edc = 0; for (i = 0 ; i < len ; ++i) (*edc) ^= data[i]; } /***************************************************************************** * *****************************************************************************/ static void CRC(char* data, int len, uchar* edc1, uchar* edc2) { int i; unsigned short crc = 0xFFFF, temp, quick; for (i = 0 ; i < len ; ++i) { temp = (crc >> 8) ^ data[len]; crc <<= 8; quick = temp ^ (temp >> 4); crc ^= quick; quick <<= 5; crc ^= quick; quick <<= 7; crc ^= quick; } *edc1 = (crc >> 8) & 0x00FF; *edc2 = crc & 0x00FF; } /***************************************************************************** * *****************************************************************************/ int T1InitProtocol (reader* globalData, char socket, char setIFSD) { int retVal; ATR *atr = &(globalData->cards[(int)socket].atr); /* set IFSC */ globalData->cards[(int)socket].T1.ifsc = MIN(GetT1IFSC(atr), ATHENA_IFSC_MAX_SIZE); /* set EDC */ globalData->cards[(int)socket].T1.edc = (GetT1EDC(atr) == 0 ? 1 : 0); /* set counters */ globalData->cards[(int)socket].T1.ns = 1; globalData->cards[(int)socket].T1.nsCard = 0; #ifdef ASE_DEBUG syslog(LOG_INFO, "T1InitProtocol: ifsc = %d, edc = %d\n", globalData->cards[(int)socket].T1.ifsc, globalData->cards[(int)socket].T1.edc); #endif // Try to set the maximal ifsd - if it fails, use the default // for (i = 0 ; i < 3 ; ++i) { if (setIFSD) { T1Block* recBlock = &(globalData->cards[(int)socket].T1.recBlock); retVal = SendSBlock(globalData, socket, T1_BLOCK_S_IFS_REQ, 254/*globalData->cards[(int)socket].T1.ifsc*/); if (retVal == ASE_OK && T1BlockGetLen(recBlock) > 0x1) { // check Correct len // check that S(IFS response) has been received if (recBlock->data[1] == T1_BLOCK_S_IFS_RES) { #ifdef ASE_DEBUG printf("<<<<<<<<< RECEIVING S(IFS response)\n"); #endif // break; } } } return PROTOCOL_T1_OK; } /***************************************************************************** * *****************************************************************************/ static int T1CommandResponseProccessor(reader* globalData, char socket, char* response, int len, char* outBuf, int* outBufLen) { int i; uchar readByte, edc1, edc2, edc11, edc22; *outBufLen = 0; if (len < 3) return PROTOCOL_T1_ERROR; readByte = response[0]; outBuf[*outBufLen] = readByte; (*outBufLen)++; readByte = response[1]; outBuf[*outBufLen] = readByte; (*outBufLen)++; readByte = response[2]; outBuf[*outBufLen] = readByte; (*outBufLen)++; /* check that LEN doesnt exceed 254 */ if (readByte > T1_BLOCK_INF_MAX_SIZE || len < (readByte + 3)) { return PROTOCOL_T1_ERROR; } /* read the information field */ if (readByte > 0) { for (i = 0 ; i < readByte ; ++i) outBuf[3 + i] = response[3 + i]; (*outBufLen) += readByte; } /* read the EDC */ if (globalData->cards[(int)socket].T1.edc == 1) { /* LRC */ LRC(outBuf, *outBufLen, &edc11); if (len < (readByte + 4)) { return PROTOCOL_T1_ERROR; } edc1 = response[readByte + 3]; outBuf[*outBufLen] = edc1; (*outBufLen)++; if (edc1 != edc11) { return PROTOCOL_T1_ERROR; } } else { /* CRC */ CRC(outBuf, *outBufLen, &edc11, &edc22); if (len < (readByte + 5)) { return PROTOCOL_T1_ERROR; } edc1 = response[readByte + 3]; outBuf[*outBufLen] = edc1; (*outBufLen)++; edc2 = response[readByte + 4]; outBuf[*outBufLen] = edc2; (*outBufLen)++; if (edc1 != edc11 || edc2 != edc22) { return PROTOCOL_T1_ERROR; } } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ /* the block to be sent is ready in T1.sendBlock -> send it using CPUCardTransact */ static int SendBlock (reader* globalData, uchar socket) { char response[BULK_BUFFER_SIZE]; int retVal, len; T1Block* send = &(globalData->cards[(int)socket].T1.sendBlock); uchar edc1, edc2, LEN = send->data[2]; #ifdef ASE_DEBUG if (T1BlockGetType(send) == T1_BLOCK_I) syslog(LOG_INFO, ">>>>>>>> SENDING I(%d, %d)\n", T1BlockGetNS(send), T1BlockGetMore(send)); else if (T1BlockGetType(send) == T1_BLOCK_R) syslog(LOG_INFO, ">>>>>>>> SENDING R(%d)\n", T1BlockGetNR(send)); else if (T1BlockGetType(send) == T1_BLOCK_S) { switch (send->data[1]) { case T1_BLOCK_S_RESYNCH_REQ: syslog(LOG_INFO, ">>>>>>>> SENDING S(RESYNCH request)\n"); break; case T1_BLOCK_S_RESYNCH_RES: syslog(LOG_INFO, ">>>>>>>> SENDING S(RESYNCH response)\n"); break; case T1_BLOCK_S_IFS_REQ: syslog(LOG_INFO, ">>>>>>>> SENDING S(IFS request)\n"); break; case T1_BLOCK_S_IFS_RES: syslog(LOG_INFO, ">>>>>>>> SENDING S(IFS = %d response)\n", send->data[3]); break; case T1_BLOCK_S_ABORT_REQ: syslog(LOG_INFO, ">>>>>>>> SENDING S(ABORT request)\n"); break; case T1_BLOCK_S_ABORT_RES: syslog(LOG_INFO, ">>>>>>>> SENDING S(ABORT response)\n"); break; case T1_BLOCK_S_WTX_REQ: syslog(LOG_INFO, ">>>>>>>> SENDING S(WTX request)\n"); break; case T1_BLOCK_S_WTX_RES: syslog(LOG_INFO, ">>>>>>>> SENDING S(WTX = %d response)\n", send->data[3]); break; case T1_BLOCK_S_VPP_ERR: syslog(LOG_INFO, ">>>>>>>> SENDING S(VPP error)\n"); } } syslog(LOG_INFO, "sendBlock: NAD = 0x%x%x, PCB = 0x%x%x, LEN = 0x%x%x sendBlock.len = %d\n", PRINT_CHAR(globalData->cards[(int)socket].T1.sendBlock.data[0]), PRINT_CHAR(globalData->cards[(int)socket].T1.sendBlock.data[1]), PRINT_CHAR(globalData->cards[(int)socket].T1.sendBlock.data[2]), globalData->cards[(int)socket].T1.sendBlock.len); #endif /* calculate the EDC */ if (globalData->cards[(int)socket].T1.edc == 1) { /* LRC */ LRC((char*)(send->data), send->len, &edc1); globalData->cards[(int)socket].T1.sendBlock.data[3 + LEN] = edc1; globalData->cards[(int)socket].T1.sendBlock.len++; } else { /* CRC */ CRC((char*)(send->data), send->len, &edc1, &edc2); globalData->cards[(int)socket].T1.sendBlock.data[3 + LEN] = edc1; globalData->cards[(int)socket].T1.sendBlock.data[4 + LEN] = edc2; globalData->cards[(int)socket].T1.sendBlock.len += 2; } retVal = T1CPUCardTransact(globalData, socket, (char*)globalData->cards[(int)socket].T1.sendBlock.data, globalData->cards[(int)socket].T1.sendBlock.len, response, &len); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "SendBlock - Error!\n"); #endif return retVal; } retVal = T1CommandResponseProccessor(globalData, socket, response, len, (char*)globalData->cards[(int)socket].T1.recBlock.data, &(globalData->cards[(int)socket].T1.recBlock.len)); #ifdef ASE_DEBUG if (retVal < 0) syslog(LOG_INFO, "SendBlock - Error!\n"); #endif return retVal; } /***************************************************************************** * *****************************************************************************/ static int SendIBlock (reader* globalData, uchar socket, uchar* data, int len, char more, int increaseNs) { uchar PCB = 0, LEN; int retVal, i; if (increaseNs) globalData->cards[(int)socket].T1.ns = (globalData->cards[(int)socket].T1.ns + 1) % 2; if (globalData->cards[(int)socket].T1.ns) PCB |= 0x40; /* N(s) */ LEN = len; if (more) PCB |= 0x20; /* M=1 */ else PCB &= 0xdf; /* M=0 */ /* prepare the sendBlock */ globalData->cards[(int)socket].T1.sendBlock.data[0] = 0x00; /* NAD */ globalData->cards[(int)socket].T1.sendBlock.data[1] = PCB; /* PCB */ globalData->cards[(int)socket].T1.sendBlock.data[2] = LEN; /* LEN */ /* copy the INF data (if exists) */ for (i = 0 ; i < LEN ; ++i) globalData->cards[(int)socket].T1.sendBlock.data[3 + i] = data[i]; globalData->cards[(int)socket].T1.sendBlock.len = LEN + 3; retVal = SendBlock(globalData, socket); return retVal; } /***************************************************************************** * *****************************************************************************/ /* data is invalid except in T1_IFS_S_BLOCK and T1_WTX_S_BLOCK */ static int SendSBlock (reader* globalData, uchar socket, uchar control, uchar data) { uchar PCB = 0, LEN = 0; int retVal; PCB = control; if (PCB == T1_BLOCK_S_IFS_REQ || PCB == T1_BLOCK_S_IFS_RES || PCB == T1_BLOCK_S_WTX_RES) LEN = 1; /* prepare the sendBlock */ globalData->cards[(int)socket].T1.sendBlock.data[0] = 0x00; /* NAD */ globalData->cards[(int)socket].T1.sendBlock.data[1] = PCB; /* PCB */ globalData->cards[(int)socket].T1.sendBlock.data[2] = LEN; /* LEN */ /* copy the INF data (if exists) */ if (LEN) globalData->cards[(int)socket].T1.sendBlock.data[3] = data; globalData->cards[(int)socket].T1.sendBlock.len = LEN + 3; retVal = SendBlock(globalData, socket); return retVal; } /***************************************************************************** * *****************************************************************************/ static int SendRBlock (reader* globalData, uchar socket, char nr) { int retVal; /* NAD */ globalData->cards[(int)socket].T1.sendBlock.data[0] = 0x00; /* PCB */ globalData->cards[(int)socket].T1.sendBlock.data[1] = 0x80; if (nr) globalData->cards[(int)socket].T1.sendBlock.data[1] |= 0x10; /* LEN */ globalData->cards[(int)socket].T1.sendBlock.data[2] = 0x00; globalData->cards[(int)socket].T1.sendBlock.len = 3; retVal = SendBlock(globalData, socket); return retVal; } /***************************************************************************** * *****************************************************************************/ /* handles S-Block requests from the card */ static int ProcessSBlock(reader* globalData, uchar socket) { int retVal, retVal2, wwt, origBwt; T1Block* recBlock = &(globalData->cards[(int)socket].T1.recBlock); // T1Block* sendBlock = &(globalData->cards[(int)socket].T1.sendBlock); struct card_params origCardParams = globalData->cards[(int)socket].cardParams, cardParams; uchar wtx; /* if this is WTX, update params including readers */ if (recBlock->data[1] == T1_BLOCK_S_WTX_REQ) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING S(WTX request)\n"); #endif if (!T1BlockGetInf(recBlock)) return PROTOCOL_T1_ERROR; cardParams = origCardParams; wtx = *(T1BlockGetInf(recBlock)); wwt = cardParams.BWT[0] * 65536 + cardParams.BWT[1] * 256 + cardParams.CWT[2]; wwt *= wtx; wwt += ASE_READER_ETU_DELTA; cardParams.BWT[0] = (uchar)((wwt & 0x00FF0000) >> 16); cardParams.BWT[1] = (uchar)((wwt & 0x0000FF00) >> 8); cardParams.BWT[2] = (uchar)(wwt & 0x000000FF); retVal = SetCardParameters(globalData, socket, cardParams); if (retVal < 0) { return retVal; } origBwt = globalData->cards[(int)socket].bwt; globalData->cards[(int)socket].bwt *= wtx; retVal = SendSBlock(globalData, socket, T1_BLOCK_S_WTX_RES, wtx); /* even if an error occured, we have to set the bwt to its original value */ globalData->cards[(int)socket].bwt = origBwt; /* the next block has already been received, so we can reset the BWT of the reader to its original values. */ retVal2 = SetCardParameters(globalData, socket, origCardParams); // NOTE: the error of the SBlock is checked only after re-setting the reader params to the default if (retVal < 0) { return retVal; } if (retVal2 < 0) { return retVal; } } /* if this if IFS, update params */ else if (recBlock->data[1] == T1_BLOCK_S_IFS_REQ) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING S(IFS request)\n"); #endif if (!T1BlockGetInf(recBlock)) return PROTOCOL_T1_ERROR; globalData->cards[(int)socket].T1.ifsc = MIN(*T1BlockGetInf(recBlock), ATHENA_IFSC_MAX_SIZE); retVal = SendSBlock(globalData, socket, T1_BLOCK_S_IFS_RES, *T1BlockGetInf(recBlock)); if (retVal < 0) { return retVal; } } /* if Abort -> response + return error code */ else if (recBlock->data[1] == T1_BLOCK_S_ABORT_REQ) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING S(ABORT request)\n"); #endif retVal = SendSBlock(globalData, socket, T1_BLOCK_S_ABORT_RES, 0); if (retVal < 0) { return retVal; } return T1_ABORT_RECEIVED; } /* if RESYNCH response -> return error code */ else if (recBlock->data[1] == T1_BLOCK_S_RESYNCH_RES) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING S(RESYNCH response)\n"); #endif return T1_RESYNCH_RECEIVED; } /* if VPP error -> return error code */ else { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING S(VPP error)\n"); #endif return T1_VPP_ERROR_RECEIVED; } /* Resynch request can only be sent by the interface device */ return PROTOCOL_T1_OK; } /***************************************************************************** * *****************************************************************************/ static int SendT1Command (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen) { uchar rsp_type; int bytes; char nr; int retVal, counter, retransmit = 0; char more, finished; T1Block* recBlock = &(globalData->cards[(int)socket].T1.recBlock); // T1Block* sendBlock = &(globalData->cards[(int)socket].T1.sendBlock); #ifdef ASE_DEBUG syslog(LOG_INFO, " SendT1Command - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; /* calculate the number of bytes to send */ counter = 0; bytes = (inBufLen > globalData->cards[(int)socket].T1.ifsc ? globalData->cards[(int)socket].T1.ifsc : inBufLen); /* see if chaining is needed */ more = (inBufLen > globalData->cards[(int)socket].T1.ifsc); finished = 0; /*================================ Sending the request to the card ================================ */ /* send block of data */ retVal = SendIBlock(globalData, socket, inBuf, bytes, more, 1); while (!finished) { /* check if an error occured */ if (retVal < 0) { if (retransmit == 3) return PROTOCOL_T1_ERROR; retransmit++; retVal = SendRBlock(globalData, socket, globalData->cards[(int)socket].T1.ns); } else { /* the block received is valid */ rsp_type = T1BlockGetType(recBlock); /* if all the data has been sent and the response from the card has arrived -> we are done here */ if (!more && rsp_type == T1_BLOCK_I) { finished = 1; } else if (rsp_type == T1_BLOCK_R) { /* errorneous R-Block received */ if (!T1ErrorFreeRBlock(recBlock)) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING R(%d + ERROR)\n", T1BlockGetNR(recBlock)); #endif if (retransmit == 3) return PROTOCOL_T1_ERROR; retransmit++; retVal = SendIBlock(globalData, socket, inBuf + counter, bytes, more, 0); } /* positive ACK R-Block received -> send next I-Block (if there still data left to send) */ else if (T1BlockGetNR(recBlock) != (globalData->cards[(int)socket].T1.ns)) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING R(%d)\n", T1BlockGetNR(recBlock)); #endif retransmit = 0; if (more) { /* calculate the number of bytes to send */ counter += bytes; bytes = ((inBufLen - counter)> globalData->cards[(int)socket].T1.ifsc ? globalData->cards[(int)socket].T1.ifsc : (inBufLen - counter)); /* see if chaining is needed */ more = ((inBufLen - counter) > globalData->cards[(int)socket].T1.ifsc); /* send block of data */ retVal = SendIBlock(globalData, socket, inBuf + counter, bytes, more, 1); } else { /* no more data left to send -> send an R-Block to get acknowledgement */ retVal = SendRBlock(globalData, socket, globalData->cards[(int)socket].T1.ns); } } /* retransmit the current block */ else { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING R(%d)\n", T1BlockGetNR(recBlock)); #endif if (retransmit == 3) return PROTOCOL_T1_ERROR; retransmit++; retVal = SendIBlock(globalData, socket, inBuf + counter, bytes, more, 0); } } /* procees the S-Block request received */ else if (rsp_type == T1_BLOCK_S) { retVal = ProcessSBlock(globalData, socket); retransmit = 0; /* (scenario 20) */ if (retVal == T1_ABORT_RECEIVED || retVal == T1_VPP_ERROR_RECEIVED) { return retVal; } } } } /*=================================== Getting the response from the card =================================== */ counter = 0; *outBufLen = 0; more = 1; retransmit = 0; nr = T1BlockGetNS(recBlock); while (more) { /* check if an error occured */ if (retVal < 0) { if (retransmit == 3) return PROTOCOL_T1_ERROR; retransmit++; retVal = SendRBlock(globalData, socket, (globalData->cards[(int)socket].T1.nsCard + 1) % 2); } else { /* the block received is valid */ rsp_type = T1BlockGetType(recBlock); if (rsp_type == T1_BLOCK_I) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING I(%d,%d)\n", T1BlockGetNS(recBlock), T1BlockGetMore(recBlock)); #endif retransmit = 0; if (nr != T1BlockGetNS(recBlock)) return PROTOCOL_T1_ERROR; globalData->cards[(int)socket].T1.nsCard = T1BlockGetNS(recBlock); /* calculate nr */ nr = (T1BlockGetNS(recBlock) + 1) % 2; /* save inf field */ bytes = T1BlockGetLen(recBlock); if (bytes) memcpy(outBuffer + counter, &(recBlock->data[3]), bytes); counter += bytes; *outBufLen = counter; /* see if chaining is requested */ more = T1BlockGetMore(recBlock); if (more) { retVal = SendRBlock(globalData, socket, nr); } } /* retransmit the current R-Block */ else if ( rsp_type == T1_BLOCK_R) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING R(%d)\n", T1BlockGetNR(recBlock)); #endif if (retransmit == 3) return PROTOCOL_T1_ERROR; retransmit++; retVal = SendRBlock(globalData, socket, (globalData->cards[(int)socket].T1.nsCard + 1) % 2); } /* procees the S-Block request received */ else if (rsp_type == T1_BLOCK_S) { retVal = ProcessSBlock(globalData, socket); retransmit = 0; /* if an Abort request is received from the card, check if the next received block is an R-Block: if yes -> return with error, if not -> clear response and continue */ if (retVal == T1_ABORT_RECEIVED) { if (T1BlockGetType(recBlock) == T1_BLOCK_R) { /* the card gave up sending is response */ #ifdef ASE_DEBUG syslog(LOG_INFO, "SendT1Command: card ABORT\n"); #endif return retVal; } else { /* the received block is an S/I-Block -> the card begins retransmitting its response */ *outBufLen = counter = 0; retVal = PROTOCOL_T1_OK; /* so that we could proceed */ } } else if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "SendT1Command: received an errorneous S-Block\n"); #endif return retVal; } } } } #ifdef ASE_DEBUG syslog(LOG_INFO, " SendT1Command - Exit\n"); #endif return retVal; } /***************************************************************************** * *****************************************************************************/ int T1Command (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen) { int retVal, retransmitTimes = 0, i; T1Block* recBlock = &(globalData->cards[(int)socket].T1.recBlock); #ifdef ASE_DEBUG syslog(LOG_INFO, "\n T1Command - Enter\n================\n"); #endif retVal = SendT1Command(globalData, socket, inBuf, inBufLen, outBuffer, outBufLen); while (retVal < 0 && retransmitTimes < 3) { /* if the command failed, check the reason and try to recover */ if (retVal < 0) { if (retVal == T1_VPP_ERROR_RECEIVED) { #ifdef ASE_DEBUG syslog(LOG_INFO, "T1Command - Error! T1_VPP_ERROR_RECEIVED\n"); #endif return retVal; /* fatal error */ } else if (retVal == T1_ABORT_RECEIVED) { #ifdef ASE_DEBUG syslog(LOG_INFO, "T1Command - Error! T1_ABORT_RECEIVED - trying again\n"); #endif /* try to retransmit the command */ retVal = SendT1Command(globalData, socket, inBuf, inBufLen, outBuffer, outBufLen); retransmitTimes++; } else { #ifdef ASE_DEBUG syslog(LOG_INFO, "T1Command - Error! retVal = %d\n", retVal); #endif /* general error -> try sending a RESYNCH request up to 3 times */ for (i = 0 ; (i < 3) && (retVal < 0) ; ++i) { retVal = SendSBlock(globalData, socket, T1_BLOCK_S_RESYNCH_REQ, 0); if (!retVal && T1BlockGetType(recBlock) == T1_BLOCK_S) { /* success - check if it's S(RESYNCH response) */ retVal = ProcessSBlock(globalData, socket); if (retVal == T1_RESYNCH_RECEIVED) retVal = PROTOCOL_T1_OK; } else retVal = PROTOCOL_T1_ERROR; /* so that we could send RESYNCH req. again */ } if (retVal < 0) { /* RESYNCH failed 3 times */ #ifdef ASE_DEBUG syslog(LOG_INFO, "T1Command - Error! could not recover - resetting the card\n"); #endif /* retVal = InitCard(globalData, socket, 0, &protocol); // warm reset ?????? */ return PROTOCOL_T1_ERROR; } else { /* RESYNCH succeeded -> init protocol + retry command */ /* init the protocol */ retVal = T1InitProtocol(globalData, socket, 1); /* try to transmit the command again */ retVal = SendT1Command(globalData, socket, inBuf, inBufLen, outBuffer, outBufLen); retransmitTimes++; } } } } /* #ifdef ASE_DEBUG syslog(LOG_INFO, "T1Command - response: "); for (i = 0 ; i < *outBufLen ; ++i) syslog(LOG_INFO, " 0x%x%x", PRINT_CHAR(outBuffer[i])); syslog(LOG_INFO, "\n"); syslog(LOG_INFO, " T1Command - Exit\n================\n\n"); #endif */ return retVal; } asedriveiiie-3.7/asedriveiiie-serial/Makefile.inc0000755000175000017500000000021211441364261022452 0ustar rousseaurousseauPREFIX=/usr USBDROPDIR=/usr/local/pcsc/drivers BUILD= CFLAGS= -pthread -I/usr/local/include/PCSC LDFLAGS= -L/usr/local/lib -lpcsclite asedriveiiie-3.7/asedriveiiie-serial/ifdhandler.c0000755000175000017500000010210011441415473022507 0ustar rousseaurousseau/***************************************************************** / / File : ifdhandler.c / Date : April 9, 2001 / Purpose: This provides reader specific low-level calls / for the ASE-III (USB) reader of Athena Smartcard Solutions. / License: See file LICENSE & COPYING / ******************************************************************/ #include #include #include #include #include "Ase.h" /***************************************************************************** * *****************************************************************************/ #define MAX_READER_NUM 16 static reader readerData[MAX_READER_NUM]; /***************************************************************************** * *****************************************************************************/ static void closeDriver ( DWORD Lun ) { int retVal, i, readerNum = (Lun & 0xFFFF0000) >> 16; /* if there are some cards that are powered on, power them off */ for (i = 0 ; i < MAX_SOCKET_NUM ; ++i) if (readerData[readerNum].cards[i].status == 2) { retVal = CardPowerOff(&readerData[readerNum], i); /* if (retVal < 0) { return IFD_COMMUNICATION_ERROR; } */ readerData[readerNum].cards[0].atr.length = 0; } retVal = ReaderFinish(&readerData[readerNum]); /* if (retVal < 0) { return IFD_COMMUNICATION_ERROR; } */ IO_Close(&readerData[readerNum]); readerData[readerNum].readerStarted = 0; readerData[readerNum].io.handle = 0; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHCreateChannel ( DWORD Lun, DWORD Channel ) { //RESPONSECODE IO_Create_Channel ( DWORD Channel ) { //DWORD Lun = 0; /* Lun - Logical Unit Number, use this for multiple card slots or multiple readers. 0xXXXXYYYY - XXXX multiple readers, YYYY multiple slots. The resource manager will set these automatically. By default the resource manager loads a new instance of the driver so if your reader does not have more than one smartcard slot then ignore the Lun in all the functions. Future versions of PC/SC might support loading multiple readers through one instance of the driver in which XXXX would be important to implement if you want this. */ /* Channel - Channel ID. This is denoted by the following: 0x000001 - /dev/pcsc/1 0x000002 - /dev/pcsc/2 0x000003 - /dev/pcsc/3 USB readers may choose to ignore this parameter and query the bus for the particular reader. */ /* This function is required to open a communications channel to the port listed by Channel. For example, the first serial reader on COM1 would link to /dev/pcsc/1 which would be a sym link to /dev/ttyS0 on some machines This is used to help with intermachine independance. Once the channel is opened the reader must be in a state in which it is possible to query IFDHICCPresence() for card status. returns: IFD_SUCCESS IFD_COMMUNICATION_ERROR */ UCHAR data[300]; int retVal, len, readerNum = (Lun & 0xFFFF0000) >> 16; char name[30]; unsigned short Unibble = Channel >> 16; /* Upper 16bits of DWORD. (DDDD) */ unsigned short Lnibble = Channel - ( Unibble << 16 ); /* Lower 16bits of DWORD. (CCCC) */ #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : entering IFDHCreateChannel Channel = 0x%04x%04x Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF), (int)((Channel >> 16) & 0xFFFF), (int)(Channel & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* if (Lnibble != 0x3F8 && Lnibble != 0x2F8 && Lnibble != 0x3E8 && Lnibble != 0x2E8) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHCreateChannel: Error! Channel not supported. Existing.\n"); #endif return IFD_NOT_SUPPORTED; } */ /* open the communication port */ if (Lnibble == 0x3F8 || Lnibble == 0x2F8 || Lnibble == 0x3E8 || Lnibble == 0x2E8) sprintf(name, "/dev/ttyS%d", (Lnibble == 0x3F8 ? 0 : Lnibble == 0x2F8 ? 1 : Lnibble == 0x3E8 ? 2 : 3)); else sprintf(name, "/dev/ttyUSB%d", Lnibble); if (IO_InitializePort(&readerData[readerNum], 115200, 8, 'N', name) == TRUE) { #ifdef ASE_DEBUG syslog(LOG_INFO, "%s opened for IO.\n", name); #endif IO_UpdateReturnBlock(&readerData[readerNum], 4); } else { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHCreateChannel: Error! Could not open %s. Existing.\n", name); #endif return IFD_COMMUNICATION_ERROR; } /* reader open */ retVal = ReaderStartup(&readerData[readerNum], (char*)data, &len); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHCreateChannel: Error! - in ReaderStartup\n"); syslog(LOG_INFO, "Closing %s.\n", name); #endif IO_Close(&readerData[readerNum]); return IFD_COMMUNICATION_ERROR; } /* retVal = GetFIDITable(&readerData[readerNum], data, &len); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHCreateChannel: Error! - in GetFIDITable\n"); syslog(LOG_INFO, "Closing %s.\n", name); #endif retVal = ReaderFinish(&readerData[readerNum]); IO_Close(&readerData[readerNum]); return IFD_COMMUNICATION_ERROR; } */ #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : exisiting IFDHCreateChannel\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHCloseChannel ( DWORD Lun ) { /* This function should close the reader communication channel for the particular reader. Prior to closing the communication channel the reader should make sure the card is powered down and the terminal is also powered down. returns: IFD_SUCCESS IFD_COMMUNICATION_ERROR */ #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : entering IFDHCloseChannel Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif closeDriver(Lun); #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : exisiting IFDHCloseChannel\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHGetCapabilities ( DWORD Lun, DWORD Tag, PDWORD Length, PUCHAR Value ) { /* This function should get the slot/card capabilities for a particular slot/card specified by Lun. Again, if you have only 1 card slot and don't mind loading a new driver for each reader then ignore Lun. Tag - the tag for the information requested example: TAG_IFD_ATR - return the Atr and it's size (required). these tags are defined in ifdhandler.h Length - the length of the returned data Value - the value of the data returns: IFD_SUCCESS IFD_ERROR_TAG */ int readerNum = (Lun & 0xFFFF0000) >> 16; uchar socket = Lun & 0x0000FFFF; #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : entering IFDHGetCapabilities Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); return IFD_ERROR_TAG; } */ switch (Tag) { case TAG_IFD_ATR: { /* If Length is not zero, powerICC has been performed. Otherwise, return NULL pointer Buffer size is stored in *Length */ *Length = readerData[readerNum].cards[socket].atr.length; if (*Length) { memcpy(Value, readerData[readerNum].cards[socket].atr.data, *Length); } break; } case TAG_IFD_SIMULTANEOUS_ACCESS: { #ifdef ASE_DEBUG syslog(LOG_INFO, "TAG_IFD_SIMULTANEOUS_ACCESS\n"); #endif *Length = 1; *Value = MAX_READER_NUM; break; } case TAG_IFD_SLOTS_NUMBER: { #ifdef ASE_DEBUG syslog(LOG_INFO, "TAG_IFD_SLOTS_NUMBER\n"); #endif *Length = 1; *Value = 1; break; } case TAG_IFD_THREAD_SAFE: { #ifdef ASE_DEBUG syslog(LOG_INFO, "TAG_IFD_THREAD_SAFE\n"); #endif if (*Length >= 1) { *Length = 1; *Value = 1; } break; } default: #ifdef ASE_DEBUG syslog(LOG_INFO, "default TAG Tag = %0X\n", (int)Tag); #endif return IFD_ERROR_TAG; } #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : exisiting IFDHGetCapabilities\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHSetCapabilities ( DWORD Lun, DWORD Tag, DWORD Length, PUCHAR Value ) { /* This function should set the slot/card capabilities for a particular slot/card specified by Lun. Again, if you have only 1 card slot and don't mind loading a new driver for each reader then ignore Lun. Tag - the tag for the information needing set Length - the length of the returned data Value - the value of the data returns: IFD_SUCCESS IFD_ERROR_TAG IFD_ERROR_SET_FAILURE IFD_ERROR_VALUE_READ_ONLY */ #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : entering IFDHSetCapabilities Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); return IFD_ERROR_SET_FAILURE; } */ #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : exisiting IFDHSetCapabilities\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHSetProtocolParameters ( DWORD Lun, DWORD Protocol, UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3) { /* This function should set the PTS of a particular card/slot using the three PTS parameters sent Protocol - 0 .... 14 T=0 .... T=14 Flags - Logical OR of possible values: IFD_NEGOTIATE_PTS1 IFD_NEGOTIATE_PTS2 IFD_NEGOTIATE_PTS3 to determine which PTS values to negotiate. PTS1,PTS2,PTS3 - PTS Values. returns: IFD_SUCCESS IFD_ERROR_PTS_FAILURE IFD_COMMUNICATION_ERROR IFD_PROTOCOL_NOT_SUPPORTED */ int retVal, PPS1present, PPS2present, PPS3present; int readerNum = (Lun & 0xFFFF0000) >> 16; uchar socket = Lun & 0x0000FFFF, ppsProt; #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : entering IFDHSetProtocolParameters Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); return IFD_COMMUNICATION_ERROR; } */ /* works only for T=0 and T=1 */ if (Protocol != SCARD_PROTOCOL_T0 && Protocol != SCARD_PROTOCOL_T1) { return IFD_PROTOCOL_NOT_SUPPORTED; } /* check if the card is absent */ if (!readerData[readerNum].cards[socket].status) return IFD_COMMUNICATION_ERROR; PPS1present = Flags & IFD_NEGOTIATE_PTS1; PPS2present = Flags & IFD_NEGOTIATE_PTS2; PPS3present = Flags & IFD_NEGOTIATE_PTS3; /* in the meanwhile only protocol could be set */ if (PPS1present || PPS2present || PPS3present) return IFD_ERROR_PTS_FAILURE; if (Protocol == SCARD_PROTOCOL_T0) ppsProt = 0; else ppsProt = 1; /* do a cold reset followed by PPS (if needed) only if the current protocol is to be changed*/ if (readerData[readerNum].cards[socket].status == 2 && ((readerData[readerNum].cards[socket].activeProtocol == 0 && ppsProt != 0) || (readerData[readerNum].cards[socket].activeProtocol == 1 && ppsProt != 1))) { retVal = InitCard(&readerData[readerNum], socket, 1, (char*)(&ppsProt)); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHSetProtocolParameters - Error! retVal = %d\n", retVal); #endif return IFD_ERROR_PTS_FAILURE; } } #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : exisiting IFDHSetProtocolParameters\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHPowerICC ( DWORD Lun, DWORD Action, PUCHAR Atr, PDWORD AtrLength ) { /* This function controls the power and reset signals of the smartcard reader at the particular reader/slot specified by Lun. Action - Action to be taken on the card. IFD_POWER_UP - Power and reset the card if not done so (store the ATR and return it and it's length). IFD_POWER_DOWN - Power down the card if not done already (Atr/AtrLength should be zero'd) IFD_RESET - Perform a quick reset on the card. If the card is not powered power up the card. (Store and return the Atr/Length) Atr - Answer to Reset of the card. The driver is responsible for caching this value in case IFDHGetCapabilities is called requesting the ATR and it's length. This should not exceed MAX_ATR_SIZE. AtrLength - Length of the Atr. This should not exceed MAX_ATR_SIZE. Notes: Memory cards without an ATR should return IFD_SUCCESS on reset but the Atr should be zero'd and the length should be zero Reset errors should return zero for the AtrLength and return IFD_ERROR_POWER_ACTION. returns: IFD_SUCCESS IFD_ERROR_POWER_ACTION IFD_COMMUNICATION_ERROR IFD_NOT_SUPPORTED */ int retVal, readerNum = (Lun & 0xFFFF0000) >> 16; uchar socket = Lun & 0x0000FFFF; #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : entering IFDHPowerICC Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* zero everything */ *AtrLength = 0; memset(Atr, 0, MAX_ATR_SIZE); /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); return IFD_COMMUNICATION_ERROR; } */ if (readerData[readerNum].cards[socket].activeProtocol == ATR_PROTOCOL_TYPE_RAW && Action == IFD_RESET) Action = IFD_POWER_UP; switch (Action) { case IFD_POWER_UP: /* check if already powered up */ if (readerData[readerNum].cards[socket].status != 2) { retVal = InitCard(&readerData[readerNum], socket, 1, NULL); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHPowerICC: Error! in InitCard\n"); #endif return IFD_ERROR_POWER_ACTION; } } *AtrLength = readerData[readerNum].cards[socket].atr.length; if (*AtrLength) { memcpy(Atr, readerData[readerNum].cards[socket].atr.data, *AtrLength); } break; case IFD_RESET: if (readerData[readerNum].cards[socket].activeProtocol == ATR_PROTOCOL_TYPE_RAW) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHPowerICC - Error! while powering on mem card with warm reset\n"); #endif return IFD_ERROR_POWER_ACTION; /* warm reset is not allowed for memort cards */ } if (readerData[readerNum].cards[socket].status == 2) { /* powered up -> warm reset */ retVal = InitCard(&readerData[readerNum], socket, 0, NULL); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHPowerICC - Error! while powering on card with warm reset\n"); #endif return IFD_COMMUNICATION_ERROR; } } else { /* not powered up -> cold reset */ retVal = InitCard(&readerData[readerNum], socket, 1, NULL); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHPowerICC - Error! while powering on card with cold reset\n"); #endif return IFD_COMMUNICATION_ERROR; } } *AtrLength = readerData[readerNum].cards[socket].atr.length; if (*AtrLength) { memcpy(Atr, readerData[readerNum].cards[socket].atr.data, *AtrLength); } break; case IFD_POWER_DOWN: /* check if the card is not already powered off */ if (readerData[readerNum].cards[socket].status == 2) { retVal = CardPowerOff(&readerData[readerNum], socket); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHPowerICC - Error! while powering off card\n"); #endif return IFD_COMMUNICATION_ERROR; } } readerData[readerNum].cards[socket].atr.length = 0; break; default: return IFD_NOT_SUPPORTED; } #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : exiting IFDHPowerICC\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHTransmitToICC ( DWORD Lun, SCARD_IO_HEADER SendPci, PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength, PSCARD_IO_HEADER RecvPci ) { /* This function performs an APDU exchange with the card/slot specified by Lun. The driver is responsible for performing any protocol specific exchanges such as T=0/1 ... differences. Calling this function will abstract all protocol differences. SendPci Protocol - 0, 1, .... 14 Length - Not used. TxBuffer - Transmit APDU example (0x00 0xA4 0x00 0x00 0x02 0x3F 0x00) TxLength - Length of this buffer. RxBuffer - Receive APDU example (0x61 0x14) RxLength - Length of the received APDU. This function will be passed the size of the buffer of RxBuffer and this function is responsible for setting this to the length of the received APDU. This should be ZERO on all errors. The resource manager will take responsibility of zeroing out any temporary APDU buffers for security reasons. RecvPci Protocol - 0, 1, .... 14 Length - Not used. Notes: The driver is responsible for knowing what type of card it has. If the current slot/card contains a memory card then this command should ignore the Protocol and use the MCT style commands for support for these style cards and transmit them appropriately. If your reader does not support memory cards or you don't want to then ignore this. RxLength should be set to zero on error. returns: IFD_SUCCESS IFD_COMMUNICATION_ERROR IFD_RESPONSE_TIMEOUT IFD_ICC_NOT_PRESENT IFD_PROTOCOL_NOT_SUPPORTED */ int retVal, actual, readerNum = (Lun & 0xFFFF0000) >> 16; UCHAR response[700], socket = Lun & 0x0000FFFF; UCHAR TxBuffer2[5]; #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : entering IFDHTransmitToICC Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } */ if (TxBuffer == NULL || TxLength == 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "Athena Serial : IFDHTransmitToICC - Error - no data in command!!!\n"); #endif if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } switch (SendPci.Protocol) { case ATR_PROTOCOL_TYPE_T0: if (readerData[readerNum].cards[socket].status == 1) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; /* not powered on */ } else if (readerData[readerNum].cards[socket].status == 0) { if (RxLength) *RxLength = 0; return IFD_ICC_NOT_PRESENT; } else if (readerData[readerNum].cards[socket].activeProtocol != 0) { /* current protocol isnt T=0 */ if (RxLength) *RxLength = 0; return IFD_PROTOCOL_NOT_SUPPORTED; } else { /* card is powered on */ if (RecvPci) RecvPci->Protocol = ATR_PROTOCOL_TYPE_T0; if (TxLength > 5) { // check if it's a case 4 command that should be splitted into write + get response DWORD tmpLen=4 + 1 + TxBuffer[4] + 1; if (TxLength == tmpLen) { retVal = T0Write(&readerData[readerNum], socket, TxBuffer, TxLength - 1, response, &actual); if (retVal == ASE_OK && actual == 2 && response[0] == 0x61) { // now send a Get Response apdu unsigned short newLen = (TxBuffer[TxLength - 1] == 0 ? 256 : TxBuffer[TxLength - 1]); UCHAR Le = (newLen < response[1] ? (newLen == 256 ? 0 : newLen) : response[1]); UCHAR getResponseCmd[5] = {0x00, 0xC0, 0x00, 0x00, 0x00}; // getResponseCmd[0] = TxBuffer[0]; getResponseCmd[4] = Le; retVal = T0Read(&readerData[readerNum], socket, getResponseCmd, 5, response, &actual); } } else { retVal = T0Write(&readerData[readerNum], socket, TxBuffer, TxLength, response, &actual); } if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } else if (TxLength == 4) { /* case 1 */ memcpy(TxBuffer2, TxBuffer, 4); TxBuffer2[4] = 0x00; retVal = T0Write(&readerData[readerNum], socket, TxBuffer2, 5, response, &actual); if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } else { retVal = T0Read(&readerData[readerNum], socket, TxBuffer, TxLength, response, &actual); if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } } break; case ATR_PROTOCOL_TYPE_T1: if (readerData[readerNum].cards[socket].status == 1) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; /* not powered on */ } else if (readerData[readerNum].cards[socket].status == 0) { if (RxLength) *RxLength = 0; return IFD_ICC_NOT_PRESENT; } else if (readerData[readerNum].cards[socket].activeProtocol != 1) { /* current protocol isnt T=1 */ if (RxLength) *RxLength = 0; return IFD_PROTOCOL_NOT_SUPPORTED; } else { /* card is powered on */ if (RecvPci) RecvPci->Protocol = ATR_PROTOCOL_TYPE_T1; retVal = T1Command (&readerData[readerNum], socket, TxBuffer, TxLength, response, &actual); if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } break; default: if (RxLength) *RxLength = 0; return IFD_PROTOCOL_NOT_SUPPORTED; } #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : exisiting IFDHTransmitToICC\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHControl ( DWORD Lun, PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength ) { /* This function performs a data exchange with the reader (not the card) specified by Lun. Here XXXX will only be used. It is responsible for abstracting functionality such as PIN pads, biometrics, LCD panels, etc. You should follow the MCT, CTBCS specifications for a list of accepted commands to implement. TxBuffer - Transmit data TxLength - Length of this buffer. RxBuffer - Receive data RxLength - Length of the received data. This function will be passed the length of the buffer RxBuffer and it must set this to the length of the received data. Notes: RxLength should be zero on error. */ int retVal, actual, readerNum = (Lun & 0xFFFF0000) >> 16; uchar socket = Lun & 0x0000FFFF; UCHAR response[700]; #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : entering IFDHControl Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } */ /* check if its an ioctl for the reader */ if (TxLength >= 4 && TxBuffer[0] == ASE_IOCTL_CLASS && TxBuffer[1] == ASE_IOCTL_XI2C_INS) { struct card_params params = readerData[readerNum].cards[socket].cardParams; params.protocol = 0x22; retVal = SetCardParameters(&readerData[readerNum], socket, params); if (retVal < 0) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } } else if (TxLength >= 4 && TxBuffer[0] == ASE_IOCTL_CLASS && TxBuffer[1] == ASE_IOCTL_CLOCK_INS) { /* change clock in reader - not supported yet */ } // other ioctls sent to the reader else if (TxLength >= 4 && TxBuffer[0] == ASE_IOCTL_RAW_CLASS && TxBuffer[1] == ASE_IOCTL_RAW_INS) { actual = (RxLength ? *RxLength : 0); retVal = SendIOCTL(&readerData[readerNum], socket, &TxBuffer[2], TxLength - 2, response, &actual); if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } /* card eject */ else if (TxLength == 5 && TxBuffer[0] == 0x20 && TxBuffer[1] == 0x15 && TxBuffer[3] == 0x00 && TxBuffer[4] == 0x00) { retVal = CardPowerOff(&readerData[readerNum], socket); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHControl - Error! while ejecting card\n"); #endif if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } readerData[readerNum].cards[socket].atr.length = 0; // return success status *RxLength = 2; RxBuffer[0] = 0x90; RxBuffer[1] = 0x00; // try to eject the card (dont care if fail) { unsigned char EXTRACT_CARD[] = {0x50, 0x63, 0x0, 0x33}; actual = 2; retVal = SendIOCTL(&readerData[readerNum], socket, EXTRACT_CARD, sizeof(EXTRACT_CARD), response, &actual); } } else if (readerData[readerNum].cards[socket].activeProtocol == ATR_PROTOCOL_TYPE_RAW) { if (readerData[readerNum].cards[socket].status == 1 || readerData[readerNum].cards[socket].status == 0) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; /* not powered on or absent */ } retVal = MemoryCardCommand (&readerData[readerNum], socket, TxBuffer, TxLength, response, &actual); if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : exisiting IFDHControl\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHICCPresence( DWORD Lun ) { /* This function returns the status of the card inserted in the reader/slot specified by Lun. It will return either: returns: IFD_ICC_PRESENT IFD_ICC_NOT_PRESENT IFD_COMMUNICATION_ERROR */ UCHAR data[300]; int retVal, len, readerNum = (Lun & 0xFFFF0000) >> 16; uchar socket = Lun & 0x0000FFFF; /* syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : entering IFDHICCPresence Lun = 0x%04x%04x\n", (Lun >> 16) & 0xFFFF, Lun & 0xFFFF); syslog(LOG_INFO, "==============================================\n"); */ /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); return IFD_COMMUNICATION_ERROR; } */ retVal = GetStatus(&readerData[readerNum], (char*)data, &len); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHICCPresence: Error! - in GetStatus\n"); #endif return IFD_COMMUNICATION_ERROR; } /* syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "Athena Serial : exisiting IFDHICCPresence\n"); syslog(LOG_INFO, "==============================================\n"); */ return (readerData[readerNum].cards[socket].status ? IFD_ICC_PRESENT : IFD_ICC_NOT_PRESENT); } asedriveiiie-3.7/asedriveiiie-serial/serial.c0000755000175000017500000003325511441413615021700 0ustar rousseaurousseau#include /* Standard Includes */ #include #include #include #include #include #include #include #include #include #include "Ase.h" //***************************************************************************** // //***************************************************************************** /* * InititalizePort -- initialize a serial port * This functions opens the serial port specified and sets the * line parameters baudrate, bits per byte and parity according to the * parameters. If no serial port is specified, the Communications * Manager's dialog is invoked to permit the user to select not only * the port, but all the other (baud/bits/parity) details as well. * Selections made by the user in this case will override the * parameters passed. */ bool IO_InitializePort(reader* globalData, int baud, int bits, char parity, char* port) { HANDLE handle; struct termios newtio; /* Try user input depending on port */ int tmpResult=open(port, O_RDWR | O_NOCTTY); if (tmpResult<0) { return FALSE; } handle = tmpResult; /* * Zero the struct to make sure that we don't use any garbage * from the stack. */ memset(&newtio, 0, sizeof(newtio)); /* * Set the baudrate */ switch (baud) { case 9600: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; case 19200: cfsetispeed(&newtio, B19200); cfsetospeed(&newtio, B19200); break; case 38400: /* Baudrate 38400 */ cfsetispeed(&newtio, B38400); cfsetospeed(&newtio, B38400); break; case 57600: /* Baudrate 57600 */ cfsetispeed(&newtio, B57600); cfsetospeed(&newtio, B57600); break; case 115200: /* Baudrate 115200 */ cfsetispeed(&newtio, B115200); cfsetospeed(&newtio, B115200); break; case 230400: /* Baudrate 230400 */ cfsetispeed(&newtio, B230400); cfsetospeed(&newtio, B230400); break; default: close(handle); return FALSE; } /* * Set the bits. */ switch (bits) { case 5: newtio.c_cflag |= CS5; break; case 6: newtio.c_cflag |= CS6; break; case 7: newtio.c_cflag |= CS7; break; case 8: newtio.c_cflag |= CS8; break; default: close(handle); return FALSE; } /* * Set the parity (Odd Even None) */ switch (parity) { case 'O': newtio.c_cflag |= PARODD | PARENB; newtio.c_iflag |= INPCK; break; case 'E': newtio.c_cflag &= (~PARODD); newtio.c_cflag |= PARENB; newtio.c_iflag |= INPCK; break; case 'N': break; default: close(handle); return FALSE; } /* * Setting Raw Input and Defaults */ newtio.c_cflag |= CSTOPB; newtio.c_cflag |= CREAD|HUPCL|CLOCAL; newtio.c_iflag &= ~(IGNPAR|PARMRK|INLCR|IGNCR|ICRNL|ISTRIP); newtio.c_iflag |= BRKINT; // newtio.c_lflag = ~(ICANON|ECHO); newtio.c_oflag = 0; newtio.c_lflag = 0; // put in remark because they dont seem to work //newtio.c_cc[VMIN] = 0; // wait for any number of bytes arriving (first byte) //newtio.c_cc[VTIME] = 100; // 10 seconds timeout /* Set the parameters */ if (tcsetattr(handle, TCSANOW, &newtio) < 0) { close(handle); return FALSE; } /* * Wait while reader sends PNP information * (I'll catch this information in future * versions if I get the information) */ usleep(1000000); { int dtr_bit = TIOCM_DTR; int rts_bit = TIOCM_RTS; /* Set RTS low then do a DTR toggle to reset */ ioctl (handle, TIOCMBIC, &rts_bit); usleep(100000); ioctl (handle, TIOCMBIC, &dtr_bit); usleep(100000); ioctl (handle, TIOCMBIS, &dtr_bit); usleep(100000); ioctl (handle, TIOCMBIC, &dtr_bit); usleep(100000); ioctl (handle, TIOCMBIS, &dtr_bit); usleep(100000); ioctl (handle, TIOCMBIC, &dtr_bit); usleep(100000); } if (tcflush(handle, TCIOFLUSH) < 0) { close(handle); return FALSE; } sleep(1); /* * Record serial port settings */ globalData->io.handle = handle; globalData->io.baud = baud; globalData->io.bits = bits; globalData->io.stopbits = 1; globalData->io.parity = parity; globalData->io.blocktime = 1; return TRUE; } //***************************************************************************** // //***************************************************************************** // returns the number of bytes available int IO_Read(reader* globalData, unsigned long timeout, int len, unsigned char *buf ) { fd_set rfds; struct timeval tv; int rval; int readBytesNum = 0; HANDLE handle; #ifdef ASE_DEBUG int i; #endif handle = globalData->io.handle; tv.tv_sec = timeout / 1000000;//globalData->io.blocktime; tv.tv_usec = timeout % 1000000;//0; FD_ZERO(&rfds); FD_SET(handle, &rfds); rval = select(handle+1, &rfds, NULL, NULL, &tv); if (rval == -1) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IO_Read: Error! in initial select\n"); #endif return 0; } else if (rval == 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IO_Read: Error! timeout (sec = %d usec = %d) in initial select\n", (int)tv.tv_sec, (int)tv.tv_usec); #endif return 0; } if (FD_ISSET(handle, &rfds)) { rval = read(handle, buf, len); if (rval < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IO_Read: Error! read() is negative (1)\n"); #endif return 0; } #ifdef ASE_DEBUG for (i = 0 ; i < rval ; ++i) syslog(LOG_INFO, "<=== 0x%02x\n", buf[i + readBytesNum]); #endif readBytesNum += rval; while (readBytesNum < len) { tv.tv_sec = timeout / 1000000;//globalData->io.blocktime; tv.tv_usec = timeout % 1000000;//0; FD_ZERO(&rfds); FD_SET(handle, &rfds); rval = select(handle+1, &rfds, NULL, NULL, &tv); if (rval == -1) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IO_Read: Error! in secondary select\n"); #endif return 0; } else if (rval == 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IO_Read: Error! timeout (sec = %d usec = %d) in secondary select\n", (int)tv.tv_sec, (int)tv.tv_usec); #endif return 0; } if (FD_ISSET(handle, &rfds)) { rval = read(handle, buf + readBytesNum, len - readBytesNum); if (rval < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IO_Read: Error! readBytesNum is negative (2)\n"); #endif return 0; } #ifdef ASE_DEBUG for (i = 0 ; i < rval ; ++i) syslog(LOG_INFO, "<=== 0x%02x\n", buf[i + readBytesNum]); #endif readBytesNum += rval; } else { #ifdef ASE_DEBUG syslog(LOG_INFO, "IO_Read: Error! our handle not ready in secondary select\n"); #endif return 0; } } } else { #ifdef ASE_DEBUG syslog(LOG_INFO, "IO_Read: Error! our handle not ready in initial select\n"); #endif return 0; } if (readBytesNum < len) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IO_Read: Error! not all bytes read\n"); #endif } return readBytesNum; } //***************************************************************************** // //***************************************************************************** int IO_Write(reader* globalData, int writesize, unsigned char* data) { HANDLE handle = globalData->io.handle; unsigned int remain = writesize, chunk, offset = 0; int i; while (remain) { chunk = (remain > SSIZE_MAX ? SSIZE_MAX : remain); i = write(handle, data + offset, chunk); if (i < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IO_Write: Error!\n"); #endif return offset; } offset += i; remain -= i; } return writesize; } //***************************************************************************** // //***************************************************************************** bool IO_Close(reader* globalData) { HANDLE handle = globalData->io.handle; /* Close the handle */ if ( close (handle) == 0 ) { return TRUE; } else { return FALSE; } } //***************************************************************************** // //***************************************************************************** void IO_CleanReadBuffer(reader* globalData) { unsigned char temp[700]; IO_Read(globalData, 1000000 /* 1 sec */, 300, temp); } //***************************************************************************** // //***************************************************************************** bool IO_FlushBuffer(reader* globalData) { HANDLE handle = globalData->io.handle; if (tcflush(handle, TCIFLUSH) == 0) return TRUE; return FALSE; } //***************************************************************************** // //***************************************************************************** char IO_UpdateParity(reader* globalData, char parity) { struct termios newtio; // Gets current settings tcgetattr(globalData->io.handle,&newtio); /* * Set the parity (Odd Even None) */ switch (parity) { /* Odd Parity */ case 'O': newtio.c_cflag |= PARODD; break; /* Even Parity */ case 'E': newtio.c_cflag &= (~PARODD); break; /* No Parity */ case 'N': break; } /* Flush the serial port */ if(tcflush(globalData->io.handle, TCIFLUSH) < 0) { close(globalData->io.handle); return -1; } /* Set the parameters */ if(tcsetattr(globalData->io.handle, TCSANOW, &newtio) < 0) { close(globalData->io.handle); return -1; } /* Record the parity */ globalData->io.parity = parity; return(globalData->io.parity); } //***************************************************************************** // //***************************************************************************** int IO_UpdateStopBits(reader* globalData, int stopbits) { struct termios newtio; // Gets current settings tcgetattr(globalData->io.handle,&newtio); /* * Set number of stop bits (1,2) */ switch (stopbits) { /* 2 stop bits */ case 2: newtio.c_cflag |= CSTOPB; break; /* 1 stop bit */ case '1': newtio.c_cflag &= (~CSTOPB); break; } /* Flush the serial port */ if(tcflush(globalData->io.handle, TCIFLUSH) < 0) { close(globalData->io.handle); return -1; } /* Set the parameters */ if(tcsetattr(globalData->io.handle, TCSANOW, &newtio) < 0) { close(globalData->io.handle); return -1; } /* Record the number of stop bits */ globalData->io.stopbits = stopbits; return(globalData->io.stopbits); } //***************************************************************************** // //***************************************************************************** int IO_UpdateReturnBlock(reader* globalData, int blocktime) { globalData->io.blocktime = (long)blocktime; return globalData->io.blocktime; } //***************************************************************************** // //***************************************************************************** HANDLE IO_ReturnHandle(reader* globalData) { /* Return the current used handle */ return globalData->io.handle; } //***************************************************************************** // //***************************************************************************** int IO_ReturnBaudRate(reader* globalData) { /* Return the current baudrate */ return globalData->io.baud; } //***************************************************************************** // //***************************************************************************** char IO_ReturnParity(reader* globalData) { /* Return the current parity */ return globalData->io.parity; } //***************************************************************************** // //***************************************************************************** int IO_ReturnStopBits(reader* globalData) { /* Return the stop bits */ return(globalData->io.stopbits); } asedriveiiie-3.7/asedriveiiie-serial/Makefile0000755000175000017500000000134011265303424021703 0ustar rousseaurousseau include Makefile.inc DRIVER_DIR=${DESTDIR}/${USBDROPDIR}/ifd-ASEDriveIIIe-Serial CC=${BUILD}-gcc SOURCES=serial.c atr.c DriverIO.c CommandTypes.c ReaderCommands.c T1Protocol.c MemoryCards.c InitCardParams.c ifdhandler.c all: libASESerial.so etc libASESerial.so: ${SOURCES} ${CC} -o libASESerial.so ${SOURCES} -fPIC -D_REENTRANT -DIFDHANDLERv2 -Wall -I. ${CFLAGS} ${LDFLAGS} -shared etc: etc/reader.conf etc/reader.conf: etc/reader.conf.in sed "s#\%PCSC_DRIVERS_DIR\%#${USBDROPDIR}#g" < etc/reader.conf.in > etc/reader.conf clean-all: clean rm Makefile.inc || true clean: rm -f *~ *.o *.so || true rm etc/reader.conf || true install: all install -c -d "${DRIVER_DIR}" install -c -m 0755 libASESerial.so "${DRIVER_DIR}" asedriveiiie-3.7/asedriveiiie-serial/InitCardParams.c0000755000175000017500000006670711441415247023275 0ustar rousseaurousseau#include "Ase.h" #include /***************************************************************************** * *****************************************************************************/ #define ASE_PPS_DEFAULT_USED -1000 #define ASE_PPS_FAILED -1001 /***************************************************************************** * *****************************************************************************/ #define EPSILON 0.001 static int fi[16] = { 372, 372, 558, 744, 1116, 1488, 1860, 1, 1, 512, 768, 1024, 1536, 2048, 1, 1 }; static int di[16] = { 1, 1, 2, 4, 8, 16, 32, 1, 12, 20, 1, 1, 1, 1, 1, 1 }; static long fs[16] = {4000000, 5000000, 6000000, 8000000, 12000000, 16000000, 20000000, 0, 0, 5000000, 7500000, 10000000, 15000000, 20000000, 0, 0}; /***************************************************************************** * *****************************************************************************/ static void GetDefaultReaderParams (reader* globalData, struct card_params* params) { params->protocol = 0; params->N = 0x03; params->CWT[0] = 0x00; params->CWT[1] = 0x25/*0x85*/; params->CWT[2] = 0x85/*0xF0*/; params->BWT[0] = 0x00; params->BWT[1] = 0x3A/*0x38*/; params->BWT[2] = 0x34/*0xA4*/; /* 372 */ params->A = 0x01; params->B = 0x74; params->freq = 0x02; params->fTod = 372.0; } /***************************************************************************** * *****************************************************************************/ static int MatchReaderParams(reader* globalData, char socket, struct card_params* params, ATR* atr, uchar Fi, uchar Di, uchar WI, uchar N, char protocol) { uchar found = 0; int F, D, WWT; float cardFToD = GetFToDFactor(Fi, Di); float readerFToD; int etuFactor; long maxFreq = fs[Fi]; int etus; #ifdef ASE_DEBUG syslog(LOG_INFO, "MatchReaderParams: card Fi = %d, Di = %d, Wi = %d, cardFToD = %f\n",Fi, Di, WI, cardFToD); #endif if (maxFreq >= 16000000) { params->freq = 0; //f = 16000000; } else if (maxFreq >= 8000000) { params->freq = 1; //f = 8000000; } else if (maxFreq >= 4000000) { params->freq = 2; //f = 4000000; } else { params->freq = 3; //f = 2000000; } /* check to see if the card parameters are supported by the reader: if readerFToD is smaller than cardFToD */ readerFToD = (float)(globalData->dataMemory[14]) * 256.0 + (float)(globalData->dataMemory[13]); if ((readerFToD - EPSILON) <= cardFToD) { found = 1; F = fi[Fi]; D = di[Di]; params->fTod = cardFToD; globalData->cards[(int)socket].FiDi = (Fi << 4) | Di; etus = (int)(cardFToD + 0.5); params->A = (etus & 0xFF00) >> 8; params->B = etus & 0x00FF; } if (!found) return ASE_READER_NO_MATCHING_PARAMS; params->protocol = protocol; params->N = N; if (protocol == ATR_PROTOCOL_TYPE_T0) { WWT = WI * 960 * D + ASE_READER_ETU_DELTA; params->CWT[0] = (uchar)((WWT & 0x00FF0000) >> 16); params->CWT[1] = (uchar)((WWT & 0x0000FF00) >> 8); params->CWT[2] = (uchar)(WWT & 0x000000FF); /* for T=0 they are identical */ params->BWT[0] = params->CWT[0]; params->BWT[1] = params->CWT[1]; params->BWT[2] = params->CWT[2]; } else { /* T = 1 */ WWT = 11 + (1 << GetT1CWI(atr)) + ASE_READER_ETU_DELTA; params->CWT[0] = (uchar)((WWT & 0x00FF0000) >> 16); params->CWT[1] = (uchar)((WWT & 0x0000FF00) >> 8); params->CWT[2] = (uchar)(WWT & 0x000000FF); etuFactor = (int)((float)(372.0 / cardFToD) + 0.5); if (etuFactor == 0) etuFactor = 1; #ifdef ASE_DEBUG syslog(LOG_INFO, "MatchReaderParams: etuFactor = %d\n", etuFactor); #endif WWT = 11 + (1 << GetT1BWI(atr)) * 960 * etuFactor + ASE_READER_ETU_DELTA; params->BWT[0] = (uchar)((WWT & 0x00FF0000) >> 16); params->BWT[1] = (uchar)((WWT & 0x0000FF00) >> 8); params->BWT[2] = (uchar)(WWT & 0x000000FF); } #ifdef ASE_DEBUG syslog(LOG_INFO, "MatchReaderParams: freq = %d, A = %d, B = %d, WWT = %d, protocol = %d, N = %d\n", params->freq, params->A, params->B, WWT, params->protocol, params->N); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int PPS (reader* globalData, char socket, uchar protocol, uchar* PPS1, uchar* PPS2, uchar* PPS3) { int retVal, len, actual, PPS1echoed, PPS2echoed, PPS3echoed; uchar request[6], response[6]; uchar PPSSreq, PPS0req, PCKreq, checksum; #ifdef ASE_DEBUG int i; syslog(LOG_INFO, "\n PPS - Enter - protocol = %d\n", protocol); #endif PPSSreq = request[0] = 0xFF; PPS0req = request[1] = 0x00 | protocol; /* PPS1 must always appear -> if not passed as a parameter, take from the globalData!!! otherwise, we propose to work with Fd and Dd - and that's not usually the intention */ /* if (PPS1) */ PPS0req = request[1] = PPS0req | 0x10; if (PPS2) PPS0req = request[1] = PPS0req | 0x20; if (PPS3) PPS0req = request[1] = PPS0req | 0x40; PCKreq = request[0] ^ request[1]; len = 2; if (PPS1) { request[len] = *PPS1; } else { request[len] = globalData->cards[(int)socket].FiDi; } PCKreq ^= request[len]; len++; if (PPS2) { request[len] = *PPS2; PCKreq ^= request[len]; len++; } if (PPS3) { request[len] = *PPS3; PCKreq ^= request[len]; len++; } request[len] = PCKreq; len++; if ((retVal = cardCommandInit(globalData, socket, 0))) return retVal; /* init the protocol if it's a PPS to T=1 */ if (protocol == ATR_PROTOCOL_TYPE_T1) T1InitProtocol(globalData, socket, 0); retVal = PPSTransact(globalData, socket, (char*)request, len, (char*)response, &actual); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "PPS - Error!.\n"); #endif return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, "PPS: response = "); for (i = 0 ; i < actual ; ++i) syslog(LOG_INFO, "0x%x%x ", PRINT_CHAR(response[i])); syslog(LOG_INFO, "\n"); #endif /* parse the reuslt */ if (actual < 3) /* must return at least 3 bytes */ return ASE_PPS_FAILED; len = 2; if (response[0] == PPSSreq) { /* PPSS */ checksum = response[0]; if ((response[1] & 0x0F) == (PPS0req & 0x0F)) { /* PPS0 */ checksum ^= response[1]; PPS1echoed = response[1] & 0x10; PPS2echoed = response[1] & 0x20; PPS3echoed = response[1] & 0x40; if (PPS1echoed) { /* if (PPS1 && response[len] == *PPS1) // if echoed, should be identical */ if (response[len] == request[2]) /* if echoed, should be identical */ checksum ^= response[len]; else return ASE_PPS_FAILED; len++; } if (PPS2echoed) { if (PPS2 && response[len] == *PPS2) /* if echoed, should be identical */ checksum ^= response[len]; else return ASE_PPS_FAILED; len++; } if (PPS3echoed) { if (PPS3 && response[len] == *PPS3) /* if echoed, should be identical */ checksum ^= response[len]; else return ASE_PPS_FAILED; len++; } if (response[len] == checksum) { if (!PPS1echoed) return ASE_PPS_DEFAULT_USED; return ASE_OK; } else return ASE_PPS_FAILED; } else return ASE_PPS_FAILED; } else return ASE_PPS_FAILED; } /***************************************************************************** * *****************************************************************************/ static int DoPPS (reader* globalData, char socket, struct card_params* params, uchar protocol, int voltage) { int retVal; ATR* atr = &(globalData->cards[(int)socket].atr); float cardFToD; float readerFToD; uchar PPS1; int cardDi = GetDi(atr), cardFi = GetFi(atr), divisionFactor; long cardClock = fs[cardFi], myClock; cardClock = (cardClock >= 16000000 ? 16000000 : cardClock >= 8000000 ? 8000000 : 4000000); myClock = cardClock; divisionFactor = (myClock == 4000000 ? 1 : myClock == 8000000 ? 2 : 4); #ifdef ASE_DEBUG syslog(LOG_INFO, "DoPPS: initial clock = %d\n", (int)myClock); #endif /* check to see if the card parameters are supported by the reader: if readerFToD is smaller than cardFToD */ readerFToD = (float)(globalData->dataMemory[14]) * 256.0 + (float)(globalData->dataMemory[13]); while (myClock >= 4000000) { cardDi = GetDi(atr); while (cardDi >= 1) { /* use only permitted values */ if (cardDi != 7 && cardDi <= 9) { /* calculate the card's f/d factor */ cardFToD = GetFToDFactor(cardFi, cardDi); if (divisionFactor != 1) cardFToD /= (float)divisionFactor; #ifdef ASE_DEBUG syslog(LOG_INFO, "DoPPS: card Fi = %d, Di = %d, F = %d, D = %d cardFToD = %f\n", cardFi, cardDi, fi[cardFi], di[cardDi], cardFToD); #endif if ((readerFToD - EPSILON) <= cardFToD) { #ifdef ASE_DEBUG syslog(LOG_INFO, "DoPPS: F = %d, D = %d\n", cardFi, cardDi); #endif PPS1 = (cardFi << 4) | cardDi; retVal = PPS(globalData, socket, protocol, &PPS1, NULL, NULL); if (retVal == ASE_OK) { /* PPS succeeded - compute the reader's params */ retVal = MatchReaderParams(globalData, socket, params, atr, cardFi, cardDi, GetWI(atr), GetN(atr), protocol); /* force the reader's clock to current clock */ params->freq = (myClock == 16000000 ? 0 : myClock == 8000000 ? 1 : 2); return retVal; } else { /* PPS failed */ #ifdef ASE_DEBUG syslog(LOG_INFO, "DoPPS: PPS failed - retVal = %d.\n", retVal); #endif myClock /= 2; divisionFactor /= 2; /* to exit the do-while loop over cardDi */ cardDi = 0; } } /* if */ } /* if */ cardDi--; } /* while (cardDi >= 1) */ } /* while clock */ #ifdef ASE_DEBUG syslog(LOG_INFO, "\n********DoPPS: No parameters found in PPS - default parameters will be used.\n\n"); #endif /* proceed with default baudrate - it must succeed */ MatchReaderParams(globalData, socket, params, atr, 1 /*Fi*/, 1 /*Di*/, GetWI(atr), GetN(atr), protocol); usleep(10000); /* wait at least 10ms between two cold resets */ /* must do a Cold Reset before proceeding with default values */ return CardPowerOn(globalData, socket, 0, voltage); } /***************************************************************************** * *****************************************************************************/ int InitCard (reader* globalData, char socket, char coldReset, char* protocol) { int retVal, actual, working = 0, retryTimes = 3, voltage = 3; uchar s[300], r[300]; struct card_params params; double freq, wwt; ATR* atr = &(globalData->cards[(int)socket].atr); // bit 0 -> 5V, bit 1 -> 3V, bit 2 -> 1.8V support uchar readerVoltage = globalData->dataMemory[9]; GetDefaultReaderParams(globalData, ¶ms); ////////////////// retVal = SetCardParameters(globalData, socket, params); /* Check to see if we have a card in the socket */ if (globalData->cards[(int)socket].status) { globalData->cards[(int)socket].cwt = 3000000; /* 3sec */ globalData->cards[(int)socket].activeProtocol = ATR_PROTOCOL_TYPE_T0; /* Call CardPowerOn to do a cold reset. Store and parse the ATR returned. (first call it with 3V and if no answer is returned, try with 5V) */ if (coldReset) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n Trying CardPowerOn with %dV\n\n", voltage); #endif retVal = CardPowerOn(globalData, socket, 0, voltage); /* if the card supports 1.8V and the reader too - > switch to 1.8V */ if (retVal == ASE_OK && (GetClassIndicator(atr) & 0x04) && (readerVoltage & 0x04)) { voltage = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with %dV classIndicator = %d\n\n", voltage,(GetClassIndicator(atr) & 0x01)); #endif usleep(10000); /* wait at least 10ms between two cold resets */ retVal = CardPowerOn(globalData, socket, 0, voltage); if (retVal < 0) { voltage = 3; /* return to 3V since this already works */ usleep(10000); #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with %dV classIndicator = %d\n\n", voltage,(GetClassIndicator(atr) & 0x01)); #endif retVal = CardPowerOn(globalData, socket, 0, voltage); } } else { /* if the card supports 3V and the reader too -> we're done */ if (retVal == ASE_OK && (GetClassIndicator(atr) & 0x02) && (readerVoltage & 0x02)) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n 3V it is\n\n"); #endif } /* if the card supports only 5V and the reader doesnt -> we cannot power on this card */ if (retVal == ASE_OK && !(GetClassIndicator(atr) & 0x02) && (GetClassIndicator(atr) & 0x01) && !(readerVoltage & 0x01)) return ASE_READER_CARD_REJECTED; } /* We should switch to 5V if either we didnt get a valid atr or the class indicator in the atr supports 5V (class A) and the reader too */ /* NOTE: we check here that the card doesnt support 3V so that we dont enter the cond if we're done */ if (retVal < 0 || (!(GetClassIndicator(atr) & 0x02) && (GetClassIndicator(atr) & 0x01) && (readerVoltage & 0x01))) { voltage = 5; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with %dV classIndicator = %d\n\n", voltage,(GetClassIndicator(atr) & 0x01)); #endif usleep(10000); /* wait at least 10ms between two cold resets */ retVal = CardPowerOn(globalData, socket, 0, voltage); /* if the card supports 1.8V and the reader too - > switch to 1.8V */ if (retVal == ASE_OK && (GetClassIndicator(atr) & 0x04) && (readerVoltage & 0x04)) { voltage = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with %dV classIndicator = %d\n\n", voltage,(GetClassIndicator(atr) & 0x01)); #endif usleep(10000); /* wait at least 10ms between two cold resets */ retVal = CardPowerOn(globalData, socket, 0, voltage); if (retVal < 0) { voltage = 5; /* return to 5V since this already works */ usleep(10000); #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with %dV classIndicator = %d\n\n", voltage,(GetClassIndicator(atr) & 0x01)); #endif retVal = CardPowerOn(globalData, socket, 0, voltage); } } if (retVal < 0) { voltage = 5; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with 2BUS memory card\n\n"); #endif retVal = CardPowerOn(globalData, socket, 0x12, voltage); if (retVal < 0 || (atr->data[0] != 0xA2 && atr->data[0] != 0x92)) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with I2C memory card\n\n"); #endif retVal = CardPowerOn(globalData, socket, 0x21, voltage); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } /* To check if this card is supported by the reader, we send a read command. If the command doesnt succeed, we reject the card. */ { unsigned char curStatus = globalData->cards[(int)socket].status; globalData->cards[(int)socket].memCard.memType = MEM_CARD_MAIN_MEM_MODE; globalData->cards[(int)socket].status = 2; /* temporarilly */ globalData->cards[(int)socket].memCard.protocolType = PROTOCOL_MEM_I2C; s[0] = 0x0; s[1] = 0xB0; s[2] = 0x0; s[3] = 0x0; s[4] = 0x4; retVal = MemoryCardCommand(globalData, socket, s, 5, r, &actual); if (retVal < 0 || (actual >= 2 && r[actual - 2] != 0x90)) { // try with XI2C #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with XI2C memory card\n\n"); #endif params.protocol = 0x22; retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { globalData->cards[(int)socket].status = curStatus; return ASE_READER_CARD_REJECTED; } { globalData->cards[(int)socket].memCard.protocolType = PROTOCOL_MEM_XI2C; s[0] = 0x0; s[1] = 0xB0; s[2] = 0x0; s[3] = 0x0; s[4] = 0x4; retVal = MemoryCardCommand(globalData, socket, s, 5, r, &actual); globalData->cards[(int)socket].status = curStatus; if (retVal < 0 || (actual >= 2 && r[actual - 2] != 0x90)) { return ASE_READER_CARD_REJECTED; } } globalData->cards[(int)socket].status = curStatus; return ASE_READER_CARD_REJECTED; } globalData->cards[(int)socket].status = curStatus; } } globalData->cards[(int)socket].activeProtocol = ATR_PROTOCOL_TYPE_RAW; } } } /* Warm reset */ else { retVal = CPUCardReset(globalData, socket); if (retVal < 0) { return ASE_READER_NOT_CPU_CARD; } } /* Check if it's a memory card */ if (globalData->cards[(int)socket].activeProtocol == ATR_PROTOCOL_TYPE_RAW) { if ( atr->data[0] == 0xA2 /*&& atr->data[1] == 0x13 && atr->data[2] == 0x10 && atr->data[3] == 0x91*/) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\nInitCard - this is a 2BUS card\n\n"); #endif params.protocol = 0x11; /* 2BUS */ globalData->cards[(int)socket].memCard.protocolType = PROTOCOL_MEM_2BUS; } else if ( atr->data[0] == 0x92) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\nInitCard - this is a 3BUS card\n\n"); #endif params.protocol = 0x12; /* 3BUS */ globalData->cards[(int)socket].memCard.protocolType = PROTOCOL_MEM_3BUS; } else { /* X/I2C */ #ifdef ASE_DEBUG syslog(LOG_INFO, "\nInitCard - this is an I2C card\n\n"); #endif params.protocol = 0x21; globalData->cards[(int)socket].memCard.protocolType = PROTOCOL_MEM_I2C; } retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } /* set ATR to dummy value */ memset(atr, 0x00, sizeof(ATR)); /* atr->data[0] = 0x3B; atr->data[1] = 0x00; atr->length = 2; */ /* set bwt and cwt */ globalData->cards[(int)socket].cwt = globalData->cards[(int)socket].bwt = 1510000; /* ~1.5sec */ globalData->cards[(int)socket].memCard.memType = MEM_CARD_MAIN_MEM_MODE; globalData->cards[(int)socket].status = 2; /* card is powered on and ready for work */ return ASE_OK; } /* Do the following until a working state has been found, or after retrying enough times: */ while (!working && retryTimes) { /* In SPECIFIC_MODE, try to match the reader params to that of the card */ if (GetCurrentMode(atr) == SPECIFIC_MODE) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n***** SPECIFIC_MODE: Fi = %d, Di = %d, WI = %d, N = %d, protocol = %d\n\n", GetFi(atr), GetDi(atr), GetWI(atr), GetN(atr), GetSpecificModeProtocol(atr)); #endif globalData->cards[(int)socket].activeProtocol = GetSpecificModeProtocol(atr); retVal = MatchReaderParams(globalData, socket, ¶ms, atr, GetFi(atr), GetDi(atr), GetWI(atr), GetN(atr), globalData->cards[(int)socket].activeProtocol); if (retVal < 0) { /* reader params could not be matched */ /* check if a warm reset can change modes */ if (CapableOfChangingMode(atr)) { retVal = CPUCardReset(globalData, socket); /* try a warm reset */ if (retVal < 0) { return ASE_READER_CARD_REJECTED; } } else { return ASE_READER_CARD_REJECTED; } } else { /* a match found */ retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } working = 1; } } /* In NEGOTIABLE_MODE, if we cannot match the reader params to that of the card, we can do a PPS */ else { /* NEGOTIABLE_MODE */ #ifdef ASE_DEBUG syslog(LOG_INFO, "\n***** NEGOTIABLE_MODE: Fi = %d, Di = %d, WI = %d, N = %d, protocol = %d\n\n", GetFi(atr), GetDi(atr), GetWI(atr), GetN(atr), (protocol ? *protocol : GetFirstOfferedProtocol(atr))); #endif /* if the values are the default, no PPS should be done */ if ( (GetFi(atr) == 0 || GetFi(atr) == 1) && GetDi(atr) == 1) { #ifdef ASE_DEBUG syslog(LOG_INFO, "DEFAULT PARAMETERS will be used\n"); #endif globalData->cards[(int)socket].activeProtocol = (protocol ? *protocol : GetFirstOfferedProtocol(atr)); retVal = MatchReaderParams(globalData, socket, ¶ms, atr, GetFi(atr), GetDi(atr), GetWI(atr), GetN(atr), globalData->cards[(int)socket].activeProtocol); if (retVal < 0) return ASE_READER_CARD_REJECTED; else { retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } working = 1; } } else { globalData->cards[(int)socket].activeProtocol = (protocol ? *protocol : GetFirstOfferedProtocol(atr)); usleep(10000); /* wait at least 10ms before sending PPS */ retVal = DoPPS(globalData, socket, ¶ms, globalData->cards[(int)socket].activeProtocol, voltage); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } else { /* success */ retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } working= 1; } } } retryTimes--; } if (working) { globalData->cards[(int)socket].status = 2; /* card is powered on and ready for work */ /* compute the character waiting time max delay */ wwt = params.CWT[0] * 65536 + params.CWT[1] * 256 + params.CWT[2]; freq = globalData->dataMemory[12] * 256 + globalData->dataMemory[11]; freq *= 1000; freq /= (params.freq == 0 ? 1.0 : params.freq == 1 ? 2.0 : params.freq == 2 ? 4.0 : 8.0); globalData->cards[(int)socket].cwt = (long)( (params.fTod * wwt) / freq * 1000000.0 ); /* in microsec */ /* compute the max delay for the first response character */ wwt = params.BWT[0] * 65536 + params.BWT[1] * 256 + params.BWT[2]; freq = globalData->dataMemory[12] * 256 + globalData->dataMemory[11]; freq *= 1000; freq /= (params.freq == 0 ? 1.0 : params.freq == 1 ? 2.0 : params.freq == 2 ? 4.0 : 8.0); globalData->cards[(int)socket].bwt = (long)( (params.fTod * wwt) / freq * 1000000.0 ); /* in microsec */ #ifdef ASE_DEBUG syslog(LOG_INFO, "InitCard: protocol = %d cwt = %d bwt = %d (each 1000 == 1ms)\n", globalData->cards[(int)socket].activeProtocol, (int)globalData->cards[(int)socket].cwt, (int)globalData->cards[(int)socket].bwt); #endif /* if it's T=1, the protocol must be inited */ if (globalData->cards[(int)socket].activeProtocol == ATR_PROTOCOL_TYPE_T1) T1InitProtocol(globalData, socket, 1); return ASE_OK; } else { return ASE_READER_CARD_REJECTED; } } return ASE_READER_NO_CARD_ERROR; } asedriveiiie-3.7/asedriveiiie-usb/0000700000175000017500000000000011441363313017541 5ustar rousseaurousseauasedriveiiie-3.7/asedriveiiie-usb/T1Protocol.h0000755000175000017500000000362011265303433021737 0ustar rousseaurousseau#ifndef __T1PROTOCOL_H #define __T1PROTOCOL_H typedef unsigned char uchar; /***************************************************************************** * *****************************************************************************/ #define T1_BLOCK_MAX_SIZE 259 #define T1_BLOCK_INF_MAX_SIZE 254 #define ATHENA_IFSC_MAX_SIZE 254 /* PCBs */ #define T1_BLOCK_I 0x00 #define T1_BLOCK_R 0x80 #define T1_BLOCK_S 0xC0 #define T1_BLOCK_S_RESYNCH_REQ 0xC0 #define T1_BLOCK_S_RESYNCH_RES 0xE0 #define T1_BLOCK_S_IFS_REQ 0xC1 #define T1_BLOCK_S_IFS_RES 0xE1 #define T1_BLOCK_S_ABORT_REQ 0xC2 #define T1_BLOCK_S_ABORT_RES 0xE2 #define T1_BLOCK_S_WTX_REQ 0xC3 #define T1_BLOCK_S_WTX_RES 0xE3 #define T1_BLOCK_S_VPP_ERR 0xE4 /***************************************************************************** * *****************************************************************************/ #define PROTOCOL_T1_OK 0 /* Command OK */ #define PROTOCOL_T1_ICC_ERROR -2000 /* ICC comunication error */ #define PROTOCOL_T1_ERROR -2001 /* T=1 Protocol Error */ #define T1_ABORT_RECEIVED -2002 #define T1_RESYNCH_RECEIVED -2003 #define T1_VPP_ERROR_RECEIVED -2004 #define PROTOCOL_T1_SEND_I_BLOCK 1 #define PROTOCOL_T1_SEND_R_BLOCK 2 #define PROTOCOL_T1_SEND_S_BLOCK 3 typedef struct { uchar data[T1_BLOCK_MAX_SIZE]; int len; } T1Block; typedef struct { int ifsc; /* Information field size for the ICC */ int edc; /* Type of error detection code */ uchar ns; /* Send sequence number */ uchar nsCard; /* Send sequence number of the card */ T1Block sendBlock, recBlock; } T1Protocol; #endif asedriveiiie-3.7/asedriveiiie-usb/ReaderCommands.c0000755000175000017500000010172211441350651022612 0ustar rousseaurousseau#include "Ase.h" /***************************************************************************** * *****************************************************************************/ //#define ASE_PACKET_TYPE(pid, cnt, dst) (pid | cnt << 2 | dst) #define ASE_PACKET_TYPE(pid, cnt, dst) (pid | dst) #define ASE_STOP_BYTE(cnt, dst) (0x60 | cnt << 2 | dst) #define T0_DATA_CHUNK_SIZE 28 #define T1_DATA_CHUNK_SIZE 32 /***************************************************************************** * *****************************************************************************/ static void GetDefaultReaderParams (reader* globalData, struct card_params* params) { params->protocol = 0; params->N = 0x03; params->CWT[0] = 0x00; params->CWT[1] = 0x25/*0x85*/; params->CWT[2] = 0x85/*0xF0*/; params->BWT[0] = 0x00; params->BWT[1] = 0x3A/*0x38*/; params->BWT[2] = 0x34/*0xA4*/; /* 372 */ params->A = 0x01; params->B = 0x74; params->freq = 0x02; } /***************************************************************************** * *****************************************************************************/ /* returns 0 on success */ int cardCommandInit (reader* globalData, char socket, char needToBePoweredOn) { if (!globalData->cards[(int)socket].status) { return ASE_READER_NO_CARD_ERROR; } if (needToBePoweredOn && globalData->cards[(int)socket].status != 2) { return ASE_READER_CARD_NOT_POWERED_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int readerCommandInit (reader* globalData, char needToBeStarted) { if (needToBeStarted && !globalData->readerStarted) { return ASE_ERROR_COMMAND; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static void lock_mutex (reader* globalData) { int retVal; #ifdef ASE_DEBUG /* syslog(LOG_INFO, " Trying...");*/ #endif retVal = pthread_mutex_lock(&(globalData->semaphore)); if (retVal != 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "Error! - in pthread_mutex_lock\n"); #endif } #ifdef ASE_DEBUG /* syslog(LOG_INFO, "Entering mutex\n");*/ #endif } /***************************************************************************** * *****************************************************************************/ static void unlock_mutex (reader* globalData) { int retVal; #ifdef ASE_DEBUG /* syslog(LOG_INFO, " Trying...");*/ #endif retVal = pthread_mutex_unlock(&(globalData->semaphore)); if (retVal != 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "Error! - in pthread_mutex_unlock\n"); #endif } #ifdef ASE_DEBUG /* syslog(LOG_INFO, "Leaving mutex\n");*/ #endif } /***************************************************************************** * *****************************************************************************/ int ReaderStartup (reader* globalData, char* response, int* len) { char cmd[4]; int retVal, i, retryTimes = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReaderStartup - Enter\n"); #endif if (globalData->readerStarted) { return ASE_ERROR_COMMAND; } globalData->readerStarted = 0; globalData->commandCounter = 1; globalData->cards[0].status = globalData->cards[0].ceei = globalData->cards[0].atr.length = 0; globalData->cards[1].status = globalData->cards[1].ceei = globalData->cards[1].atr.length = 0; globalData->cards[0].cwt = globalData->cards[1].cwt = 1500000; /* 1.5 sec */ globalData->cards[0].bwt = globalData->cards[1].bwt = 1500000; /* 1.5 sec */ /* init mutex */ retVal = pthread_mutex_init(&(globalData->semaphore), NULL); if (retVal != 0) return ASE_ERROR_COMMAND; //?????????? if ((retVal = readerCommandInit(globalData, 0))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x10; cmd[2] = 0x00; cmd[3] = cmd[0] ^ cmd[1] ^ cmd[2]; do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, 0, cmd2, 4, response, len, 1); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, 0, cmd, 4, response, len, 1); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); if (retVal < 0) { return retVal; } globalData->readerStarted = 1; /* copy response to the ASE data memory field */ /* first byte is communication data ??? */ for (i = 1 ; i < (*len) ; ++i) globalData->dataMemory[i - 1] = response[i]; #ifdef ASE_DEBUG syslog(LOG_INFO, " ReaderStartup - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int ReaderFinish (reader* globalData) { char cmd[4], ack; int retVal, actual, retryTimes = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReaderFinish - Enter\n"); #endif if ((retVal = readerCommandInit(globalData, 1))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x11; cmd[2] = 0x0; cmd[3] = cmd[0] ^ cmd[1] ^ cmd[2]; do { lock_mutex(globalData); retVal = sendControlCommand(globalData, 0, cmd, 4, &ack, &actual, 0); unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (ack != 0x20) { return parseStatus(ack); } globalData->readerStarted = 0; #ifdef ASE_DEBUG syslog(LOG_INFO, " ReaderFinish - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int GetStatus (reader* globalData, char* response, int* len) { char cmd[4]; int retVal, retryTimes = 2; /* syslog(LOG_INFO, "\n GetStatus - Enter\n"); */ if ((retVal = readerCommandInit(globalData, 1))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x16; cmd[2] = 0x0; cmd[3] = cmd[0] ^ cmd[1] ^ cmd[2]; do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, 0, cmd2, 4, response, len, 1); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, 0, cmd, 4, response, len, 1); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (response[0] & 0x01) { if (!(globalData->cards[0].status)) /* only if not powered on */ globalData->cards[0].status = 1; } else globalData->cards[0].status = 0; if (response[0] & 0x02) { if (!(globalData->cards[1].status)) /* only if not powered on */ globalData->cards[1].status = 1; } else globalData->cards[1].status = 0; /* syslog(LOG_INFO, " GetStatus - Exit\n"); */ return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int SetCardParameters (reader* globalData, char socket, struct card_params params) { char cmd[15], ack; int retVal, i, actual, retryTimes = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SetCardParameters - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 0))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x15; cmd[2] = 0x0B; cmd[3] = params.protocol; cmd[4] = params.N; cmd[5] = params.CWT[0]; cmd[6] = params.CWT[1]; cmd[7] = params.CWT[2]; cmd[8] = params.BWT[0]; cmd[9] = params.BWT[1]; cmd[10] = params.BWT[2]; cmd[11] = params.A; cmd[12] = params.B; cmd[13] = params.freq; cmd[14] = cmd[0]; for (i = 1 ; i < 14 ; i++) cmd[14] ^= cmd[i]; do { lock_mutex(globalData); retVal = sendControlCommand(globalData, socket, cmd, 15, &ack, &actual, 0); unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (ack != 0x20) { return parseStatus(ack); } globalData->cards[(int)socket].cardParams = params; #ifdef ASE_DEBUG syslog(LOG_INFO, " SetCardParameters - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int CardPowerOn (reader* globalData, char socket, uchar cardType, uchar voltage) { char cmd[6], response[300]; int retVal, len, retryTimes = 2; ATR* atr = &(globalData->cards[(int)socket].atr); #ifdef ASE_DEBUG syslog(LOG_INFO, "\n CardPowerOn - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 0))) return retVal; /* GetDefaultReaderParams(globalData, ¶ms); retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return retVal; } */ cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x20; cmd[2] = 0x02; cmd[3] = cardType; cmd[4] = voltage; cmd[5] = cmd[0] ^ cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4]; /* CPU cards -> an open response should be receievd */ if (cardType == 0x00 || cardType == 0x01) { do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, response, &len, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, cmd, 6, response, &len, 0); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } retVal = ParseATR(globalData, socket, response, len); } /* 2/3BUS memory cards -> a close response should be received */ else if (cardType == 0x11 || cardType == 0x12) { memset(atr, 0x00, sizeof(ATR)); do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, response, &len, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, cmd, 6, response, &len, 0); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (retVal == ASE_OK) { if (len) { memcpy(atr->data, response, len); atr->length = len; } } } /* X/I2C memory cards -> an acknowledgement should be received */ else { memset(atr, 0x00, sizeof(ATR)); do { lock_mutex(globalData); retVal = sendControlCommand(globalData, socket, cmd, 6, response, &len, 0); unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } } if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " CardPowerOn - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int CPUCardReset (reader* globalData, char socket) { char cmd[4], response[300]; int retVal, len, retryTimes = 2; struct card_params params; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n CPUCardReset - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; GetDefaultReaderParams(globalData, ¶ms); retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return retVal; } cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x22; cmd[2] = 0x00; cmd[3] = cmd[0] ^ cmd[1] ^ cmd[2]; do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, response, &len, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, cmd, 4, response, &len, 0); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } retVal = ParseATR(globalData, socket, response, len); if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " CPUCardReset - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int CardPowerOff (reader* globalData, char socket) { char cmd[4], ack; int retVal, actual, retryTimes = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n CardPowerOff - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x21; cmd[2] = 0x0; cmd[3] = cmd[0] ^ cmd[1] ^ cmd[2]; do { lock_mutex(globalData); retVal = sendControlCommand(globalData, socket, cmd, 4, &ack, &actual, 0); unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (ack != 0x20) { return parseStatus(ack); } /* if the card is present, change the status to powered off */ if (globalData->cards[(int)socket].status) globalData->cards[(int)socket].status = 1; #ifdef ASE_DEBUG syslog(LOG_INFO, " CardPowerOff - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ /* on == 0x01, off == 0x00 */ int ChangeLedState (reader* globalData, char on) { char cmd[5], ack; int retVal, actual, retryTimes = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ChangeLedState - Enter\n"); #endif if ((retVal = readerCommandInit(globalData, 1))) return retVal; cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, 0); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x17; cmd[2] = 0x01; cmd[3] = on; cmd[4] = cmd[0] ^ cmd[1] ^ cmd[2] ^ cmd[3]; do { lock_mutex(globalData); retVal = sendControlCommand(globalData, 0, cmd, 5, &ack, &actual, 1); unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); // if during the 3 tries the command failed, return an error status if (retVal < 0) { return retVal; } if (ack != 0x20) { return parseStatus(ack); } #ifdef ASE_DEBUG syslog(LOG_INFO, " ChangeLedState - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int PPSTransact (reader* globalData, char socket, char* buffer, int len, char* outBuf, int* outBufLen) { int retVal; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n PPSTransact - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 0))) return retVal; retVal = CardCommand(globalData, socket, 0x43, (unsigned char*)buffer, len, (unsigned char*)outBuf, outBufLen); if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " PPSTransact - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int MemoryCardTransact (reader* globalData, char socket, char cmdType, uchar command, ushort address, uchar len, uchar* data, char* outBuf, int* outBufLen) { char cmd[BULK_BUFFER_SIZE]; uchar checksum, readByte; int retVal, i, actual; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n MemoryCardTransact - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n MemoryCardTransact - sending\n"); #endif cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = 0x25; cmd[2] = 5 + (cmdType == 0 ? len : 0); cmd[3] = cmdType; cmd[4] = command; cmd[5] = (address >> 8) & 0xFF; cmd[6] = address & 0xFF; cmd[7] = len; checksum = cmd[0] ^ cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5] ^ cmd[6] ^ cmd[7]; i = 0; if (cmdType == 0) { for (; i < len ; ++i) { cmd[i + 8] = data[i]; checksum ^= cmd[i + 8]; } } cmd[i + 8] = checksum; lock_mutex(globalData); /* send the command */ retVal = writeToReader(globalData, cmd, cmd[2] + 4, &actual); if (retVal < 0) { return retVal; } checksum = 0; /* read the Ack control byte or the close response packet type */ retVal = readResponse(globalData, socket, 1, (char*)(&readByte), &actual, 1000000); if (retVal < 0) { unlock_mutex(globalData); return retVal; } while ((readByte & 0xF0) != 0x10) { if ((readByte & 0xF0) == 0x20) { if (readByte != 0x20) { unlock_mutex(globalData); return parseStatus(readByte); } else break; } else if (isEvent(readByte)) { #ifdef ASE_DEBUG syslog(LOG_INFO, "MemoryCardTransact - Event 0x%x%x.\n", (readByte & 0xF0) >> 4, readByte & 0x0F); #endif parseEvent(globalData, socket, readByte); } retVal = readResponse(globalData, socket, 1, (char*)(&readByte), &actual, 1000000); if (retVal < 0) { unlock_mutex(globalData); return retVal; } } checksum ^= readByte; /* if readByte == 0x2x */ if ((readByte & 0xF0) == 0x20) { if (readByte != 0x20) { /* *outBufLen = 0; */ unlock_mutex(globalData); return parseStatus(readByte); } } /* ths response is a close response */ else if ((readByte & 0xF0) == 0x10) { if (readByte != 0x10) { unlock_mutex(globalData); return parseStatus(readByte); } /* read data length */ retVal = readResponse(globalData, socket, 1, (char*)(&readByte), &actual, 1000000); if (retVal < 0) { unlock_mutex(globalData); return retVal; } checksum ^= readByte; /* read data */ retVal = readResponse(globalData, socket, readByte, outBuf, outBufLen, 1000000); if (retVal < 0 || (*outBufLen) != readByte) { unlock_mutex(globalData); return retVal; } for (i = 0 ; i < *outBufLen ; ++i) checksum ^= outBuf[i]; /* read the checksum */ retVal = readResponse(globalData, socket, 1, (char*)(&readByte), &actual, 1000000); if (retVal < 0) { unlock_mutex(globalData); return retVal; } if (checksum != readByte) { unlock_mutex(globalData); return ASE_ERROR_CHECKSUM; } } unlock_mutex(globalData); #ifdef ASE_DEBUG syslog(LOG_INFO, " MemoryCardTransact - Exit\n\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int T0Read (reader* globalData, char socket, uchar* buffer, int len, uchar* outBuf, int* outBufLen) { int retVal; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n T0Read - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; retVal = CardCommand(globalData, socket, 0x41, buffer, len, outBuf, outBufLen); if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " T0Read - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int T0Write (reader* globalData, char socket, uchar* buffer, int len, uchar* outBuf, int* outBufLen) { int retVal; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n T0Write - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; retVal = CardCommand(globalData, socket, 0x40, buffer, len, outBuf, outBufLen); if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " T0Write - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int T1CPUCardTransact (reader* globalData, char socket, char* buffer, int len, char* outBuf, int* outBufLen) { int retVal; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n T1CPUCardTransact - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; retVal = CardCommand(globalData, socket, 0x42, (unsigned char*)buffer, len, (unsigned char*)outBuf, outBufLen); if (retVal < 0) { return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, " T1CPUCardTransact - Exit\n"); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int CardCommand (reader* globalData, char socket, char command, uchar* buffer, int len, uchar* outBuf, int* outBufLen) { char cmd[BULK_BUFFER_SIZE]; uchar checksum; int retVal = ASE_OK, i, retryTimes = 2; /* short format */ if (len <= 255) { cmd[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = command; cmd[2] = (uchar)len; checksum = cmd[0] ^ cmd[1] ^ cmd[2]; i = 0; for (; i < len ; ++i) { cmd[i + 3] = buffer[i]; checksum ^= cmd[i + 3]; } cmd[i + 3] = checksum; do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, (char*)outBuf, outBufLen, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, cmd, len + 4, (char*)outBuf, outBufLen, 0); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); } /* long format */ else { cmd[0] = ASE_PACKET_TYPE(0xD0, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd[1] = command; cmd[2] = (len >> 8) & 0xFF; cmd[3] = len & 0xFF; checksum = cmd[0] ^ cmd[1] ^ cmd[2] ^ cmd[3]; i = 0; for (; i < len ; ++i) { cmd[i + 4] = buffer[i]; checksum ^= cmd[i + 4]; } cmd[i + 4] = checksum; do { lock_mutex(globalData); /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, (char*)outBuf, outBufLen, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, cmd, len + 5, (char*)outBuf, outBufLen, 0); } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); } if (retVal < 0) { return retVal; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int SendIOCTL (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuf, int *outBufLen) { char ack = 0x00; int retVal, actual, retryTimes = 2, sendLen = *outBufLen; int dataLen, i; unsigned char cs = 0; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SendIOCTL - Enter sendLen = %d\n", sendLen); #endif if ((retVal = readerCommandInit(globalData, 1))) return retVal; // verify that inBuf has a valid reader command structure (including checksum) if (inBuf[0] != 0x50) return ASE_READER_PID_ERROR; // inBuf[1] is the command dataLen = inBuf[2]; if (dataLen != (inBufLen - 4 /*PID+CMD+LEN+CKM*/)) return ASE_READER_LEN_ERROR; for (i = 0 ; i < inBufLen ; ++i) cs ^= inBuf[i]; if (cs) return ASE_READER_CS_ERROR; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SendIOCTL - cmd struct ok\n"); #endif do { lock_mutex(globalData); if (sendLen == 2) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SendIOCTL - ControlCommand\n"); #endif retVal = sendControlCommand(globalData, 0, (char*)inBuf, inBufLen, &ack, &actual, 1); } else { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SendIOCTL - CloseResponseCommand retVal = %0x\n", retVal); #endif /* A Retry command should be sent */ if (retVal == ASE_ERROR_DATA_INCOMPLETE || retVal == ASE_ERROR_CHECKSUM) { char cmd2[4]; cmd2[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmd2[1] = 0x44; cmd2[2] = 0x0; cmd2[3] = cmd2[0] ^ cmd2[1] ^ cmd2[2]; retVal = sendCloseResponseCommand(globalData, socket, cmd2, 4, (char*)outBuf, outBufLen, 0); } /* The command should be re-sent to the reader */ else { retVal = sendCloseResponseCommand(globalData, socket, (char*)inBuf, inBufLen, (char*)outBuf, outBufLen, 0); } } unlock_mutex(globalData); retryTimes--; } while (retVal != ASE_OK && retryTimes); #ifdef ASE_DEBUG syslog(LOG_INFO, "\n SendIOCTL - retVal = %0x ack = %0x *outBufLen = %d\n", retVal, ack, *outBufLen); #endif // if during the 3 tries the command failed, return an error status if (retVal < 0) { // general error outBuf[0] = 0x6F; outBuf[1] = 0x00; *outBufLen = 2; return retVal; } if (sendLen == 2 && ack != 0x20) { // general error outBuf[0] = 0x6F; outBuf[1] = 0x00; return parseStatus(ack); } // success if (sendLen == 2) { outBuf[0] = 0x90; outBuf[1] = 0x00; } else { outBuf[(*outBufLen)++] = 0x90; outBuf[(*outBufLen)++] = 0x00; } #ifdef ASE_DEBUG syslog(LOG_INFO, " SendIOCTL - Exit\n"); #endif return ASE_OK; } asedriveiiie-3.7/asedriveiiie-usb/ChangeLog0000755000175000017500000000102211265303433021324 0ustar rousseaurousseauasedriveiiie-usb-3.6: ===================== - IFDHSetProtocolParameters does nothing when the protocol need not be changed. asedriveiiie-usb-3.5: ===================== - removed ifdhandler.h and added IFDHANDLERv2 to Makefile in order to support pcsc-lite-1.4.0 and above. asedriveiiieusb-3.4: ===================== - fixed and changed bundle names and Makefile scripts asedriveiiieusb-3.3: ===================== - add support for AseIIIeUSB KB asedriveiiie-3.7/asedriveiiie-usb/configure0000755000175000017500000000273411265303433021471 0ustar rousseaurousseau#!/bin/sh cd `dirname $0` USAGE=0 PREFIX=/usr USBDROPDIR= BUILD= PCSC_HEADERS= PCSC_LIBS= for p in $*; do v=${p#*=} case "$p" in --help) USAGE=1 ;; --prefix=*) PREFIX="$v" ;; --with-pcsc-drivers-dir=*) USBDROPDIR="$v" ;; --with-pcsc-headers=*) PCSC_HEADERS="$v" ;; --with-pcsc-libs=*) PCSC_LIBS="$v" ;; --build=*) BUILD="$v" ;; esac done if [ ${USAGE} != 0 ]; then echo -e "usage $0" echo -e "\t--help\t\t\tThis help." echo -e "\t--build=arch\t\tSet build architacture (gcc prefix), default empty." echo -e "\t--prefix=dir\t\tSet installation prefix, default /usr." echo -e "\t--with-pcsc-drivers-dir=dir\tSet pcsc drivers directory." echo -e "\t--with-pcsc-headers=dir\t\tSet manual pcsc headers directory." echo -e "\t--with-pcsc-libs=dir\t\tSet manual pcsc library dir." exit 1 fi if [ -z "$USBDROPDIR" ]; then USBDROPDIR=`pkg-config libpcsclite --variable=usbdropdir` fi if [ -z "$USBDROPDIR" ]; then echo "Cannot find pcsc drivers directory" exit 1 fi if [ -z "$PCSC_HEADERS" ]; then CFLAGS="$CFLAGS `pkg-config libpcsclite --cflags`" else CFLAGS="$CFLAGS -I${PCSC_HEADERS}" fi if [ -z "$PCSC_LIBS" ]; then LDFLAGS="$LDFLAGS `pkg-config libpcsclite --libs`" else LDFLAGS="$LDFLAGS -L${PCSC_LIBS} -lpcsclite" fi echo "PREFIX=${PREFIX}" > Makefile.inc echo "USBDROPDIR=${USBDROPDIR}" >> Makefile.inc echo "BUILD=${BUILD}" >> Makefile.inc echo "CFLAGS=${CFLAGS}" >> Makefile.inc echo "LDFLAGS=${LDFLAGS}" >> Makefile.inc exit 0 asedriveiiie-3.7/asedriveiiie-usb/README0000755000175000017500000000572711265303433020452 0ustar rousseaurousseau*************************************************************** Title : README Hardware: ASEDrive IIIe USB Smartcard Reader Company : Athena Smartcard Solutions, http://www.athena-scs.com Version : 3.6 LICENSE : See file LICENSE Required: gcc 2.7 or higher, Linux kernel 2.4 or higher *************************************************************** What you need: ================ 1) Get the latest version of PCSC Lite by David Corcoran. You can get the latest version of PCSC Lite from: http://www.linuxnet.com/middle.html Follow the instructions and install it on your computer. 2) The ifd-AseIIIeUSB driver uses the libusb library to access USB devices. It can be downloaded from: http://libusb.sourceforge.net/ You need to install this library and in particular its usb.h file which is needed in the driver's compilation under GNU/Linux. Installing the ASEDrive IIIe USB driver: =========================================== To complie this package from a Linux prompt use the following: # ./configure # make # make install The driver installs itself to /usr/local/pcsc/drivers by default. To change this edit the Makefile. This will create a shared library called ifd-AseIIIeUSB (under ifd-AseIIIeUSB.bundle/Contents/Linux) which is the library used to talk to the IFD Handler interface. You must be root to install all the files to their locations. Starting and testing: ======================= To start the pcsc daemon you'll need root privileges. # /usr/local/pcsc/bin/pcscd You should be able to communicate with the reader by now. There is a small test program called "testpcsc" that comes with the pcsc-lite package. Refer to the pcsc-lite's README for compilation instructions. This program tries to connect to the selected reader and to get the ATR. Notes: ======== - To see the driver's debug messages, add -DASE_DEBUG to CFLAGS in the Makefile. Recompile and rerun the installation script. Note that the messages are written to the system log (usually: /var/log/messages). - In order to use the USB ports your kernel needs to support usbdevfs. You should have the following results: $ grep usb /proc/devices 180 usb $ grep usb /proc/filesystems nodev usbdevfs nodev usbfs If it is not the case, you may have to recompile your kernel. More details are available at: http://www.linux-usb.org/ - If the reader fails to function, check if your system supports usb. To do so, check if /proc/bus/usb/ exists, and if yes "cd" into this directory. Run the command "cat devices" and check if the reader appears. If your system does not support usb, you may need to reinstall/reconfigure it. More details can be found at: /usr/src/linux/Documentation/usb/proc_usb_info.txt and at: http://linux-hotplug.sourceforge.net/ Questions: ============ For questions, please email at: support@athena-scs.com asedriveiiie-3.7/asedriveiiie-usb/atr.h0000755000175000017500000000277411265303433020530 0ustar rousseaurousseau#ifndef __ATR_H #define __ATR_H /***************************************************************************** * *****************************************************************************/ #define MAX_ATR_SIZE 33 #define UNKNOWN_PROTOCOL 20 #define SPECIFIC_MODE 1 #define NEGOTIABLE_MODE 2 #define ATR_MAX_SIZE 33 /* Maximum size of ATR byte array */ #define ATR_MAX_HISTORICAL 15 /* Maximum number of historical bytes */ #define ATR_MAX_PROTOCOLS 7 /* Maximun number of protocols */ #define ATR_MAX_IB 4 /* Maximum number of interface bytes per protocol */ #define ATR_PROTOCOL_TYPE_T0 0 /* Protocol type T=0 */ #define ATR_PROTOCOL_TYPE_T1 1 /* Protocol type T=1 */ #define ATR_PROTOCOL_TYPE_T2 2 /* Protocol type T=2 */ #define ATR_PROTOCOL_TYPE_T3 3 /* Protocol type T=3 */ #define ATR_PROTOCOL_TYPE_T14 14 /* Protocol type T=14 */ #define ATR_PROTOCOL_TYPE_T15 15 /* Protocol type T=15 */ #define ATR_PROTOCOL_TYPE_RAW 16 /* Memory Cards Raw Protocol */ /***************************************************************************** * *****************************************************************************/ typedef struct { unsigned char data[MAX_ATR_SIZE]; unsigned length; unsigned char TS; unsigned char T0; struct { unsigned char value; char present; } ib[ATR_MAX_PROTOCOLS][ATR_MAX_IB], TCK; int pn; /* protocol number */ unsigned char hb[ATR_MAX_HISTORICAL]; int hbn; } ATR; #endif asedriveiiie-3.7/asedriveiiie-usb/LinuxDefines.h0000755000175000017500000000313111265303433022323 0ustar rousseaurousseau#ifndef __Linux_Defines_h_ #define __Linux_Defines_h_ #define BOOL unsigned short #define bool unsigned short #define HANDLE unsigned long /* #ifndef BOOL typedef unsigned short BOOL; #endif typedef BOOL bool; typedef unsigned short USHORT; typedef unsigned char UCHAR; typedef UCHAR BYTE; typedef unsigned char* PUCHAR; typedef char* STR; typedef unsigned long ULONG; typedef short BOOLEAN; typedef ULONG RESPONSECODE; typedef ULONG* PULONG; typedef ULONG DWORD; typedef void* PVOID; typedef ULONG HANDLE; */ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef NULL #define NULL 0x0000 #endif /********************************************/ #ifndef MAX_BUFFER_SIZE #define MAX_BUFFER_SIZE 264 #endif #define MAX_ATR_SIZE 33 #define STATUS_SUCCESS 0x0000 #define STATUS_UNSUCCESSFUL 0x0001 #define STATUS_IO_TIMEOUT 0x0002 #define STATUS_DATA_ERROR 0x0004 #define STATUS_UNRECOGNIZED_MEDIA 0x0008 #define STATUS_BUFFER_TOO_SMALL 0x0010 #define STATUS_DEVICE_PROTOCOL_ERROR 0x0020 /***************************************************************************** * *****************************************************************************/ /* Packet IDs */ #define READER_ACK 0x20 #define READER_CLOSE_RESPONSE 0x10 #define READER_LONG_CLOSE_RESPONSE 0x90 #define HOST_COMMAND 0x50 #define HOST_LONG_COMMAND 0xD0 #endif asedriveiiie-3.7/asedriveiiie-usb/MemoryCards.h0000755000175000017500000000625311265303433022163 0ustar rousseaurousseau#ifndef __MEMEORY_CARDS_H #define __MEMEORY_CARDS_H /***************************************************************************** * *****************************************************************************/ #define MAIN_MEM 0 #define PROTECTED_MEM 1 #define PROTOCOL_MEM_2BUS 0 #define PROTOCOL_MEM_3BUS 1 #define PROTOCOL_MEM_I2C 2 #define PROTOCOL_MEM_XI2C 3 #define MEM_CARD_MAIN_MEM_MODE 1 #define MEM_CARD_PROT_MEM_MODE 2 typedef struct { char memType; char protocolType; } MemCard; /***************************************************************************** * *****************************************************************************/ #define MEM_CARD_OK 0 #define MEM_CARD_ERROR_CMD_STRUCT -3000 #define MEM_CARD_ERROR_APDU -3001 #define MEM_CARD_COMM_ERROR -3002 #define MEM_CARD_BLOCKED -3003 #define MEM_CARD_PROTOCOL_NOT_SUPPORTED -3004 #define MEM_CARD_INVALID_PARAMETER -3005 #define MEM_CARD_ILLEGAL_ADDRESS -3006 #define MEM_CARD_BAD_MODE -3007 #define MEM_CARD_VERIFY_FAILED -3008 #define MEM_CARD_NOT_VERIFIED -3009 #define MEM_CARD_WRONG_LENGTH -3010 #define MEM_CARD_WRONG_CLASS -3011 #define MEM_CARD_WRONG_INST -3012 #define MEM_CARD_FILE_NOT_FOUND -3013 #define MEM_CARD_WRITE_FAILED -3014 /***************************************************************************** * *****************************************************************************/ #define APDU_INS_SELECT 0xA4 #define APDU_INS_VERIFY 0x20 #define APDU_INS_CHANGE_PASSWORD 0x24 #define APDU_INS_READ_BINARY 0xB0 #define APDU_INS_WRITE_BINARY 0xD6 /***************************************************************************** * *****************************************************************************/ /* 2 Card commands definitions */ #define _2BUS_READ_DATA 0x30 #define _2BUS_UPDATE_DATA 0x38 #define _2BUS_READ_PBIT 0x34 #define _2BUS_PROTECT_DATA_COND 0x3C #define _2BUS_READ_SECURITY_MEM 0x31 #define _2BUS_UPDATE_SECURITY_MEM 0x39 #define _2BUS_COMPARE_VERIFICATION 0x33 /* 3 Card commands definitions */ #define _3BUS_UPDATE_AND_PROTECT 0x31 #define _3BUS_UPDATE_DATA 0x33 #define _3BUS_WRITE_PBIT_COND 0x30 #define _3BUS_READ_DATA 0x0E #define _3BUS_READ_DATA_AND_PBIT 0x0C #define _3BUS_WRITE_ERROR_COUNTER 0x32 #define _3BUS_VERIFY_PSC 0x0D /* 2 BUS Addresses */ #define _2BUS_MAX_ADDRESS 255 #define _2BUS_MAX_PROTECTED_ADDRESS 31 #define _2BUS_ERROR_COUNTER_ADDRESS 0 #define _2BUS_PSC_CODE_1_ADDRESS 1 #define _2BUS_PSC_CODE_2_ADDRESS 2 #define _2BUS_PSC_CODE_3_ADDRESS 3 #define _2BUS_PSC_SIZE 3 /* 3 BUS Addresses */ #define _3BUS_MAX_ADDRESS 1020 /* 1KByte card - 3 bytes */ #define _3BUS_ERROR_COUNTER_ADDRESS 1021 #define _3BUS_PSC_CODE_1_ADDRESS 1022 #define _3BUS_PSC_CODE_2_ADDRESS 1023 #define _3BUS_PSC_SIZE 2 #define _23BUS_ATR_SIZE 4 #define _23BUS_COMMAND_SIZE 3 #endif asedriveiiie-3.7/asedriveiiie-usb/50-pcscd-asedriveiiie.rules0000755000175000017500000000071211440456601024612 0ustar rousseaurousseau# udev rules to set the access rights of CCID smart card readers # so they can be used by pcscd # If not adding the device, go away ACTION!="add", GOTO="asedriveiiie_rules_end" SUBSYSTEM!="usb", GOTO="asedriveiiie_rules_end" ENV{DEVTYPE}!="usb_device", GOTO="asedriveiiie_rules_end" ATTRS{idVendor}=="0dc3", ATTRS{idProduct}=="0802", GROUP="pcscd" ATTRS{idVendor}=="0dc3", ATTRS{idProduct}=="1104", GROUP="pcscd" # All done LABEL="asedriveiiie_rules_end" asedriveiiie-3.7/asedriveiiie-usb/MemoryCards.c0000755000175000017500000010645611265303433022164 0ustar rousseaurousseau#include "Ase.h" /***************************************************************************** * *****************************************************************************/ #define MEM_CARD_READ_CHUNK_SIZE 29 #define MEM_CARD_WRITE_CHUNK_SIZE 23 /***************************************************************************** * *****************************************************************************/ static void AddSW1SW2 (int status, uchar* outBuf, int* outBufLen, uchar moreInfo) { switch (status) { case ASE_OK: outBuf[*outBufLen] = 0x90; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_COMM_ERROR: /* command failed */ case MEM_CARD_INVALID_PARAMETER: /* wrong file in select */ outBuf[*outBufLen] = 0x69; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_ILLEGAL_ADDRESS: outBuf[*outBufLen] = 0x6B; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_BAD_MODE: outBuf[*outBufLen] = 0x68; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_BLOCKED: outBuf[*outBufLen] = 0x69; (*outBufLen)++; outBuf[*outBufLen] = 0x83; (*outBufLen)++; break; case MEM_CARD_WRONG_LENGTH: outBuf[*outBufLen] = 0x67; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_WRONG_CLASS: outBuf[*outBufLen] = 0x6E; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_WRONG_INST: outBuf[*outBufLen] = 0x6D; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_FILE_NOT_FOUND: outBuf[*outBufLen] = 0x6A; (*outBufLen)++; outBuf[*outBufLen] = 0x82; (*outBufLen)++; break; case MEM_CARD_WRITE_FAILED: outBuf[*outBufLen] = 0x62; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; case MEM_CARD_VERIFY_FAILED: outBuf[*outBufLen] = 0x63; (*outBufLen)++; outBuf[*outBufLen] = (0xC0 | moreInfo); (*outBufLen)++; break; default: outBuf[*outBufLen] = 0x6F; (*outBufLen)++; outBuf[*outBufLen] = 0x00; (*outBufLen)++; break; } } ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// // 2BUS cards functions ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// /***************************************************************************** * *****************************************************************************/ static int _2BUSExecInCommand (reader* globalData, uchar socket, uchar cmdCode, ushort address, uchar len, uchar* outBuffer, int *outBufLen) { int retVal, actual = 0; retVal = MemoryCardTransact(globalData, socket, 1, cmdCode, address, len, NULL, (char*)outBuffer, &actual); *outBufLen += actual; if (retVal < 0 || actual != len) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _2BUSExecOutCommand (reader* globalData, uchar socket, uchar cmdCode, ushort address, uchar* data, uchar len, uchar* outBuffer, int *outBufLen) { int retVal; retVal = MemoryCardTransact(globalData, socket, 0, cmdCode, address, len, data, (char*)outBuffer, outBufLen); if (retVal < 0) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static void ArrangeBitsIntoBytes(uchar* bitsBuff, uchar* buff, ushort address, int len) { int bytesLen = (address + len + 7) / 8; unsigned char buffIndex = 0; unsigned char bitsCount = 0; unsigned char i, j; for (i = 0; i < bytesLen; i++) { for (j = 0; j < 8; j++) { if (bitsCount++ < address) continue; buff[buffIndex++] = ((bitsBuff[i] >> j) & 0x1); if (buffIndex >= len) return; } } } /***************************************************************************** * *****************************************************************************/ static int _2BUSReadData(reader* globalData, uchar socket, ushort address, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0, actual; ushort maxAddress = 0; uchar cmdCode = 0, mode = globalData->cards[socket].memCard.memType; uchar thisRead; ushort readLen = len; uchar bitsBuff[4]; /* for 2 bus cards, 32 protected bits */ uchar* readBuff = outBuffer; switch (mode) { case MEM_CARD_MAIN_MEM_MODE: if (address > _2BUS_MAX_ADDRESS) { retVal = MEM_CARD_ILLEGAL_ADDRESS; } else { maxAddress = _2BUS_MAX_ADDRESS; cmdCode = _2BUS_READ_DATA; } break; case MEM_CARD_PROT_MEM_MODE: if (address > _2BUS_MAX_PROTECTED_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _2BUS_MAX_PROTECTED_ADDRESS; cmdCode = _2BUS_READ_PBIT; /* address is DON'T CARE in this case */ readLen = 4; /* 4 bytes is 32 protections bits */ readBuff = bitsBuff; } break; default: retVal = MEM_CARD_BAD_MODE; break; } if (retVal == ASE_OK) { /* check if we are not trying to read too much */ if (/*mode != MEM_CARD_PROT_MEM_MODE &&*/ len > (maxAddress - address + 1)) retVal = MEM_CARD_WRONG_LENGTH; else { if (mode == MEM_CARD_PROT_MEM_MODE) retVal = _2BUSExecInCommand(globalData, socket, cmdCode, address, readLen, readBuff, &actual); else { while (counter < len && retVal == ASE_OK) { thisRead = (readLen > MEM_CARD_READ_CHUNK_SIZE ? MEM_CARD_READ_CHUNK_SIZE : readLen); retVal = _2BUSExecInCommand(globalData, socket, cmdCode, address + counter, thisRead, outBuffer + counter, outBufLen); counter += thisRead; readLen -= thisRead; } } if (retVal == ASE_OK) { *outBufLen = len; /* Put each bit into one memory byte at the user's buffer */ if (mode == MEM_CARD_PROT_MEM_MODE) ArrangeBitsIntoBytes(bitsBuff, outBuffer, address, *outBufLen); } } } /* if command failed, clean the output buffer */ if (retVal < 0) *outBufLen = 0; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _2BUSWriteData(reader* globalData, uchar socket, ushort address, uchar* data, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0, writeLen = len; ushort maxAddress = 0; uchar cmdCode = 0, thisWrite; uchar mode = globalData->cards[socket].memCard.memType; switch (mode) { case MEM_CARD_MAIN_MEM_MODE: if (address > _2BUS_MAX_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _2BUS_MAX_ADDRESS; cmdCode = _2BUS_UPDATE_DATA; } break; case MEM_CARD_PROT_MEM_MODE: if (address > _2BUS_MAX_PROTECTED_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _2BUS_MAX_PROTECTED_ADDRESS; cmdCode = _2BUS_PROTECT_DATA_COND; } break; default: retVal = MEM_CARD_BAD_MODE; break; } if (retVal == ASE_OK) { /* check if we are not trying to write too much */ if (len > (maxAddress - address + 1)) { retVal = MEM_CARD_WRONG_LENGTH; } else { while (counter < len && retVal == ASE_OK) { thisWrite = (writeLen > MEM_CARD_WRITE_CHUNK_SIZE ? MEM_CARD_WRITE_CHUNK_SIZE : writeLen); retVal = _2BUSExecOutCommand(globalData, socket, cmdCode, address + counter, data + counter, thisWrite, outBuffer, outBufLen); counter += thisWrite; writeLen -= thisWrite; } } } if (retVal < 0) retVal = MEM_CARD_WRITE_FAILED; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _2BUSVerifyPSC(reader* globalData, uchar socket, uchar* password, int len, uchar* outBuffer, int *outBufLen) { uchar errorCounter[4]; uchar dataToWrite, i, attempts, newAttempts; int retVal = ASE_OK, actual; if (len != _2BUS_PSC_SIZE) { AddSW1SW2(MEM_CARD_INVALID_PARAMETER, outBuffer, outBufLen, 0); return retVal; } /* Read Error Counter - address has no effect in this command */ actual = 4; retVal = _2BUSExecInCommand(globalData, socket, _2BUS_READ_SECURITY_MEM, 0, 4, errorCounter, &actual); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Count number of erased bits */ attempts = 0; for (i = 1; i != 0x08; i <<= 1) { if (errorCounter[0] & i) attempts++; } /* Check if the card is already blocked */ if (attempts == 0) { AddSW1SW2(MEM_CARD_BLOCKED, outBuffer, outBufLen, 0); return ASE_OK; } /* find an erased bit - only 3 bits in counter */ for (i = 1; i != 0x08; i <<= 1) { if (errorCounter[0] & i) { dataToWrite = (~i & errorCounter[0]); break; } } /* Write the erased bit */ retVal = _2BUSExecOutCommand(globalData, socket, _2BUS_UPDATE_SECURITY_MEM, _2BUS_ERROR_COUNTER_ADDRESS, &dataToWrite, 1, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Verify PSC data */ retVal = _2BUSExecOutCommand(globalData, socket, _2BUS_COMPARE_VERIFICATION, _2BUS_PSC_CODE_1_ADDRESS, password, _2BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Try to clear the error counter */ dataToWrite = 0xff; retVal = _2BUSExecOutCommand(globalData, socket, _2BUS_UPDATE_SECURITY_MEM, _2BUS_ERROR_COUNTER_ADDRESS, &dataToWrite, 1, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Read Error Counter - address has no effect in this command */ actual = 4; retVal = _2BUSExecInCommand(globalData, socket, _2BUS_READ_SECURITY_MEM, 0, 4, errorCounter, &actual); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Count number of erased bits */ newAttempts = 0; for (i = 1; i != 0x08; i <<= 1) { if (errorCounter[0] & i) newAttempts++; } if (newAttempts < attempts) AddSW1SW2(MEM_CARD_VERIFY_FAILED, outBuffer, outBufLen, newAttempts); else AddSW1SW2(ASE_OK, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _2BUSChangePSC (reader* globalData, uchar socket, uchar* password, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK; if (len != 2 * _2BUS_PSC_SIZE) { AddSW1SW2(MEM_CARD_INVALID_PARAMETER, outBuffer, outBufLen, 0); return retVal; } retVal = _2BUSVerifyPSC(globalData, socket, password, _2BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { return ASE_OK; } if (*outBufLen >= 2 && outBuffer[*outBufLen - 2] == 0x90 && outBuffer[*outBufLen - 1] == 0x00) { /* verification has succeeded - try to change the password */ retVal = _2BUSExecOutCommand(globalData, socket, _2BUS_UPDATE_SECURITY_MEM, _2BUS_PSC_CODE_1_ADDRESS, password + 3, _2BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { *outBufLen = 0; /* replace the 9000 of the Verify command */ AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } } return ASE_OK; } ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// // 3BUS cards functions ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// /***************************************************************************** * *****************************************************************************/ static int _3BUSExecInCommand (reader* globalData, uchar socket, uchar mode, uchar cmdCode, ushort address, uchar len, uchar* outBuffer, int *outBufLen) { int retVal, actual = 0; if (mode == MEM_CARD_MAIN_MEM_MODE) retVal = MemoryCardTransact(globalData, socket, 1, cmdCode, address, len, NULL, (char*)outBuffer, &actual); else retVal = MemoryCardTransact(globalData, socket, 2, cmdCode, address, len, NULL, (char*)outBuffer, &actual); *outBufLen += actual; if (retVal < 0 || actual != len) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _3BUSExecOutCommand (reader* globalData, uchar socket, uchar cmdCode, ushort address, uchar* data, uchar len, uchar* outBuffer, int *outBufLen) { int retVal; retVal = MemoryCardTransact(globalData, socket, 0, cmdCode, address, len, data, (char*)outBuffer, outBufLen); if (retVal < 0) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _3BUSReadData(reader* globalData, uchar socket, ushort address, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0, actual, i; ushort maxAddress = 0; uchar cmdCode = 0, mode = globalData->cards[socket].memCard.memType; uchar thisRead; ushort readLen = len; uchar temp[600]; switch (mode) { case MEM_CARD_MAIN_MEM_MODE: if (address > _3BUS_MAX_ADDRESS) { retVal = MEM_CARD_ILLEGAL_ADDRESS; } else { maxAddress = _3BUS_MAX_ADDRESS; cmdCode = _3BUS_READ_DATA; } break; case MEM_CARD_PROT_MEM_MODE: if (address > _3BUS_MAX_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _3BUS_MAX_ADDRESS; cmdCode = _3BUS_READ_DATA_AND_PBIT; readLen *= 2; /* we are reading 9 bits for each prot. bit stored in two bytes */ } break; default: retVal = MEM_CARD_BAD_MODE; break; } if (retVal == ASE_OK) { /* check if we are not trying to read too much */ if (len > (maxAddress - address + 1)) retVal = MEM_CARD_WRONG_LENGTH; else { if (mode == MEM_CARD_PROT_MEM_MODE) { int chunk = ((MEM_CARD_READ_CHUNK_SIZE % 2) ? (MEM_CARD_READ_CHUNK_SIZE - 1) : MEM_CARD_READ_CHUNK_SIZE); while (counter < 2 * len && retVal == ASE_OK) { thisRead = (readLen > chunk ? chunk : readLen); retVal = _3BUSExecInCommand(globalData, socket, mode, cmdCode, address + counter, thisRead, temp + counter, &actual); counter += thisRead; readLen -= thisRead; } /* remove the data bytes */ for (i = 0 ; i < len ; ++i) outBuffer[i] = temp[1 + i * 2]; } else { while (counter < len && retVal == ASE_OK) { thisRead = (readLen > MEM_CARD_READ_CHUNK_SIZE ? MEM_CARD_READ_CHUNK_SIZE : readLen); retVal = _3BUSExecInCommand(globalData, socket, mode, cmdCode, address + counter, thisRead, outBuffer + counter, outBufLen); counter += thisRead; readLen -= thisRead; } } *outBufLen = len; } } /* if command failed, clean the output buffer */ if (retVal < 0) *outBufLen = 0; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _3BUSWriteData(reader* globalData, uchar socket, ushort address, uchar* data, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0, writeLen = len; ushort maxAddress = 0; uchar cmdCode = 0, thisWrite; uchar mode = globalData->cards[socket].memCard.memType; switch (mode) { case MEM_CARD_MAIN_MEM_MODE: if (address > _3BUS_MAX_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _3BUS_MAX_ADDRESS; cmdCode = _3BUS_UPDATE_DATA; } break; case MEM_CARD_PROT_MEM_MODE: if (address > _3BUS_MAX_ADDRESS) retVal = MEM_CARD_ILLEGAL_ADDRESS; else { maxAddress = _3BUS_MAX_ADDRESS; cmdCode = _3BUS_WRITE_PBIT_COND; } break; default: retVal = MEM_CARD_BAD_MODE; break; } if (retVal == ASE_OK) { /* check if we are not trying to write too much */ if (len > (maxAddress - address + 1)) { retVal = MEM_CARD_WRONG_LENGTH; } else { while (counter < len && retVal == ASE_OK) { thisWrite = (writeLen > MEM_CARD_WRITE_CHUNK_SIZE ? MEM_CARD_WRITE_CHUNK_SIZE : writeLen); retVal = _3BUSExecOutCommand(globalData, socket, cmdCode, address + counter, data + counter, thisWrite, outBuffer, outBufLen); counter += thisWrite; writeLen -= thisWrite; } } } if (retVal < 0) retVal = MEM_CARD_WRITE_FAILED; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _3BUSVerifyPSC(reader* globalData, uchar socket, uchar* password, int len, uchar* outBuffer, int *outBufLen) { uchar errorCounter, dataToWrite, i, attempts, newAttempts; int retVal = ASE_OK, actual; if (len != _3BUS_PSC_SIZE) { AddSW1SW2(MEM_CARD_INVALID_PARAMETER, outBuffer, outBufLen, 0); return retVal; } /* Read Error Counter - address has no effect in this command */ retVal = _3BUSExecInCommand(globalData, socket, MEM_CARD_MAIN_MEM_MODE, _3BUS_READ_DATA, _3BUS_ERROR_COUNTER_ADDRESS, 1, &errorCounter, &actual); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Count number of erased bits */ attempts = 0; for (i = 1; i != 0; i <<= 1) { if (errorCounter & i) attempts++; } /* Check if the card is already blocked */ if (attempts == 0) { AddSW1SW2(MEM_CARD_BLOCKED, outBuffer, outBufLen, 0); return ASE_OK; } /* find an erased bit - only 3 bits in counter */ for (i = 1; i != 0; i <<= 1) { if (errorCounter & i) { dataToWrite = (~i & errorCounter); break; } } /* Write the erased bit */ retVal = _3BUSExecOutCommand(globalData, socket, _3BUS_WRITE_ERROR_COUNTER, _3BUS_ERROR_COUNTER_ADDRESS, &dataToWrite, 1, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Verify PSC data */ retVal = _3BUSExecOutCommand(globalData, socket, _3BUS_VERIFY_PSC, _3BUS_PSC_CODE_1_ADDRESS, password, _3BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Try to clear the error counter */ dataToWrite = 0xff; retVal = _3BUSExecOutCommand(globalData, socket, _3BUS_UPDATE_DATA, _3BUS_ERROR_COUNTER_ADDRESS, &dataToWrite, 1, outBuffer, outBufLen); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Read Error Counter - address has no effect in this command */ retVal = _3BUSExecInCommand(globalData, socket, MEM_CARD_MAIN_MEM_MODE, _3BUS_READ_DATA, _3BUS_ERROR_COUNTER_ADDRESS, 1, &errorCounter, &actual); if (retVal < 0) { AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /* Count number of erased bits */ newAttempts = 0; for (i = 1; i != 0; i <<= 1) { if (errorCounter & i) newAttempts++; } if (newAttempts < attempts) AddSW1SW2(MEM_CARD_VERIFY_FAILED, outBuffer, outBufLen, newAttempts); else AddSW1SW2(ASE_OK, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int _3BUSChangePSC (reader* globalData, uchar socket, uchar* password, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK; if (len != 2 * _3BUS_PSC_SIZE) { AddSW1SW2(MEM_CARD_INVALID_PARAMETER, outBuffer, outBufLen, 0); return retVal; } retVal = _3BUSVerifyPSC(globalData, socket, password, _3BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { return ASE_OK; } if (*outBufLen >= 2 && outBuffer[*outBufLen - 2] == 0x90 && outBuffer[*outBufLen - 1] == 0x00) { /* verification has succeeded - try to change the password */ retVal = _3BUSExecOutCommand(globalData, socket, _3BUS_UPDATE_DATA, _3BUS_PSC_CODE_1_ADDRESS, password + 2, _3BUS_PSC_SIZE, outBuffer, outBufLen); if (retVal < 0) { *outBufLen = 0; /* replace the 9000 of the Verify command */ AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } } return ASE_OK; } ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// // X/I2C cards functions ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// /***************************************************************************** * *****************************************************************************/ static int I2CExecInCommand (reader* globalData, uchar socket, uchar cmdCode, ushort address, uchar len, uchar* outBuffer, int *outBufLen) { int retVal, actual = 0; retVal = MemoryCardTransact(globalData, socket, 1, cmdCode, address, len, NULL, (char*)outBuffer, &actual); *outBufLen += actual; if (retVal < 0) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int I2CExecOutCommand (reader* globalData, uchar socket, uchar cmdCode, ushort address, uchar* data, uchar len, uchar* outBuffer, int *outBufLen) { int retVal; retVal = MemoryCardTransact(globalData, socket, 0, cmdCode, address, len, data, (char*)outBuffer, outBufLen); if (retVal < 0) { return MEM_CARD_COMM_ERROR; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int I2CReadData(reader* globalData, uchar socket, ushort address, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0; uchar cmdCode = 0; uchar thisRead; ushort readLen = len; cmdCode = 0xA0; while (counter < len && retVal == ASE_OK) { thisRead = (readLen > MEM_CARD_READ_CHUNK_SIZE ? MEM_CARD_READ_CHUNK_SIZE : readLen); retVal = I2CExecInCommand(globalData, socket, cmdCode, address + counter, thisRead, outBuffer + counter, outBufLen); counter += thisRead; readLen -= thisRead; } if (retVal == ASE_OK) *outBufLen = len; else *outBufLen = 0; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int I2CWriteData(reader* globalData, uchar socket, ushort address, uchar* data, int len, uchar* outBuffer, int *outBufLen) { int retVal = ASE_OK, counter = 0, writeLen = len; uchar cmdCode = 0, thisWrite; cmdCode = 0xA0; while (counter < len && retVal == ASE_OK) { thisWrite = (writeLen > MEM_CARD_WRITE_CHUNK_SIZE ? MEM_CARD_WRITE_CHUNK_SIZE : writeLen); retVal = I2CExecOutCommand(globalData, socket, cmdCode, address + counter, data + counter, thisWrite, outBuffer, outBufLen); counter += thisWrite; writeLen -= thisWrite; } if (retVal < 0) retVal = MEM_CARD_WRITE_FAILED; AddSW1SW2(retVal, outBuffer, outBufLen, 0); return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int VerifyAPDUValidStructure(uchar* inBuf, int inBufLen) { int lc, dataLen; if (inBufLen <= 3) return MEM_CARD_ERROR_CMD_STRUCT; /* APDU case 1 */ if (inBufLen == 4) return ASE_OK; /* APDU case 2 */ if (inBufLen == 5) return ASE_OK; /* APDU case 3 + 4 (len > 5 here) */ lc = inBuf[4]; if (lc == 0x00) /* lc should be positive */ return MEM_CARD_ERROR_CMD_STRUCT; dataLen = inBufLen - 5; /* dataLen is equal to lc in case 3 and equal to lc+1 in case 4 */ if (dataLen != lc && dataLen != (lc + 1)) return MEM_CARD_ERROR_CMD_STRUCT; return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int SendMemoryCommand (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen) { uchar INS = inBuf[1]; ushort address; char cardType = globalData->cards[socket].memCard.protocolType; int retVal = ASE_OK; *outBufLen = 0; /* check if the class is valid */ if (inBuf[0] != 0x00) { AddSW1SW2(MEM_CARD_WRONG_CLASS, outBuffer, outBufLen, 0); return retVal; } switch (INS) { case APDU_INS_SELECT: switch (cardType) { case PROTOCOL_MEM_2BUS: case PROTOCOL_MEM_3BUS: if (inBuf[5] == 0x3F && inBuf[6] == 0x00) globalData->cards[socket].memCard.memType = MEM_CARD_MAIN_MEM_MODE; else if (inBuf[5] == 0x3F && inBuf[6] == 0x01) globalData->cards[socket].memCard.memType = MEM_CARD_PROT_MEM_MODE; else AddSW1SW2(MEM_CARD_FILE_NOT_FOUND, outBuffer, outBufLen, 0); break; case PROTOCOL_MEM_I2C: case PROTOCOL_MEM_XI2C: if (inBuf[5] == 0x3F && inBuf[6] == 0x00) globalData->cards[socket].memCard.memType = MEM_CARD_MAIN_MEM_MODE; else AddSW1SW2(MEM_CARD_FILE_NOT_FOUND, outBuffer, outBufLen, 0); break; default: AddSW1SW2(MEM_CARD_COMM_ERROR, outBuffer, outBufLen, 0); break; } break; case APDU_INS_VERIFY: switch (cardType) { case PROTOCOL_MEM_2BUS: retVal = _2BUSVerifyPSC(globalData, socket, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_3BUS: retVal = _3BUSVerifyPSC(globalData, socket, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_I2C: case PROTOCOL_MEM_XI2C: default: AddSW1SW2(MEM_CARD_COMM_ERROR, outBuffer, outBufLen, 0); break; } break; case APDU_INS_CHANGE_PASSWORD: switch (cardType) { case PROTOCOL_MEM_2BUS: retVal = _2BUSChangePSC(globalData, socket, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_3BUS: retVal = _3BUSChangePSC(globalData, socket, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_I2C: case PROTOCOL_MEM_XI2C: default: AddSW1SW2(MEM_CARD_COMM_ERROR, outBuffer, outBufLen, 0); break; } break; case APDU_INS_READ_BINARY: address = (inBuf[2] << 8) | inBuf[3]; switch (cardType) { case PROTOCOL_MEM_2BUS: /* if p3==0 then we should read 256 bytes */ retVal = _2BUSReadData(globalData, socket, address, (inBuf[4] == 0 ? 256 : inBuf[4]), outBuffer, outBufLen); break; case PROTOCOL_MEM_3BUS: retVal = _3BUSReadData(globalData, socket, address, (inBuf[4] == 0 ? 256 : inBuf[4]), outBuffer, outBufLen); break; case PROTOCOL_MEM_I2C: case PROTOCOL_MEM_XI2C: retVal = I2CReadData(globalData, socket, address, (inBuf[4] == 0 ? 256 : inBuf[4]), outBuffer, outBufLen); break; default: AddSW1SW2(MEM_CARD_COMM_ERROR, outBuffer, outBufLen, 0); break; } break; case APDU_INS_WRITE_BINARY: address = (inBuf[2] << 8) | inBuf[3]; switch (cardType) { case PROTOCOL_MEM_2BUS: retVal = _2BUSWriteData(globalData, socket, address, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_3BUS: retVal = _3BUSWriteData(globalData, socket, address, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; case PROTOCOL_MEM_I2C: case PROTOCOL_MEM_XI2C: retVal = I2CWriteData(globalData, socket, address, inBuf + 5, inBuf[4], outBuffer, outBufLen); break; default: AddSW1SW2(MEM_CARD_COMM_ERROR, outBuffer, outBufLen, 0); break; } break; default: AddSW1SW2(MEM_CARD_WRONG_INST, outBuffer, outBufLen, 0); break; } return retVal; } /***************************************************************************** * *****************************************************************************/ int MemoryCardCommand (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen) { int retVal; retVal = VerifyAPDUValidStructure(inBuf, inBufLen); if (retVal < 0) { return MEM_CARD_ERROR_CMD_STRUCT; /* no SW1/SW2 here */ } retVal = SendMemoryCommand(globalData, socket, inBuf, inBufLen, outBuffer, outBufLen); if (retVal < 0) { return retVal; } return ASE_OK; } asedriveiiie-3.7/asedriveiiie-usb/atr.c0000755000175000017500000003116511441156635020525 0ustar rousseaurousseau#include "Ase.h" /***************************************************************************** * *****************************************************************************/ #define ATR_INTERFACE_BYTE_TA 0 /* Interface byte TAi */ #define ATR_INTERFACE_BYTE_TB 1 /* Interface byte TBi */ #define ATR_INTERFACE_BYTE_TC 2 /* Interface byte TCi */ #define ATR_INTERFACE_BYTE_TD 3 /* Interface byte TDi */ /***************************************************************************** * *****************************************************************************/ static int fi[16] = { 372, 372, 558, 744, 1116, 1488, 1860, 1, 1, 512, 768, 1024, 1536, 2048, 1, 1 }; static int di[16] = { 1, 1, 2, 4, 8, 16, 32, 1, 12, 20, 1, 1, 1, 1, 1, 1 }; static long fs[16] = {4000000, 5000000, 6000000, 8000000, 12000000, 16000000, 20000000, 0, 0, 5000000, 7500000, 10000000, 15000000, 20000000, 0, 0}; /*static int num_ib[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };*/ /* number of interface bytes */ /***************************************************************************** * *****************************************************************************/ int ParseATR (reader* globalData, char socket, char data[], int len) { uchar TDi; int pointer = 0, pn = 0, i; ATR* atr = &(globalData->cards[(int)socket].atr); memset(atr, 0x00, sizeof(ATR)); /* Store T0 and TS */ if (len < 1) return ASE_ERROR_ATR; atr->TS = data[0]; atr->data[pointer] = atr->TS; if (atr->TS == 0x03) atr->TS = 0x3F; if ((atr->TS != 0x3B) && (atr->TS != 0x3F)) return ASE_ERROR_ATR; if (len < 2) return ASE_ERROR_ATR; atr->T0 = data[1]; TDi = atr->T0; pointer = 1; atr->data[pointer] = atr->T0; /* Store number of historical bytes */ atr->hbn = TDi & 0x0F; /* TCK is not present by default */ (atr->TCK).present = 0; /* Extract interface bytes */ while (1) { /* Check TAi is present */ if (TDi & 0x10) { pointer++; if (len < pointer) return ASE_ERROR_ATR; atr->ib[pn][ATR_INTERFACE_BYTE_TA].value = data[pointer]; atr->ib[pn][ATR_INTERFACE_BYTE_TA].present = 1; atr->data[pointer] = atr->ib[pn][ATR_INTERFACE_BYTE_TA].value; } else atr->ib[pn][ATR_INTERFACE_BYTE_TA].present = 0; /* Check TBi is present */ if (TDi & 0x20) { pointer++; if (len < pointer) return ASE_ERROR_ATR; atr->ib[pn][ATR_INTERFACE_BYTE_TB].value = data[pointer]; atr->ib[pn][ATR_INTERFACE_BYTE_TB].present = 1; atr->data[pointer] = atr->ib[pn][ATR_INTERFACE_BYTE_TB].value; } else atr->ib[pn][ATR_INTERFACE_BYTE_TB].present = 0; /* Check TCi is present */ if (TDi & 0x40) { pointer++; if (len < pointer) return ASE_ERROR_ATR; atr->ib[pn][ATR_INTERFACE_BYTE_TC].value = data[pointer]; atr->ib[pn][ATR_INTERFACE_BYTE_TC].present = 1; atr->data[pointer] = atr->ib[pn][ATR_INTERFACE_BYTE_TC].value; } else atr->ib[pn][ATR_INTERFACE_BYTE_TC].present = 0; /* Read TDi if present */ if (TDi & 0x80) { pointer++; if (len < pointer) return ASE_ERROR_ATR; atr->ib[pn][ATR_INTERFACE_BYTE_TD].value = data[pointer]; TDi = atr->ib[pn][ATR_INTERFACE_BYTE_TD].value; atr->ib[pn][ATR_INTERFACE_BYTE_TD].present = 1; atr->data[pointer] = atr->ib[pn][ATR_INTERFACE_BYTE_TD].value; (atr->TCK).present = ((TDi & 0x0F) != ATR_PROTOCOL_TYPE_T0); if (pn >= ATR_MAX_PROTOCOLS) return ASE_ERROR_ATR; pn++; } else { atr->ib[pn][ATR_INTERFACE_BYTE_TD].present = 0; break; } } /* Store number of protocols */ atr->pn = pn + 1; /* Store historical bytes */ for (i = 0; i < (atr->hbn); i++) { pointer++; if (len < pointer) return ASE_ERROR_ATR; atr->hb[i] = data[pointer]; atr->data[pointer] = atr->hb[i]; } /* Store TCK */ if ((atr->TCK).present) { pointer++; if (len < pointer) return ASE_ERROR_ATR; (atr->TCK).value = data[pointer]; atr->data[pointer] = atr->TCK.value; } atr->length = pointer + 1; return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int GetCurrentMode (ATR* atr) { /* TA2 */ if (atr->ib[1][ATR_INTERFACE_BYTE_TA].present) { return SPECIFIC_MODE; } else return NEGOTIABLE_MODE; } /***************************************************************************** * *****************************************************************************/ int CapableOfChangingMode (ATR* atr) { if (atr->ib[1][ATR_INTERFACE_BYTE_TA].present) /* TA2 */ return ((atr->ib[1][ATR_INTERFACE_BYTE_TA].value) & 0x80) == 0; else return 0; } /***************************************************************************** * *****************************************************************************/ uchar GetSpecificModeProtocol (ATR* atr) { if (GetCurrentMode(atr) == SPECIFIC_MODE) return ((atr->ib[1][ATR_INTERFACE_BYTE_TA].value) & 0x0F); else return UNKNOWN_PROTOCOL; } /***************************************************************************** * *****************************************************************************/ static int UseDefaultBaudrateInSpecificMode (ATR* atr) { if (GetCurrentMode(atr) == SPECIFIC_MODE) return ((atr->ib[1][ATR_INTERFACE_BYTE_TA].value) & 0x10); /* if b5=1 default */ else return 0; } /***************************************************************************** * *****************************************************************************/ float GetFToDFactor (int F, int D) { return (float)(fi[F]) / (float)(di[D]); } /***************************************************************************** * *****************************************************************************/ float GetDToFFactor (int F, int D) { return (float)(di[D]) / (float)(fi[F]); } /***************************************************************************** * *****************************************************************************/ uchar GetFi (ATR* atr) { if (UseDefaultBaudrateInSpecificMode(atr)) return 0; else if (atr->ib[0][ATR_INTERFACE_BYTE_TA].present) return (atr->ib[0][ATR_INTERFACE_BYTE_TA].value & 0xF0) >> 4; else return 1; /* 372 */ } /***************************************************************************** * *****************************************************************************/ long GetMaxFreq (ATR* atr) { return fs[GetFi(atr)]; } /***************************************************************************** * *****************************************************************************/ uchar GetDi (ATR* atr) { if (UseDefaultBaudrateInSpecificMode(atr)) return 1; else if (atr->ib[0][ATR_INTERFACE_BYTE_TA].present) return (atr->ib[0][ATR_INTERFACE_BYTE_TA].value & 0x0F); else return 1; /* 1 */ } /***************************************************************************** * *****************************************************************************/ uchar GetN (ATR* atr) { if (atr->ib[0][ATR_INTERFACE_BYTE_TC].present) return (atr->ib[0][ATR_INTERFACE_BYTE_TC].value); else return 0; } /***************************************************************************** * *****************************************************************************/ uchar GetWI (ATR* atr) { if (atr->ib[1][ATR_INTERFACE_BYTE_TC].present) return (atr->ib[1][ATR_INTERFACE_BYTE_TC].value); else return 10; } /***************************************************************************** * *****************************************************************************/ uchar GetFirstOfferedProtocol (ATR* atr) { /* only in NEGOTIABLE_MODE */ if (atr->ib[0][ATR_INTERFACE_BYTE_TD].present) return (atr->ib[0][ATR_INTERFACE_BYTE_TD].value) & 0x0F; else return ATR_PROTOCOL_TYPE_T0; } /***************************************************************************** * *****************************************************************************/ uchar GetT1IFSC (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=1 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T1) { /* return TA(i+1) if present */ if (atr->ib[i + 1][ATR_INTERFACE_BYTE_TA].present) return atr->ib[i + 1][ATR_INTERFACE_BYTE_TA].value; else return 32; /* default */ } } return 32; } /***************************************************************************** * *****************************************************************************/ uchar GetT1CWI (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=1 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T1) { /* return TA(i+1) if present */ if (atr->ib[i + 1][ATR_INTERFACE_BYTE_TB].present) return (atr->ib[i + 1][ATR_INTERFACE_BYTE_TB].value & 0x0F); else return 13; /* default */ } } return 13; } /***************************************************************************** * *****************************************************************************/ uchar GetT1BWI (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=1 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T1) { /* return TA(i+1) if present */ if (atr->ib[i + 1][ATR_INTERFACE_BYTE_TB].present) return ((atr->ib[i + 1][ATR_INTERFACE_BYTE_TB].value & 0xF0) >> 4); else return 4; /* default */ } } return 4; } /***************************************************************************** * *****************************************************************************/ uchar GetT1EDC (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=1 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T1) { /* return TA(i+1) if present */ if (atr->ib[i + 1][ATR_INTERFACE_BYTE_TC].present) return (atr->ib[i + 1][ATR_INTERFACE_BYTE_TC].value & 0x01); else return 0; /* default - LRC */ } } return 0; } /***************************************************************************** * *****************************************************************************/ int IsT1Available (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=1 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T1) { return 1; } } return 0; } /***************************************************************************** * *****************************************************************************/ uchar GetClassIndicator (ATR* atr) { int i; for (i = 1 ; i < atr->pn ; ++i) { /* check for the first occurance of T=15 in TDi */ if (atr->ib[i][ATR_INTERFACE_BYTE_TD].present && (atr->ib[i][ATR_INTERFACE_BYTE_TD].value & 0x0F) == ATR_PROTOCOL_TYPE_T15) { /* return TA(i+1) if present */ if (atr->ib[i + 1][ATR_INTERFACE_BYTE_TA].present) return (atr->ib[i + 1][ATR_INTERFACE_BYTE_TA].value & 0x3F); else return 1; /* default - only class A (5V) supported */ } } return 1; /* default - only class A (5V) supported */ } asedriveiiie-3.7/asedriveiiie-usb/LICENSE0000755000175000017500000000257711265303433020577 0ustar rousseaurousseauCopyright (c) 2003 Athena Smartcard Solutions All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. asedriveiiie-3.7/asedriveiiie-usb/DriverIO.c0000755000175000017500000001426711265303433021420 0ustar rousseaurousseau#include "Ase.h" /***************************************************************************** * *****************************************************************************/ /* reader status */ #define STS_PID_OK 0x00 #define STS_PID_ERROR 0x01 #define STS_CNT_ERROR 0x02 #define STS_TRUNC_ERROR 0x03 #define STS_LEN_ERROR 0x04 #define STS_UNKNOWN_CMD_ERROR 0x05 #define STS_TIMEOUT_ERROR 0x06 #define STS_CS_ERROR 0x07 #define STS_INVALID_PARAM_ERROR 0x08 #define STS_CMD_FAILED_ERROR 0x09 #define STS_NO_CARD_ERROR 0x0A #define STS_CARD_NOT_POWERED_ERROR 0x0B #define STS_COMM_ERROR 0x0C #define STS_EXTRA_WAITING_TIME 0x0D #define STS_RETRY_FAILED 0x0E /* Card events */ #define EID_CARD1_NOT_PRESENT 0x01 #define EID_CARD1_INSERTED 0x02 #define EID_CARD2_NOT_PRESENT 0x05 #define EID_CARD2_INSERTED 0x06 #define EID_CARD3_NOT_PRESENT 0x09 #define EID_CARD3_INSERTED 0x0A #define EID_CARD4_NOT_PRESENT 0x0D #define EID_CARD4_INSERTED 0x0E /***************************************************************************** * *****************************************************************************/ /* returns 0 if no error, status code otherwise */ int parseStatus (uchar ackByte) { int retVal; if ((ackByte & 0xF0) != 0x20) retVal = ASE_READER_INVALID_STATUS_BYTE; else { ackByte &= 0x0F; switch (ackByte) { case STS_PID_ERROR: retVal = ASE_READER_PID_ERROR; break; case STS_CNT_ERROR: retVal = ASE_READER_CNT_ERROR; break; case STS_TRUNC_ERROR: retVal = ASE_READER_TRUNC_ERROR; break; case STS_LEN_ERROR: retVal = ASE_READER_LEN_ERROR; break; case STS_UNKNOWN_CMD_ERROR: retVal = ASE_READER_UNKNOWN_CMD_ERROR; break; case STS_TIMEOUT_ERROR: retVal = ASE_READER_TIMEOUT_ERROR; break; case STS_CS_ERROR: retVal = ASE_READER_CS_ERROR; break; case STS_INVALID_PARAM_ERROR: retVal = ASE_READER_INVALID_PARAM_ERROR; break; case STS_CMD_FAILED_ERROR: retVal = ASE_READER_CMD_FAILED_ERROR; break; case STS_NO_CARD_ERROR: retVal = ASE_READER_NO_CARD_ERROR; break; case STS_CARD_NOT_POWERED_ERROR: retVal = ASE_READER_CARD_NOT_POWERED_ERROR; break; case STS_COMM_ERROR: retVal = ASE_READER_COMM_ERROR; break; case STS_EXTRA_WAITING_TIME: retVal = ASE_READER_EXTRA_WAITING_TIME; break; case STS_RETRY_FAILED: retVal = ASE_READER_RETRY_FAILED; break; default: retVal = 0; break; } } #ifdef ASE_DEBUG if (retVal) syslog(LOG_INFO, "parseStatus: Error! status = %d\n", ackByte); #endif return retVal; } /***************************************************************************** * *****************************************************************************/ int isEvent (uchar event) { if (event == EID_CARD1_NOT_PRESENT || event == EID_CARD2_NOT_PRESENT || event == EID_CARD1_INSERTED || event == EID_CARD2_INSERTED || event == EID_CARD3_NOT_PRESENT || event == EID_CARD4_NOT_PRESENT || event == EID_CARD3_INSERTED || event == EID_CARD4_INSERTED) return 1; return 0; } /***************************************************************************** * *****************************************************************************/ /* returns 0 if not an error, error code otherwise. change global data status if neccesary */ int parseEvent (reader* globalData, char socket, uchar event) { uchar skn; #ifdef ASE_DEBUG syslog(LOG_INFO, "=============> Event = 0x%x%x <===============\n", PRINT_CHAR(event)); #endif skn = (event & 0x0C) >> 2; globalData->cards[skn].status = ((event & 0x01) ? 0 : 1); /* if the card is out and the socket number is the one we use, return an error indication */ if ((event & 0x01) && (skn == socket)) return ASE_READER_NO_CARD_ERROR; return ASE_OK; } /***************************************************************************** * *****************************************************************************/ int writeToReader (reader* globalData, char* data, int len, int* actual) { *actual = WriteUSB(globalData, len, (unsigned char*)data); #ifdef ASE_DEBUG syslog(LOG_INFO, "writeToReader: wrote %d bytes. data = ", *actual); int i; for (i = 0 ; i < *actual ; ++i) syslog(LOG_INFO, "0x%x%x ", PRINT_CHAR(data[i])); syslog(LOG_INFO, "\n"); #endif if (*actual != len) { #ifdef ASE_DEBUG syslog(LOG_INFO, "writeToReader - Error! len = %d, actual = %d\n", len, *actual); #endif return ASE_ERROR_WRITE; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ /* returns 0 on success; negative value otherwise */ int readResponse (reader* globalData, char socket, int num, char* outBuf, int* outBufLen, unsigned long timeout/*, int startOfResponse*/) { int len; int remain = num; *outBufLen = 0; /* the timeout should be switched from microsec to millisec */ timeout /= 1000; len = ReadUSB(globalData, timeout + 4000 /* 4 sec. delta */, remain, (unsigned char*)(&(outBuf[*outBufLen]))); (*outBufLen) = (*outBufLen) + len; if (num == *outBufLen) /* all data arrived */ return ASE_OK; else { /* part of the data is missing */ #ifdef ASE_DEBUG syslog(LOG_INFO, "readResponse - Error! read only %d out of %d bytes\n", *outBufLen, num); #endif return ASE_ERROR_DATA_INCOMPLETE; } } asedriveiiie-3.7/asedriveiiie-usb/CommandTypes.c0000755000175000017500000002732711441350403022334 0ustar rousseaurousseau#include "Ase.h" /* ASE reader generic command types */ #define ASE_LONG_RESPONSE_PID 0x90 #define ASE_RESPONSE_PID 0x10 #define ASE_ACK_PID 0x20 #define ASE_LONG_RESPONSE_WITH_STATUS_PID 0xF0 #define ASE_RESPONSE_WITH_STATUS_PID 0x70 /***************************************************************************** * *****************************************************************************/ //#define ASE_PACKET_TYPE(pid, cnt, dst) (pid | cnt << 2 | dst) #define ASE_PACKET_TYPE(pid, cnt, dst) (pid | dst) /***************************************************************************** * *****************************************************************************/ /* returns 0 on success, negative number otherwise */ int checkValidity (int retVal, int len, int actual, const char* message) { if (retVal < 0 || actual != len) { #ifdef ASE_DEBUG syslog(LOG_INFO, "%s Error = %d\n", message, retVal); #endif return retVal; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static void cleanResponseBuffer (reader* globalData) { CleanReadBufferUSB(globalData); } /***************************************************************************** * *****************************************************************************/ /* returns 0 on success, negative number otherwise outBuf should be large enough to contain the close response */ int sendCloseResponseCommand (reader* globalData, char socket, char* cmd, int len, char* outBuf, int* outBufLen, char ignoreEvents) { int retVal, actual, i, j, readLen, retryTimes = 3, withStatus = 0; uchar oneByte, cs, readcs; unsigned long waitingTime; // unsigned long cwt = (globalData->cards[socket].cwt > 0 ? globalData->cards[socket].cwt : 1000); cleanResponseBuffer(globalData); /* send the command */ retVal = writeToReader(globalData, cmd, len, &actual); if (checkValidity(retVal, len, actual, "sendCloseResponseCommand - Error! in command write.\n")) { cleanResponseBuffer(globalData); return retVal; } /* read the close response */ /* set the timeout for the packet header */ waitingTime = (globalData->cards[(int)socket].bwt > 0 ? globalData->cards[(int)socket].bwt : 1000); waitingTime += globalData->cards[(int)socket].cwt * 262; // waitingTime += 200000; // delta of 0.2 seconds /* read packet header and verify it's ok */ retVal = readResponse(globalData, socket, 1, (char*)(&oneByte), &actual, waitingTime); if (checkValidity(retVal, 1, actual, "sendCloseResponseCommand - Error! in packet header read.\n")) { cleanResponseBuffer(globalData); return retVal; } /* loop until we get the start of a response or an error has occured */ while (oneByte != ASE_LONG_RESPONSE_PID && oneByte != ASE_RESPONSE_PID && oneByte != ASE_RESPONSE_WITH_STATUS_PID && oneByte != ASE_LONG_RESPONSE_WITH_STATUS_PID && retryTimes) { #ifdef ASE_DEBUG syslog(LOG_INFO, "sendCloseResponseCommand - oneByte = 0x%x%x.\n", (oneByte & 0xF0) >> 4, oneByte & 0x0F); #endif /* check if it's an acknowledgment */ if (oneByte & ASE_ACK_PID) { if (parseStatus(oneByte) != ASE_READER_EXTRA_WAITING_TIME) { #ifdef ASE_DEBUG syslog(LOG_INFO, "sendCloseResponseCommand - Error! packet header is 0x%x%x.\n", (oneByte & 0xF0) >> 4, oneByte & 0x0F); #endif cleanResponseBuffer(globalData); return parseStatus(oneByte); } else retryTimes = 3; } /* check if it's an event */ else if (isEvent(oneByte)) { #ifdef ASE_DEBUG syslog(LOG_INFO, "sendCloseResponseCommand - Event 0x%x%x.\n", (oneByte & 0xF0) >> 4, oneByte & 0x0F); #endif parseEvent(globalData, socket, oneByte); retryTimes = 3; } /* this must be an error -> send a retry command */ else { char cmdTmp[4]; cleanResponseBuffer(globalData); cmdTmp[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmdTmp[1] = 0x44; cmdTmp[2] = 0x0; cmdTmp[3] = cmdTmp[0] ^ cmdTmp[1] ^ cmdTmp[2]; retVal = writeToReader(globalData, cmdTmp, 4, &actual); if (checkValidity(retVal, 4, actual, "sendControlCommand - Error! in command write.\n")) { cleanResponseBuffer(globalData); return retVal; } // retryTimes = 3; } /* read packet header and verify it's ok */ retVal = readResponse(globalData, socket, 1, (char*)(&oneByte), &actual, waitingTime); if (checkValidity(retVal, 1, actual, "sendCloseResponseCommand - Error! in packet header read.\n")) { cleanResponseBuffer(globalData); return retVal; } retryTimes--; } if (retryTimes == 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "sendCloseResponseCommand - Error! retryTimes is 0.\n"); #endif return ASE_ERROR_RESEND_COMMAND; } cs = oneByte; /* set the timeout for the length */ // waitingTime = (globalData->cards[socket].cwt > 0 ? globalData->cards[socket].cwt : 1000); /* check if a status byte appears at the end of the response */ if (oneByte == ASE_LONG_RESPONSE_WITH_STATUS_PID || oneByte == ASE_RESPONSE_WITH_STATUS_PID) withStatus = 1; /* this is a response header, so read its length */ if (oneByte == ASE_LONG_RESPONSE_PID || oneByte == ASE_LONG_RESPONSE_WITH_STATUS_PID) { /* long response */ retVal = readResponse(globalData, socket, 1, (char*)(&oneByte), &actual, waitingTime); if (checkValidity(retVal, 1, actual, "sendCloseResponseCommand - Error! in packet header read.\n")) { cleanResponseBuffer(globalData); return retVal; } cs ^= oneByte; readLen = (oneByte << 8); readLen &= 0xFF00; retVal = readResponse(globalData, socket, 1, (char*)(&oneByte), &actual, waitingTime); if (checkValidity(retVal, 1, actual, "sendCloseResponseCommand - Error! in packet header read.\n")) { cleanResponseBuffer(globalData); return retVal; } cs ^= oneByte; readLen |= (oneByte & 0xFF); } else { /* short response */ retVal = readResponse(globalData, socket, 1, (char*)(&oneByte), &actual, waitingTime); if (checkValidity(retVal, 1, actual, "sendCloseResponseCommand - Error! in packet header read.\n")) { cleanResponseBuffer(globalData); return retVal; } cs ^= oneByte; readLen = oneByte; } /* set the timeout for the data */ // cwt = 100000 * (readLen + 1); // 0.1 sec per byte /***!!!!!!!!!!!!!!!!!!!!***************************************/ /* read data + checksum */ for (j = 0 ; (j < readLen + 1) && (retVal == 0) ; ++j) { retVal = readResponse(globalData, socket, 1, (char*)&oneByte, &actual, waitingTime); outBuf[j] = oneByte; } if (checkValidity(retVal, readLen + 1, j/**outBufLen*/, "sendCloseResponseCommand - Error! in data read.\n")) { cleanResponseBuffer(globalData); return retVal; } *outBufLen = j; readcs = outBuf[*outBufLen - 1]; (*outBufLen)--; for (i = 0 ; i < *outBufLen ; ++i) cs ^= outBuf[i]; /* check the status byte provided */ if (withStatus) { /* remove the last byte of outBuf and check the status */ (*outBufLen)--; if ( (outBuf[*outBufLen] != ASE_ACK_PID) ) { /* read the checksum */ /*retVal = readResponse(globalData, socket, 1, &oneByte, &actual, waitingTime);*/ //BM Check Len = 0xFF /* return error according to the status byte */ cleanResponseBuffer(globalData); // retVal = parseStatus(outBuf[*outBufLen]); /* if( (retVal == ASE_BWT_EXCEEDED) && (*outBufLen>4) && ( (unsigned char)outBuf[2] == 0xff) ) return ASE_READER_LEN_ERROR; else*/ return parseStatus(outBuf[*outBufLen]); } } if (cs != readcs) { #ifdef ASE_DEBUG syslog(LOG_INFO, "sendCloseResponseCommand - Error! invalid checksum.\n"); #endif cleanResponseBuffer(globalData); return ASE_ERROR_CHECKSUM; } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ /* returns 0 on success, negative number otherwise outBuf will contain the ACK/NAK byte sent as response */ int sendControlCommand (reader* globalData, char socket, char* cmd, int len, char* outBuf, int* outBufLen, char ignoreEvents) { int retVal, actual, retryTimes = 3; #ifdef ASE_DEBUG uchar oneByte; #endif // unsigned long cwt = (globalData->cards[socket].cwt > 0 ? globalData->cards[socket].cwt : 1000); unsigned long waitingTime; cleanResponseBuffer(globalData); /* send the command */ retVal = writeToReader(globalData, cmd, len, &actual); if (checkValidity(retVal, len, actual, "sendControlCommand - Error! in command write.\n")) { cleanResponseBuffer(globalData); return retVal; } /* read the Ack control byte */ /* set the timeout for the packet header */ // cwt = MAX(cwt * 260, globalData->cards[socket].bwt); // waitingTime = (globalData->cards[socket].bwt > 0 ? globalData->cards[socket].bwt : 1000); waitingTime = 3000000; // 3 sec retVal = readResponse(globalData, socket, 1, outBuf, outBufLen, waitingTime); if (checkValidity(retVal, 1, *outBufLen, "sendControlCommand - Error! in ack read.\n")) { cleanResponseBuffer(globalData); return retVal; } /* loop until we get an OK acknowledgement */ while (outBuf[0] != ASE_ACK_PID && retryTimes) { /* check if it's an acknowledgment */ if (outBuf[0] & ASE_ACK_PID) { if (parseStatus(outBuf[0]) != ASE_READER_EXTRA_WAITING_TIME) { #ifdef ASE_DEBUG syslog(LOG_INFO, "sendControlCommand - Error! packet header is 0x%x%x.\n", (oneByte & 0xF0) >> 4, oneByte & 0x0F); #endif cleanResponseBuffer(globalData); return parseStatus(outBuf[0]); } else retryTimes = 3; } /* check if it's an event */ else if (isEvent((uchar)(outBuf[0]))) { parseEvent(globalData, socket, outBuf[0]); retryTimes = 3; } /* this must be an error -> send a retry command */ else { char cmdTmp[4]; cmdTmp[0] = ASE_PACKET_TYPE(0x50, globalData->commandCounter, socket); globalData->commandCounter++; globalData->commandCounter %= 4; cmdTmp[1] = 0x44; cmdTmp[2] = 0x0; cmdTmp[3] = cmdTmp[0] ^ cmdTmp[1] ^ cmdTmp[2]; retVal = writeToReader(globalData, cmdTmp, 4, &actual); if (checkValidity(retVal, 4, actual, "sendControlCommand - Error! in command write.\n")) { cleanResponseBuffer(globalData); return retVal; } retryTimes = 3; } /* read packet header and verify it's ok */ retVal = readResponse(globalData, socket, 1, outBuf, outBufLen, waitingTime); if (checkValidity(retVal, 1, *outBufLen, "sendControlCommand - Error! in ack read.\n")) { cleanResponseBuffer(globalData); return retVal; } retryTimes--; } return ASE_OK; } asedriveiiie-3.7/asedriveiiie-usb/Ase.h0000755000175000017500000002321711441350257020447 0ustar rousseaurousseau#ifndef __ASE_H #define __ASE_H #include #include #include #include #include #include #include #include #include //#include #include #include #include #include //#include #include #include #include "LinuxDefines.h" #include "atr.h" #include "T1Protocol.h" #include "MemoryCards.h" //#define ASE_DEBUG /***************************************************************************** * IOCTL *****************************************************************************/ #define ASE_IOCTL_CLASS 0xF0 #define ASE_IOCTL_XI2C_INS 0xA0 #define ASE_IOCTL_CLOCK_INS 0xB0 // for sending raw reader ioctls #define ASE_IOCTL_RAW_CLASS 0xFF #define ASE_IOCTL_RAW_INS 0xA0 /***************************************************************************** * *****************************************************************************/ #define LEFT_NIBBLE(c) ((c & 0xF0) >> 4) #define RIGHT_NIBBLE(c) (c & 0x0F) #define PRINT_CHAR(c) LEFT_NIBBLE(c), RIGHT_NIBBLE(c) #ifndef MIN #define MIN(a, b) (a > b ? b : a) #endif #ifndef MAX #define MAX(a, b) (a > b ? a : b) #endif #define ASE_READER_ETU_DELTA 150 /***************************************************************************** * *****************************************************************************/ #define BULK_BUFFER_SIZE 300 #define EVENT_BUFFER_SIZE 16 #define RESPONSE_BUFFER_SIZE 4096 #define MAX_SOCKET_NUM 4 #define ASE_DATA_MEMORY_SIZE 64 #define READER_FIDI_TABLE_SIZE 100 #define BUFFER_SIZE 8192 #define MAX_READER_NUM 16 /***************************************************************************** * *****************************************************************************/ struct card_params { uchar protocol; uchar N; uchar CWT[3]; uchar BWT[3]; uchar A; uchar B; uchar freq; float fTod; }; typedef struct { int status; /* 0 - absent, 1 - inserted, 2 - powered on */ int ceei; ATR atr; long cwt; /* max time in microseconds to wait between characters */ long bwt; /* max time in microseconds to wait to first character (in T=0, equals to cwt) */ T1Protocol T1; struct card_params cardParams; uchar FiDi; char activeProtocol; MemCard memCard; } card; typedef struct { HANDLE handle; unsigned char baud; unsigned char bits; int stopbits; char parity; long blocktime; } ioport; #define BUS_DEVICE_STRSIZE 32 typedef struct { // int handle; usb_dev_handle* handle; struct usb_device* dev; char bus_device[BUS_DEVICE_STRSIZE]; int interface; /* * Endpoints */ int bulk_in; int bulk_out; char response[RESPONSE_BUFFER_SIZE]; unsigned int curPos, lastPos; char stopReading; } usbDevice; typedef struct { usbDevice io; char dataMemory[ASE_DATA_MEMORY_SIZE]; int readerStarted; /* 1 - started, 0 - not yet */ char commandCounter; card cards[MAX_SOCKET_NUM]; pthread_mutex_t semaphore; } reader; /***************************************************************************** * *****************************************************************************/ /* return codes */ #define ASE_OK 0 #define ASE_ERROR_DATA_INCOMPLETE -1 #define ASE_ERROR_IOCTL_RESPONSE -2 #define ASE_ERROR_IOCTL_EVENT -3 #define ASE_ERROR_READ -4 #define ASE_ERROR_WRITE -5 #define ASE_ERROR_TIMEOUT -6 #define ASE_ERROR_COMMAND -7 #define ASE_ERROR_CHECKSUM -8 #define ASE_ERROR_RESPONSE_INCORRECT -9 #define ASE_ERROR_OVERHEATING -10 #define ASE_ERROR_ATR -11 #define ASE_ERROR_PARITY -12 #define ASE_ERROR_FIFO_OVERRUN -13 #define ASE_ERROR_FRAMING -14 #define ASE_ERROR_EARLY_ANSWER -15 #define ASE_ERROR_RESEND_COMMAND -16 #define ASE_READER_PID_ERROR -110 #define ASE_READER_CNT_ERROR -111 #define ASE_READER_TRUNC_ERROR -112 #define ASE_READER_LEN_ERROR -113 #define ASE_READER_UNKNOWN_CMD_ERROR -114 #define ASE_READER_TIMEOUT_ERROR -115 #define ASE_READER_CS_ERROR -116 #define ASE_READER_INVALID_PARAM_ERROR -117 #define ASE_READER_CMD_FAILED_ERROR -118 #define ASE_READER_NO_CARD_ERROR -119 #define ASE_READER_CARD_NOT_POWERED_ERROR -120 #define ASE_READER_COMM_ERROR -121 #define ASE_READER_EXTRA_WAITING_TIME -122 #define ASE_READER_NOT_CPU_CARD -123 #define ASE_READER_NO_MATCHING_PARAMS -124 #define ASE_READER_CARD_REJECTED -125 #define ASE_READER_INVALID_STATUS_BYTE -126 #define ASE_READER_RETRY_FAILED -127 /***************************************************************************** * externs *****************************************************************************/ extern int ParseATR (reader* globalData, char socket, char data[], int len); extern int GetCurrentMode (ATR* atr); extern int CapableOfChangingMode (ATR* atr); extern uchar GetSpecificModeProtocol (ATR* atr); extern uchar GetFi (ATR* atr); extern uchar GetDi (ATR* atr); extern uchar GetN (ATR* atr); extern uchar GetWI (ATR* atr); extern long GetMaxFreq (ATR* atr); extern uchar GetFirstOfferedProtocol (ATR* atr); extern float GetFToDFactor (int F, int D); extern float GetDToFFactor (int F, int D); extern uchar GetT1IFSC (ATR* atr); extern uchar GetT1CWI (ATR* atr); extern uchar GetT1BWI (ATR* atr); extern uchar GetT1EDC (ATR* atr); extern int IsT1Available (ATR* atr); extern uchar GetClassIndicator (ATR* atr); extern int parseStatus (uchar ackByte); extern int isEvent (uchar event); extern int parseEvent (reader* globalData, char socket, uchar event); extern int readResponse (reader* globalData, char socket, int num, char* outBuf, int* outBufLen, unsigned long timeout/*, int startOfResponse*/); extern int writeToReader (reader* globalData, char* data, int len, int* actual); extern int checkValidity (int retVal, int len, int actual, const char* message); extern int sendCloseResponseCommand (reader* globalData, char socket, char* cmd, int len, char* outBuf, int* outBufLen, char ignoreEvents); extern int sendControlCommand (reader* globalData, char socket, char* cmd, int len, char* outBuf, int* outBufLen, char ignoreEvents); extern int cardCommandInit (reader* globalData, char socket, char needToBePoweredOn); extern int readerCommandInit (reader* globalData, char needToBeStarted); extern int ReaderStartup (reader* globalData, char* response, int* len); extern int ReaderFinish (reader* globalData); extern int GetStatus (reader* globalData, char* response, int* len); extern int SetCardParameters (reader* globalData, char socket, struct card_params params); extern int CardPowerOn (reader* globalData, char socket, uchar cardType, uchar voltage); extern int CPUCardReset (reader* globalData, char socket); extern int CardPowerOff (reader* globalData, char socket); extern int ChangeLedState (reader* globalData, char on); extern int PPSTransact (reader* globalData, char socket, char* buffer, int len, char* outBuf, int* outBufLen); extern int CardCommand (reader* globalData, char socket, char command, uchar* buffer, int len, uchar* outBuf, int* outBufLen); /* extern int T0CPUCardTransact (reader* globalData, char socket, char* buffer, int len, char* outBuf, int* outBufLen, openResponseProccessor orp, unsigned long arg); */ extern int T1CPUCardTransact (reader* globalData, char socket, char* buffer, int len, char* outBuf, int* outBufLen); extern int MemoryCardTransact (reader* globalData, char socket, char cmdType, uchar command, ushort address, uchar len, uchar* data, char* outBuf, int* outBufLen); /* the protocol is not NULL if a PPS is required to switch to it.*/ extern int InitCard (reader* globalData, char socket, char coldReset, char* protocol); /* outBuf will contain the SW1/SW2 as well */ extern int T0Read (reader* globalData, char socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen); extern int T0Write (reader* globalData, char socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen); extern int T1InitProtocol (reader* globalData, char socket, char setIFSD); extern int T1Command (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen); extern int MemoryCardCommand (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen); extern int SendIOCTL (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen); bool OpenUSB(reader* allReaders, reader* globalData); bool CloseUSB(reader* globalData); int WriteUSB(reader* globalData, int writesize, unsigned char* data); int ReadUSB(reader* globalData, unsigned long timeout, int len, unsigned char *buf); void CleanReadBufferUSB(reader* globalData); #endif asedriveiiie-3.7/asedriveiiie-usb/T1Protocol.c0000755000175000017500000006563211441154006021741 0ustar rousseaurousseau#include "Ase.h" static int SendSBlock (reader* globalData, uchar socket, uchar control, uchar data); /***************************************************************************** * *****************************************************************************/ static uchar T1BlockGetType (T1Block* block) { if ((block->data[1] & 0x80) == T1_BLOCK_I) return T1_BLOCK_I; return (block->data[1] & 0xC0); } static int T1ErrorFreeRBlock (T1Block* block) { return ((block->data[1] & 0x0F) == 0); } static uchar T1BlockGetNS (T1Block* block) { return ((block->data[1] >> 6) & 0x01); } static uchar T1BlockGetMore (T1Block* block) { return ((block->data[1] >> 5) & 0x01); } static uchar T1BlockGetNR (T1Block* block) { return ((block->data[1] >> 4) & 0x01); } static int T1BlockGetLen (T1Block* block) { return block->data[2]; } static uchar* T1BlockGetInf (T1Block* block) { if (block->len < 5) return NULL; return block->data + 3; } /***************************************************************************** * *****************************************************************************/ static void LRC(char* data, int len, uchar* edc) { int i; *edc = 0; for (i = 0 ; i < len ; ++i) (*edc) ^= data[i]; } /***************************************************************************** * *****************************************************************************/ static void CRC(char* data, int len, uchar* edc1, uchar* edc2) { int i; unsigned short crc = 0xFFFF, temp, quick; for (i = 0 ; i < len ; ++i) { temp = (crc >> 8) ^ data[len]; crc <<= 8; quick = temp ^ (temp >> 4); crc ^= quick; quick <<= 5; crc ^= quick; quick <<= 7; crc ^= quick; } *edc1 = (crc >> 8) & 0x00FF; *edc2 = crc & 0x00FF; } /***************************************************************************** * *****************************************************************************/ int T1InitProtocol (reader* globalData, char socket, char setIFSD) { int retVal; ATR *atr = &(globalData->cards[(int)socket].atr); /* set IFSC */ globalData->cards[(int)socket].T1.ifsc = MIN(GetT1IFSC(atr), ATHENA_IFSC_MAX_SIZE); /* set EDC */ globalData->cards[(int)socket].T1.edc = (GetT1EDC(atr) == 0 ? 1 : 0); /* set counters */ globalData->cards[(int)socket].T1.ns = 1; globalData->cards[(int)socket].T1.nsCard = 0; #ifdef ASE_DEBUG syslog(LOG_INFO, "T1InitProtocol: ifsc = %d, edc = %d\n", globalData->cards[(int)socket].T1.ifsc, globalData->cards[(int)socket].T1.edc); #endif // Try to set the maximal ifsd - if it fails, use the default // for (i = 0 ; i < 3 ; ++i) { if (setIFSD) { T1Block* recBlock = &(globalData->cards[(int)socket].T1.recBlock); retVal = SendSBlock(globalData, socket, T1_BLOCK_S_IFS_REQ, 254/*globalData->cards[(int)socket].T1.ifsc*/); if (retVal == ASE_OK && T1BlockGetLen(recBlock) > 0x1) { // check Correct len // check that S(IFS response) has been received if (recBlock->data[1] == T1_BLOCK_S_IFS_RES) { #ifdef ASE_DEBUG printf("<<<<<<<<< RECEIVING S(IFS response)\n"); #endif // break; } } } return PROTOCOL_T1_OK; } /***************************************************************************** * *****************************************************************************/ static int T1CommandResponseProccessor(reader* globalData, char socket, char* response, int len, char* outBuf, int* outBufLen) { int i; uchar readByte, edc1, edc2, edc11, edc22; *outBufLen = 0; if (len < 3) return PROTOCOL_T1_ERROR; readByte = response[0]; outBuf[*outBufLen] = readByte; (*outBufLen)++; readByte = response[1]; outBuf[*outBufLen] = readByte; (*outBufLen)++; readByte = response[2]; outBuf[*outBufLen] = readByte; (*outBufLen)++; /* check that LEN doesnt exceed 254 */ if (readByte > T1_BLOCK_INF_MAX_SIZE || len < (readByte + 3)) { return PROTOCOL_T1_ERROR; } /* read the information field */ if (readByte > 0) { for (i = 0 ; i < readByte ; ++i) outBuf[3 + i] = response[3 + i]; (*outBufLen) += readByte; } /* read the EDC */ if (globalData->cards[(int)socket].T1.edc == 1) { /* LRC */ LRC(outBuf, *outBufLen, &edc11); if (len < (readByte + 4)) { return PROTOCOL_T1_ERROR; } edc1 = response[readByte + 3]; outBuf[*outBufLen] = edc1; (*outBufLen)++; if (edc1 != edc11) { return PROTOCOL_T1_ERROR; } } else { /* CRC */ CRC(outBuf, *outBufLen, &edc11, &edc22); if (len < (readByte + 5)) { return PROTOCOL_T1_ERROR; } edc1 = response[readByte + 3]; outBuf[*outBufLen] = edc1; (*outBufLen)++; edc2 = response[readByte + 4]; outBuf[*outBufLen] = edc2; (*outBufLen)++; if (edc1 != edc11 || edc2 != edc22) { return PROTOCOL_T1_ERROR; } } return ASE_OK; } /***************************************************************************** * *****************************************************************************/ /* the block to be sent is ready in T1.sendBlock -> send it using CPUCardTransact */ static int SendBlock (reader* globalData, uchar socket) { char response[BULK_BUFFER_SIZE]; int retVal, len; T1Block* send = &(globalData->cards[(int)socket].T1.sendBlock); uchar edc1, edc2, LEN = send->data[2]; #ifdef ASE_DEBUG if (T1BlockGetType(send) == T1_BLOCK_I) syslog(LOG_INFO, ">>>>>>>> SENDING I(%d, %d)\n", T1BlockGetNS(send), T1BlockGetMore(send)); else if (T1BlockGetType(send) == T1_BLOCK_R) syslog(LOG_INFO, ">>>>>>>> SENDING R(%d)\n", T1BlockGetNR(send)); else if (T1BlockGetType(send) == T1_BLOCK_S) { switch (send->data[1]) { case T1_BLOCK_S_RESYNCH_REQ: syslog(LOG_INFO, ">>>>>>>> SENDING S(RESYNCH request)\n"); break; case T1_BLOCK_S_RESYNCH_RES: syslog(LOG_INFO, ">>>>>>>> SENDING S(RESYNCH response)\n"); break; case T1_BLOCK_S_IFS_REQ: syslog(LOG_INFO, ">>>>>>>> SENDING S(IFS request)\n"); break; case T1_BLOCK_S_IFS_RES: syslog(LOG_INFO, ">>>>>>>> SENDING S(IFS = %d response)\n", send->data[3]); break; case T1_BLOCK_S_ABORT_REQ: syslog(LOG_INFO, ">>>>>>>> SENDING S(ABORT request)\n"); break; case T1_BLOCK_S_ABORT_RES: syslog(LOG_INFO, ">>>>>>>> SENDING S(ABORT response)\n"); break; case T1_BLOCK_S_WTX_REQ: syslog(LOG_INFO, ">>>>>>>> SENDING S(WTX request)\n"); break; case T1_BLOCK_S_WTX_RES: syslog(LOG_INFO, ">>>>>>>> SENDING S(WTX = %d response)\n", send->data[3]); break; case T1_BLOCK_S_VPP_ERR: syslog(LOG_INFO, ">>>>>>>> SENDING S(VPP error)\n"); } } syslog(LOG_INFO, "sendBlock: NAD = 0x%x%x, PCB = 0x%x%x, LEN = 0x%x%x sendBlock.len = %d\n", PRINT_CHAR(globalData->cards[(int)socket].T1.sendBlock.data[0]), PRINT_CHAR(globalData->cards[(int)socket].T1.sendBlock.data[1]), PRINT_CHAR(globalData->cards[(int)socket].T1.sendBlock.data[2]), globalData->cards[(int)socket].T1.sendBlock.len); #endif /* calculate the EDC */ if (globalData->cards[(int)socket].T1.edc == 1) { /* LRC */ LRC((char*)(send->data), send->len, &edc1); globalData->cards[(int)socket].T1.sendBlock.data[3 + LEN] = edc1; globalData->cards[(int)socket].T1.sendBlock.len++; } else { /* CRC */ CRC((char*)(send->data), send->len, &edc1, &edc2); globalData->cards[(int)socket].T1.sendBlock.data[3 + LEN] = edc1; globalData->cards[(int)socket].T1.sendBlock.data[4 + LEN] = edc2; globalData->cards[(int)socket].T1.sendBlock.len += 2; } retVal = T1CPUCardTransact(globalData, socket, (char*)globalData->cards[(int)socket].T1.sendBlock.data, globalData->cards[(int)socket].T1.sendBlock.len, response, &len); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "SendBlock - Error!\n"); #endif return retVal; } retVal = T1CommandResponseProccessor(globalData, socket, response, len, (char*)globalData->cards[(int)socket].T1.recBlock.data, &(globalData->cards[(int)socket].T1.recBlock.len)); #ifdef ASE_DEBUG if (retVal < 0) syslog(LOG_INFO, "SendBlock - Error!\n"); #endif return retVal; } /***************************************************************************** * *****************************************************************************/ static int SendIBlock (reader* globalData, uchar socket, uchar* data, int len, char more, int increaseNs) { uchar PCB = 0, LEN; int retVal, i; if (increaseNs) globalData->cards[(int)socket].T1.ns = (globalData->cards[(int)socket].T1.ns + 1) % 2; if (globalData->cards[(int)socket].T1.ns) PCB |= 0x40; /* N(s) */ LEN = len; if (more) PCB |= 0x20; /* M=1 */ else PCB &= 0xdf; /* M=0 */ /* prepare the sendBlock */ globalData->cards[(int)socket].T1.sendBlock.data[0] = 0x00; /* NAD */ globalData->cards[(int)socket].T1.sendBlock.data[1] = PCB; /* PCB */ globalData->cards[(int)socket].T1.sendBlock.data[2] = LEN; /* LEN */ /* copy the INF data (if exists) */ for (i = 0 ; i < LEN ; ++i) globalData->cards[(int)socket].T1.sendBlock.data[3 + i] = data[i]; globalData->cards[(int)socket].T1.sendBlock.len = LEN + 3; retVal = SendBlock(globalData, socket); return retVal; } /***************************************************************************** * *****************************************************************************/ /* data is invalid except in T1_IFS_S_BLOCK and T1_WTX_S_BLOCK */ static int SendSBlock (reader* globalData, uchar socket, uchar control, uchar data) { uchar PCB = 0, LEN = 0; int retVal; PCB = control; if (PCB == T1_BLOCK_S_IFS_REQ || PCB == T1_BLOCK_S_IFS_RES || PCB == T1_BLOCK_S_WTX_RES) LEN = 1; /* prepare the sendBlock */ globalData->cards[(int)socket].T1.sendBlock.data[0] = 0x00; /* NAD */ globalData->cards[(int)socket].T1.sendBlock.data[1] = PCB; /* PCB */ globalData->cards[(int)socket].T1.sendBlock.data[2] = LEN; /* LEN */ /* copy the INF data (if exists) */ if (LEN) globalData->cards[(int)socket].T1.sendBlock.data[3] = data; globalData->cards[(int)socket].T1.sendBlock.len = LEN + 3; retVal = SendBlock(globalData, socket); return retVal; } /***************************************************************************** * *****************************************************************************/ static int SendRBlock (reader* globalData, uchar socket, char nr) { int retVal; /* NAD */ globalData->cards[(int)socket].T1.sendBlock.data[0] = 0x00; /* PCB */ globalData->cards[(int)socket].T1.sendBlock.data[1] = 0x80; if (nr) globalData->cards[(int)socket].T1.sendBlock.data[1] |= 0x10; /* LEN */ globalData->cards[(int)socket].T1.sendBlock.data[2] = 0x00; globalData->cards[(int)socket].T1.sendBlock.len = 3; retVal = SendBlock(globalData, socket); return retVal; } /***************************************************************************** * *****************************************************************************/ /* handles S-Block requests from the card */ static int ProcessSBlock(reader* globalData, uchar socket) { int retVal, retVal2, wwt, origBwt; T1Block* recBlock = &(globalData->cards[(int)socket].T1.recBlock); // T1Block* sendBlock = &(globalData->cards[(int)socket].T1.sendBlock); struct card_params origCardParams = globalData->cards[(int)socket].cardParams, cardParams; uchar wtx; /* if this is WTX, update params including readers */ if (recBlock->data[1] == T1_BLOCK_S_WTX_REQ) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING S(WTX request)\n"); #endif if (!T1BlockGetInf(recBlock)) return PROTOCOL_T1_ERROR; cardParams = origCardParams; wtx = *(T1BlockGetInf(recBlock)); wwt = cardParams.BWT[0] * 65536 + cardParams.BWT[1] * 256 + cardParams.CWT[2]; wwt *= wtx; wwt += ASE_READER_ETU_DELTA; cardParams.BWT[0] = (uchar)((wwt & 0x00FF0000) >> 16); cardParams.BWT[1] = (uchar)((wwt & 0x0000FF00) >> 8); cardParams.BWT[2] = (uchar)(wwt & 0x000000FF); retVal = SetCardParameters(globalData, socket, cardParams); if (retVal < 0) { return retVal; } origBwt = globalData->cards[(int)socket].bwt; globalData->cards[(int)socket].bwt *= wtx; retVal = SendSBlock(globalData, socket, T1_BLOCK_S_WTX_RES, wtx); /* even if an error occured, we have to set the bwt to its original value */ globalData->cards[(int)socket].bwt = origBwt; /* the next block has already been received, so we can reset the BWT of the reader to its original values. */ retVal2 = SetCardParameters(globalData, socket, origCardParams); // NOTE: the error of the SBlock is checked only after re-setting the reader params to the default if (retVal < 0) { return retVal; } if (retVal2 < 0) { return retVal; } } /* if this if IFS, update params */ else if (recBlock->data[1] == T1_BLOCK_S_IFS_REQ) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING S(IFS request)\n"); #endif if (!T1BlockGetInf(recBlock)) return PROTOCOL_T1_ERROR; globalData->cards[(int)socket].T1.ifsc = MIN(*T1BlockGetInf(recBlock), ATHENA_IFSC_MAX_SIZE); retVal = SendSBlock(globalData, socket, T1_BLOCK_S_IFS_RES, *T1BlockGetInf(recBlock)); if (retVal < 0) { return retVal; } } /* if Abort -> response + return error code */ else if (recBlock->data[1] == T1_BLOCK_S_ABORT_REQ) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING S(ABORT request)\n"); #endif retVal = SendSBlock(globalData, socket, T1_BLOCK_S_ABORT_RES, 0); if (retVal < 0) { return retVal; } return T1_ABORT_RECEIVED; } /* if RESYNCH response -> return error code */ else if (recBlock->data[1] == T1_BLOCK_S_RESYNCH_RES) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING S(RESYNCH response)\n"); #endif return T1_RESYNCH_RECEIVED; } /* if VPP error -> return error code */ else { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING S(VPP error)\n"); #endif return T1_VPP_ERROR_RECEIVED; } /* Resynch request can only be sent by the interface device */ return PROTOCOL_T1_OK; } /***************************************************************************** * *****************************************************************************/ static int SendT1Command (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen) { uchar rsp_type; int bytes; char nr; int retVal, counter, retransmit = 0; char more, finished; T1Block* recBlock = &(globalData->cards[(int)socket].T1.recBlock); // T1Block* sendBlock = &(globalData->cards[(int)socket].T1.sendBlock); #ifdef ASE_DEBUG syslog(LOG_INFO, " SendT1Command - Enter\n"); #endif if ((retVal = cardCommandInit(globalData, socket, 1))) return retVal; /* calculate the number of bytes to send */ counter = 0; bytes = (inBufLen > globalData->cards[(int)socket].T1.ifsc ? globalData->cards[(int)socket].T1.ifsc : inBufLen); /* see if chaining is needed */ more = (inBufLen > globalData->cards[(int)socket].T1.ifsc); finished = 0; /*================================ Sending the request to the card ================================ */ /* send block of data */ retVal = SendIBlock(globalData, socket, inBuf, bytes, more, 1); while (!finished) { /* check if an error occured */ if (retVal < 0) { if (retransmit == 3) return PROTOCOL_T1_ERROR; retransmit++; retVal = SendRBlock(globalData, socket, globalData->cards[(int)socket].T1.ns); } else { /* the block received is valid */ rsp_type = T1BlockGetType(recBlock); /* if all the data has been sent and the response from the card has arrived -> we are done here */ if (!more && rsp_type == T1_BLOCK_I) { finished = 1; } else if (rsp_type == T1_BLOCK_R) { /* errorneous R-Block received */ if (!T1ErrorFreeRBlock(recBlock)) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING R(%d + ERROR)\n", T1BlockGetNR(recBlock)); #endif if (retransmit == 3) return PROTOCOL_T1_ERROR; retransmit++; retVal = SendIBlock(globalData, socket, inBuf + counter, bytes, more, 0); } /* positive ACK R-Block received -> send next I-Block (if there still data left to send) */ else if (T1BlockGetNR(recBlock) != (globalData->cards[(int)socket].T1.ns)) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING R(%d)\n", T1BlockGetNR(recBlock)); #endif retransmit = 0; if (more) { /* calculate the number of bytes to send */ counter += bytes; bytes = ((inBufLen - counter)> globalData->cards[(int)socket].T1.ifsc ? globalData->cards[(int)socket].T1.ifsc : (inBufLen - counter)); /* see if chaining is needed */ more = ((inBufLen - counter) > globalData->cards[(int)socket].T1.ifsc); /* send block of data */ retVal = SendIBlock(globalData, socket, inBuf + counter, bytes, more, 1); } else { /* no more data left to send -> send an R-Block to get acknowledgement */ retVal = SendRBlock(globalData, socket, globalData->cards[(int)socket].T1.ns); } } /* retransmit the current block */ else { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING R(%d)\n", T1BlockGetNR(recBlock)); #endif if (retransmit == 3) return PROTOCOL_T1_ERROR; retransmit++; retVal = SendIBlock(globalData, socket, inBuf + counter, bytes, more, 0); } } /* procees the S-Block request received */ else if (rsp_type == T1_BLOCK_S) { retVal = ProcessSBlock(globalData, socket); retransmit = 0; /* (scenario 20) */ if (retVal == T1_ABORT_RECEIVED || retVal == T1_VPP_ERROR_RECEIVED) { return retVal; } } } } /*=================================== Getting the response from the card =================================== */ counter = 0; *outBufLen = 0; more = 1; retransmit = 0; nr = T1BlockGetNS(recBlock); while (more) { /* check if an error occured */ if (retVal < 0) { if (retransmit == 3) return PROTOCOL_T1_ERROR; retransmit++; retVal = SendRBlock(globalData, socket, (globalData->cards[(int)socket].T1.nsCard + 1) % 2); } else { /* the block received is valid */ rsp_type = T1BlockGetType(recBlock); if (rsp_type == T1_BLOCK_I) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING I(%d,%d)\n", T1BlockGetNS(recBlock), T1BlockGetMore(recBlock)); #endif retransmit = 0; if (nr != T1BlockGetNS(recBlock)) return PROTOCOL_T1_ERROR; globalData->cards[(int)socket].T1.nsCard = T1BlockGetNS(recBlock); /* calculate nr */ nr = (T1BlockGetNS(recBlock) + 1) % 2; /* save inf field */ bytes = T1BlockGetLen(recBlock); if (bytes) memcpy(outBuffer + counter, &(recBlock->data[3]), bytes); counter += bytes; *outBufLen = counter; /* see if chaining is requested */ more = T1BlockGetMore(recBlock); if (more) { retVal = SendRBlock(globalData, socket, nr); } } /* retransmit the current R-Block */ else if ( rsp_type == T1_BLOCK_R) { #ifdef ASE_DEBUG syslog(LOG_INFO, "<<<<<<<<< RECEIVING R(%d)\n", T1BlockGetNR(recBlock)); #endif if (retransmit == 3) return PROTOCOL_T1_ERROR; retransmit++; retVal = SendRBlock(globalData, socket, (globalData->cards[(int)socket].T1.nsCard + 1) % 2); } /* procees the S-Block request received */ else if (rsp_type == T1_BLOCK_S) { retVal = ProcessSBlock(globalData, socket); retransmit = 0; /* if an Abort request is received from the card, check if the next received block is an R-Block: if yes -> return with error, if not -> clear response and continue */ if (retVal == T1_ABORT_RECEIVED) { if (T1BlockGetType(recBlock) == T1_BLOCK_R) { /* the card gave up sending is response */ #ifdef ASE_DEBUG syslog(LOG_INFO, "SendT1Command: card ABORT\n"); #endif return retVal; } else { /* the received block is an S/I-Block -> the card begins retransmitting its response */ *outBufLen = counter = 0; retVal = PROTOCOL_T1_OK; /* so that we could proceed */ } } else if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "SendT1Command: received an errorneous S-Block\n"); #endif return retVal; } } } } #ifdef ASE_DEBUG syslog(LOG_INFO, " SendT1Command - Exit\n"); #endif return retVal; } /***************************************************************************** * *****************************************************************************/ int T1Command (reader* globalData, uchar socket, uchar* inBuf, int inBufLen, uchar* outBuffer, int *outBufLen) { int retVal, retransmitTimes = 0, i; T1Block* recBlock = &(globalData->cards[(int)socket].T1.recBlock); #ifdef ASE_DEBUG syslog(LOG_INFO, "\n T1Command - Enter\n================\n"); #endif retVal = SendT1Command(globalData, socket, inBuf, inBufLen, outBuffer, outBufLen); while (retVal < 0 && retransmitTimes < 3) { /* if the command failed, check the reason and try to recover */ if (retVal < 0) { if (retVal == T1_VPP_ERROR_RECEIVED) { #ifdef ASE_DEBUG syslog(LOG_INFO, "T1Command - Error! T1_VPP_ERROR_RECEIVED\n"); #endif return retVal; /* fatal error */ } else if (retVal == T1_ABORT_RECEIVED) { #ifdef ASE_DEBUG syslog(LOG_INFO, "T1Command - Error! T1_ABORT_RECEIVED - trying again\n"); #endif /* try to retransmit the command */ retVal = SendT1Command(globalData, socket, inBuf, inBufLen, outBuffer, outBufLen); retransmitTimes++; } else { #ifdef ASE_DEBUG syslog(LOG_INFO, "T1Command - Error! retVal = %d\n", retVal); #endif /* general error -> try sending a RESYNCH request up to 3 times */ for (i = 0 ; (i < 3) && (retVal < 0) ; ++i) { retVal = SendSBlock(globalData, socket, T1_BLOCK_S_RESYNCH_REQ, 0); if (!retVal && T1BlockGetType(recBlock) == T1_BLOCK_S) { /* success - check if it's S(RESYNCH response) */ retVal = ProcessSBlock(globalData, socket); if (retVal == T1_RESYNCH_RECEIVED) retVal = PROTOCOL_T1_OK; } else retVal = PROTOCOL_T1_ERROR; /* so that we could send RESYNCH req. again */ } if (retVal < 0) { /* RESYNCH failed 3 times */ #ifdef ASE_DEBUG syslog(LOG_INFO, "T1Command - Error! could not recover - resetting the card\n"); #endif /* retVal = InitCard(globalData, socket, 0, &protocol); // warm reset ?????? */ return PROTOCOL_T1_ERROR; } else { /* RESYNCH succeeded -> init protocol + retry command */ /* init the protocol */ retVal = T1InitProtocol(globalData, socket, 1); /* try to transmit the command again */ retVal = SendT1Command(globalData, socket, inBuf, inBufLen, outBuffer, outBufLen); retransmitTimes++; } } } } /* #ifdef ASE_DEBUG syslog(LOG_INFO, "T1Command - response: "); for (i = 0 ; i < *outBufLen ; ++i) syslog(LOG_INFO, " 0x%x%x", PRINT_CHAR(outBuffer[i])); syslog(LOG_INFO, "\n"); syslog(LOG_INFO, " T1Command - Exit\n================\n\n"); #endif */ return retVal; } asedriveiiie-3.7/asedriveiiie-usb/ifd-ASEDriveIIIe-USB.bundle/0000700000175000017500000000000011265303433024303 5ustar rousseaurousseauasedriveiiie-3.7/asedriveiiie-usb/ifd-ASEDriveIIIe-USB.bundle/Contents/0000700000175000017500000000000011447406541026106 5ustar rousseaurousseauasedriveiiie-3.7/asedriveiiie-usb/ifd-ASEDriveIIIe-USB.bundle/Contents/PkgInfo0000755000175000017500000000001011265303433027364 0ustar rousseaurousseauBNDL????asedriveiiie-3.7/asedriveiiie-usb/ifd-ASEDriveIIIe-USB.bundle/Contents/Linux/0000700000175000017500000000000011265303433027177 5ustar rousseaurousseauasedriveiiie-3.7/asedriveiiie-usb/ifd-ASEDriveIIIe-USB.bundle/Contents/Resources/0000700000175000017500000000000011265303433030052 5ustar rousseaurousseauasedriveiiie-3.7/asedriveiiie-usb/ifd-ASEDriveIIIe-USB.bundle/Contents/Resources/English.lproj/0000700000175000017500000000000011447406541032576 5ustar rousseaurousseau././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootasedriveiiie-3.7/asedriveiiie-usb/ifd-ASEDriveIIIe-USB.bundle/Contents/Resources/English.lproj/InfoPlist.stringsasedriveiiie-3.7/asedriveiiie-usb/ifd-ASEDriveIIIe-USB.bundle/Contents/Resources/English.lproj/InfoP0000755000175000017500000000044211265303433033543 0ustar rousseaurousseau/* Localized versions of Info.plist keys */ CFBundleName = "ifd-AseIIIeUSB"; CFBundleShortVersionString = "ifd-AseIIIeUSB version 0.1.0"; CFBundleGetInfoString = "ifd-AseIIIeUSB version 0.1.0, Copyright 2003"; NSHumanReadableCopyright = "Copyright 2003, Athena Smartcard Solutions"; asedriveiiie-3.7/asedriveiiie-usb/ifd-ASEDriveIIIe-USB.bundle/Contents/Info.plist0000755000175000017500000000221411265303433030064 0ustar rousseaurousseau CFBundleDevelopmentRegion English CFBundleExecutable libASEDriveIIIe-USB.so CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType BNDL CFBundleSignature ???? CFBundleVersion 0.0.1d1 ifdCapabilities 0x00000000 ifdFriendlyName AseIIIeUSB AseIIIeUSB KB ifdManufacturerString Athena SCS ifdProductID 0x0802 0x1104 ifdProductString AseIIIeUSB ifdProtocolSupport 0x00000001 ifdVendorID 0x0DC3 0x0DC3 ifdVersionNumber 0x10000001 asedriveiiie-3.7/asedriveiiie-usb/Makefile.inc0000755000175000017500000000021211441150433021756 0ustar rousseaurousseauPREFIX=/usr USBDROPDIR=/usr/local/pcsc/drivers BUILD= CFLAGS= -pthread -I/usr/local/include/PCSC LDFLAGS= -L/usr/local/lib -lpcsclite asedriveiiie-3.7/asedriveiiie-usb/ifdhandler.c0000755000175000017500000010141211441352667022033 0ustar rousseaurousseau/***************************************************************** / / File : ifdhandler.c / Date : April 9, 2001 / Purpose: This provides reader specific low-level calls / for the ASE-III (USB) reader of Athena Smartcard Solutions. / License: See file LICENSE & COPYING / ******************************************************************/ #include #include "ifdhandler.h" #include #include #include "Ase.h" /***************************************************************************** * *****************************************************************************/ static reader readerData[MAX_READER_NUM]; /***************************************************************************** * *****************************************************************************/ static void closeDriver ( DWORD Lun ) { int retVal, i, readerNum = (Lun & 0xFFFF0000) >> 16; /* if there are some cards that are powered on, power them off */ for (i = 0 ; i < MAX_SOCKET_NUM ; ++i) if (readerData[readerNum].cards[i].status == 2) { retVal = CardPowerOff(&readerData[readerNum], i); /* if (retVal < 0) { return IFD_COMMUNICATION_ERROR; } */ readerData[readerNum].cards[0].atr.length = 0; } retVal = ReaderFinish(&readerData[readerNum]); /* if (retVal < 0) { return IFD_COMMUNICATION_ERROR; } */ // stop reading any response from the reader (if we're doing so currently) // readerData[readerNum].io.stopReading = 1; CloseUSB(&readerData[readerNum]); readerData[readerNum].readerStarted = 0; readerData[readerNum].io.handle = 0; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHCreateChannel ( DWORD Lun, DWORD Channel ) { /* Lun - Logical Unit Number, use this for multiple card slots or multiple readers. 0xXXXXYYYY - XXXX multiple readers, YYYY multiple slots. The resource manager will set these automatically. By default the resource manager loads a new instance of the driver so if your reader does not have more than one smartcard slot then ignore the Lun in all the functions. Future versions of PC/SC might support loading multiple readers through one instance of the driver in which XXXX would be important to implement if you want this. */ /* Channel - Channel ID. This is denoted by the following: 0x000001 - /dev/pcsc/1 0x000002 - /dev/pcsc/2 0x000003 - /dev/pcsc/3 USB readers may choose to ignore this parameter and query the bus for the particular reader. */ /* This function is required to open a communications channel to the port listed by Channel. For example, the first serial reader on COM1 would link to /dev/pcsc/1 which would be a sym link to /dev/ttyS0 on some machines This is used to help with intermachine independance. Once the channel is opened the reader must be in a state in which it is possible to query IFDHICCPresence() for card status. returns: IFD_SUCCESS IFD_COMMUNICATION_ERROR */ UCHAR data[300]; int retVal, len, readerNum = (Lun & 0xFFFF0000) >> 16; #ifdef ASE_DEBUG char name[30]; syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB reader : entering IFDHCreateChannel Channel = 0x%04x%04x Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF), (int)((Channel >> 16) & 0xFFFF), (int)(Channel & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* open the communication */ if (OpenUSB(readerData, &readerData[readerNum]) == TRUE) { #ifdef ASE_DEBUG syslog(LOG_INFO, " opened for IO.\n"/*, readerData[readerNum].io.bus_device*/); #endif } else { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHCreateChannel: Error! Could not open %s. Existing.\n", name); #endif return IFD_COMMUNICATION_ERROR; } /* reader open */ retVal = ReaderStartup(&readerData[readerNum], (char*)data, &len); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHCreateChannel: Error! - in ReaderStartup\n"); syslog(LOG_INFO, "Closing %s.\n", name); #endif CloseUSB(&readerData[readerNum]); return IFD_COMMUNICATION_ERROR; } /* retVal = GetFIDITable(&readerData[readerNum], data, &len); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHCreateChannel: Error! - in GetFIDITable\n"); syslog(LOG_INFO, "Closing %s.\n", name); #endif retVal = ReaderFinish(&readerData[readerNum]); CloseUSB(&readerData[readerNum]); return IFD_COMMUNICATION_ERROR; } */ #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : exisiting IFDHCreateChannel\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHCloseChannel ( DWORD Lun ) { /* This function should close the reader communication channel for the particular reader. Prior to closing the communication channel the reader should make sure the card is powered down and the terminal is also powered down. returns: IFD_SUCCESS IFD_COMMUNICATION_ERROR */ #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : entering IFDHCloseChannel Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif closeDriver(Lun); #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : exisiting IFDHCloseChannel\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHGetCapabilities ( DWORD Lun, DWORD Tag, PDWORD Length, PUCHAR Value ) { /* This function should get the slot/card capabilities for a particular slot/card specified by Lun. Again, if you have only 1 card slot and don't mind loading a new driver for each reader then ignore Lun. Tag - the tag for the information requested example: TAG_IFD_ATR - return the Atr and it's size (required). these tags are defined in ifdhandler.h Length - the length of the returned data Value - the value of the data returns: IFD_SUCCESS IFD_ERROR_TAG */ int readerNum = (Lun & 0xFFFF0000) >> 16; uchar socket = Lun & 0x0000FFFF; #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : entering IFDHGetCapabilities Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); return IFD_ERROR_TAG; } */ switch (Tag) { case TAG_IFD_ATR: { /* If Length is not zero, powerICC has been performed. Otherwise, return NULL pointer Buffer size is stored in *Length */ *Length = readerData[readerNum].cards[socket].atr.length; #ifdef ASE_DEBUG syslog(LOG_INFO, "TAG_IFD_ATR - *Length = %d\n", (int)(*Length)); #endif if (*Length) { memcpy(Value, readerData[readerNum].cards[socket].atr.data, *Length); } break; } case TAG_IFD_SIMULTANEOUS_ACCESS: { #ifdef ASE_DEBUG syslog(LOG_INFO, "TAG_IFD_SIMULTANEOUS_ACCESS\n"); #endif *Length = 1; *Value = MAX_READER_NUM; break; } case TAG_IFD_SLOTS_NUMBER: { #ifdef ASE_DEBUG syslog(LOG_INFO, "TAG_IFD_SLOTS_NUMBER\n"); #endif *Length = 1; *Value = 1; break; } case TAG_IFD_THREAD_SAFE: { #ifdef ASE_DEBUG syslog(LOG_INFO, "TAG_IFD_THREAD_SAFE\n"); #endif if (*Length >= 1) { *Length = 1; *Value = 1; } break; } default: #ifdef ASE_DEBUG syslog(LOG_INFO, "default TAG Tag = %0X\n", (int)Tag); #endif return IFD_ERROR_TAG; } #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : exisiting IFDHGetCapabilities\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHSetCapabilities ( DWORD Lun, DWORD Tag, DWORD Length, PUCHAR Value ) { /* This function should set the slot/card capabilities for a particular slot/card specified by Lun. Again, if you have only 1 card slot and don't mind loading a new driver for each reader then ignore Lun. Tag - the tag for the information needing set Length - the length of the returned data Value - the value of the data returns: IFD_SUCCESS IFD_ERROR_TAG IFD_ERROR_SET_FAILURE IFD_ERROR_VALUE_READ_ONLY */ #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : entering IFDHSetCapabilities Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); return IFD_ERROR_SET_FAILURE; } */ #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : exisiting IFDHSetCapabilities\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHSetProtocolParameters ( DWORD Lun, DWORD Protocol, UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3) { /* This function should set the PTS of a particular card/slot using the three PTS parameters sent Protocol - 0 .... 14 T=0 .... T=14 Flags - Logical OR of possible values: IFD_NEGOTIATE_PTS1 IFD_NEGOTIATE_PTS2 IFD_NEGOTIATE_PTS3 to determine which PTS values to negotiate. PTS1,PTS2,PTS3 - PTS Values. returns: IFD_SUCCESS IFD_ERROR_PTS_FAILURE IFD_COMMUNICATION_ERROR IFD_PROTOCOL_NOT_SUPPORTED */ int retVal, PPS1present, PPS2present, PPS3present; int readerNum = (Lun & 0xFFFF0000) >> 16; uchar socket = Lun & 0x0000FFFF, ppsProt; #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : entering IFDHSetProtocolParameters Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); return IFD_COMMUNICATION_ERROR; } */ /* works only for T=0 and T=1 */ if (Protocol != SCARD_PROTOCOL_T0 && Protocol != SCARD_PROTOCOL_T1) { return IFD_PROTOCOL_NOT_SUPPORTED; } /* check if the card is absent */ if (!readerData[readerNum].cards[socket].status) return IFD_COMMUNICATION_ERROR; PPS1present = Flags & IFD_NEGOTIATE_PTS1; PPS2present = Flags & IFD_NEGOTIATE_PTS2; PPS3present = Flags & IFD_NEGOTIATE_PTS3; /* in the meanwhile only protocol could be set */ if (PPS1present || PPS2present || PPS3present) return IFD_ERROR_PTS_FAILURE; if (Protocol == SCARD_PROTOCOL_T0) ppsProt = 0; else ppsProt = 1; /* do a cold reset followed by PPS (if needed) only if the current protocol is to be changed*/ if (readerData[readerNum].cards[socket].status == 2 && ((readerData[readerNum].cards[socket].activeProtocol == 0 && ppsProt != 0) || (readerData[readerNum].cards[socket].activeProtocol == 1 && ppsProt != 1))) { retVal = InitCard(&readerData[readerNum], socket, 1, (char*)(&ppsProt)); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHSetProtocolParameters - Error! retVal = %d\n", retVal); #endif return IFD_ERROR_PTS_FAILURE; } } #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : exisiting IFDHSetProtocolParameters\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHPowerICC ( DWORD Lun, DWORD Action, PUCHAR Atr, PDWORD AtrLength ) { /* This function controls the power and reset signals of the smartcard reader at the particular reader/slot specified by Lun. Action - Action to be taken on the card. IFD_POWER_UP - Power and reset the card if not done so (store the ATR and return it and it's length). IFD_POWER_DOWN - Power down the card if not done already (Atr/AtrLength should be zero'd) IFD_RESET - Perform a quick reset on the card. If the card is not powered power up the card. (Store and return the Atr/Length) Atr - Answer to Reset of the card. The driver is responsible for caching this value in case IFDHGetCapabilities is called requesting the ATR and it's length. This should not exceed MAX_ATR_SIZE. AtrLength - Length of the Atr. This should not exceed MAX_ATR_SIZE. Notes: Memory cards without an ATR should return IFD_SUCCESS on reset but the Atr should be zero'd and the length should be zero Reset errors should return zero for the AtrLength and return IFD_ERROR_POWER_ACTION. returns: IFD_SUCCESS IFD_ERROR_POWER_ACTION IFD_COMMUNICATION_ERROR IFD_NOT_SUPPORTED */ int retVal, readerNum = (Lun & 0xFFFF0000) >> 16; uchar socket = Lun & 0x0000FFFF; #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : entering IFDHPowerICC Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* zero everything */ *AtrLength = 0; memset(Atr, 0, MAX_ATR_SIZE); /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); return IFD_COMMUNICATION_ERROR; } */ if (readerData[readerNum].cards[socket].activeProtocol == ATR_PROTOCOL_TYPE_RAW && Action == IFD_RESET) Action = IFD_POWER_UP; switch (Action) { case IFD_POWER_UP: /* check if already powered up */ if (readerData[readerNum].cards[socket].status != 2) { retVal = InitCard(&readerData[readerNum], socket, 1, NULL); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHPowerICC: Error! in InitCard status = %d\n", readerData[readerNum].cards[socket].status); #endif return IFD_ERROR_POWER_ACTION; } } *AtrLength = readerData[readerNum].cards[socket].atr.length; if (*AtrLength) { memcpy(Atr, readerData[readerNum].cards[socket].atr.data, *AtrLength); } break; case IFD_RESET: if (readerData[readerNum].cards[socket].activeProtocol == ATR_PROTOCOL_TYPE_RAW) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHPowerICC - Error! while powering on mem card with warm reset\n"); #endif return IFD_ERROR_POWER_ACTION; /* warm reset is not allowed for memort cards */ } if (readerData[readerNum].cards[socket].status == 2) { /* powered up -> warm reset */ retVal = InitCard(&readerData[readerNum], socket, 0, NULL); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHPowerICC - Error! while powering on card with warm reset\n"); #endif return IFD_COMMUNICATION_ERROR; } } else { /* not powered up -> cold reset */ retVal = InitCard(&readerData[readerNum], socket, 1, NULL); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHPowerICC - Error! while powering on card with cold reset\n"); #endif return IFD_COMMUNICATION_ERROR; } } *AtrLength = readerData[readerNum].cards[socket].atr.length; if (*AtrLength) { memcpy(Atr, readerData[readerNum].cards[socket].atr.data, *AtrLength); } break; case IFD_POWER_DOWN: /* check if the card is not already powered off */ if (readerData[readerNum].cards[socket].status == 2) { retVal = CardPowerOff(&readerData[readerNum], socket); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHPowerICC - Error! while powering off card\n"); #endif return IFD_COMMUNICATION_ERROR; } } readerData[readerNum].cards[socket].atr.length = 0; break; default: return IFD_NOT_SUPPORTED; } #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : exiting IFDHPowerICC\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHTransmitToICC ( DWORD Lun, SCARD_IO_HEADER SendPci, PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength, PSCARD_IO_HEADER RecvPci ) { /* This function performs an APDU exchange with the card/slot specified by Lun. The driver is responsible for performing any protocol specific exchanges such as T=0/1 ... differences. Calling this function will abstract all protocol differences. SendPci Protocol - 0, 1, .... 14 Length - Not used. TxBuffer - Transmit APDU example (0x00 0xA4 0x00 0x00 0x02 0x3F 0x00) TxLength - Length of this buffer. RxBuffer - Receive APDU example (0x61 0x14) RxLength - Length of the received APDU. This function will be passed the size of the buffer of RxBuffer and this function is responsible for setting this to the length of the received APDU. This should be ZERO on all errors. The resource manager will take responsibility of zeroing out any temporary APDU buffers for security reasons. RecvPci Protocol - 0, 1, .... 14 Length - Not used. Notes: The driver is responsible for knowing what type of card it has. If the current slot/card contains a memory card then this command should ignore the Protocol and use the MCT style commands for support for these style cards and transmit them appropriately. If your reader does not support memory cards or you don't want to then ignore this. RxLength should be set to zero on error. returns: IFD_SUCCESS IFD_COMMUNICATION_ERROR IFD_RESPONSE_TIMEOUT IFD_ICC_NOT_PRESENT IFD_PROTOCOL_NOT_SUPPORTED */ int retVal, actual, readerNum = (Lun & 0xFFFF0000) >> 16; UCHAR response[65535], socket = Lun & 0x0000FFFF; UCHAR TxBuffer2[5]; #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : entering IFDHTransmitToICC Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } */ if (TxBuffer == NULL || TxLength == 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "ASE IIIe USB Reader : IFDHTransmitToICC - Error - no data in command!!!\n"); #endif if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } switch (SendPci.Protocol) { case ATR_PROTOCOL_TYPE_T0: if (readerData[readerNum].cards[socket].status == 1) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; /* not powered on */ } else if (readerData[readerNum].cards[socket].status == 0) { if (RxLength) *RxLength = 0; return IFD_ICC_NOT_PRESENT; } else if (readerData[readerNum].cards[socket].activeProtocol != 0) { /* current protocol isnt T=0 */ if (RxLength) *RxLength = 0; return IFD_PROTOCOL_NOT_SUPPORTED; } else { /* card is powered on */ if (RecvPci) RecvPci->Protocol = ATR_PROTOCOL_TYPE_T0; if (TxLength > 5) { // check if it's a case 4 command that should be splitted into write + get response DWORD tmpLen=4 + 1 + TxBuffer[4] + 1; if (TxLength == tmpLen) { retVal = T0Write(&readerData[readerNum], socket, TxBuffer, TxLength - 1, response, &actual); if (retVal == ASE_OK && actual == 2 && response[0] == 0x61) { // now send a Get Response apdu unsigned short newLen = (TxBuffer[TxLength - 1] == 0 ? 256 : TxBuffer[TxLength - 1]); UCHAR Le = (newLen < response[1] ? (newLen == 256 ? 0 : newLen) : response[1]); UCHAR getResponseCmd[5] = {0x00, 0xC0, 0x00, 0x00, 0x00}; // getResponseCmd[0] = TxBuffer[0]; getResponseCmd[4] = Le; retVal = T0Read(&readerData[readerNum], socket, getResponseCmd, 5, response, &actual); } } else { retVal = T0Write(&readerData[readerNum], socket, TxBuffer, TxLength, response, &actual); } if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } else if (TxLength == 4) { /* case 1 */ memcpy(TxBuffer2, TxBuffer, 4); TxBuffer2[4] = 0x00; retVal = T0Write(&readerData[readerNum], socket, TxBuffer2, 5, response, &actual); if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } else { retVal = T0Read(&readerData[readerNum], socket, TxBuffer, TxLength, response, &actual); if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } } break; case ATR_PROTOCOL_TYPE_T1: if (readerData[readerNum].cards[socket].status == 1) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; /* not powered on */ } else if (readerData[readerNum].cards[socket].status == 0) { if (RxLength) *RxLength = 0; return IFD_ICC_NOT_PRESENT; } else if (readerData[readerNum].cards[socket].activeProtocol != 1) { /* current protocol isnt T=1 */ if (RxLength) *RxLength = 0; return IFD_PROTOCOL_NOT_SUPPORTED; } else { /* card is powered on */ if (RecvPci) RecvPci->Protocol = ATR_PROTOCOL_TYPE_T1; retVal = T1Command (&readerData[readerNum], socket, TxBuffer, TxLength, response, &actual); if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } break; default: if (RxLength) *RxLength = 0; return IFD_PROTOCOL_NOT_SUPPORTED; } #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : exisiting IFDHTransmitToICC\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHControl ( DWORD Lun, PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength ) { /* This function performs a data exchange with the reader (not the card) specified by Lun. Here XXXX will only be used. It is responsible for abstracting functionality such as PIN pads, biometrics, LCD panels, etc. You should follow the MCT, CTBCS specifications for a list of accepted commands to implement. TxBuffer - Transmit data TxLength - Length of this buffer. RxBuffer - Receive data RxLength - Length of the received data. This function will be passed the length of the buffer RxBuffer and it must set this to the length of the received data. Notes: RxLength should be zero on error. */ int retVal, actual, readerNum = (Lun & 0xFFFF0000) >> 16; uchar socket = Lun & 0x0000FFFF; UCHAR response[700]; #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : entering IFDHControl Lun = 0x%04x%04x\n", (int)((Lun >> 16) & 0xFFFF), (int)(Lun & 0xFFFF)); syslog(LOG_INFO, "==============================================\n"); #endif /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } */ /* check if its an ioctl for the reader */ if (TxLength >= 4 && TxBuffer[0] == ASE_IOCTL_CLASS && TxBuffer[1] == ASE_IOCTL_XI2C_INS) { struct card_params params = readerData[readerNum].cards[socket].cardParams; params.protocol = 0x22; retVal = SetCardParameters(&readerData[readerNum], socket, params); if (retVal < 0) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } } else if (TxLength >= 4 && TxBuffer[0] == ASE_IOCTL_CLASS && TxBuffer[1] == ASE_IOCTL_CLOCK_INS) { /* change clock in reader - not supported yet */ } // other ioctls sent to the reader else if (TxLength >= 4 && TxBuffer[0] == ASE_IOCTL_RAW_CLASS && TxBuffer[1] == ASE_IOCTL_RAW_INS) { actual = (RxLength ? *RxLength : 0); retVal = SendIOCTL(&readerData[readerNum], socket, &TxBuffer[2], TxLength - 2, response, &actual); if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } /* card eject */ else if (TxLength == 5 && TxBuffer[0] == 0x20 && TxBuffer[1] == 0x15 && TxBuffer[3] == 0x00 && TxBuffer[4] == 0x00) { retVal = CardPowerOff(&readerData[readerNum], socket); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHControl - Error! while ejecting card\n"); #endif if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } readerData[readerNum].cards[socket].atr.length = 0; // return success status *RxLength = 2; RxBuffer[0] = 0x90; RxBuffer[1] = 0x00; // try to eject the card (dont care if fail) { unsigned char EXTRACT_CARD[] = {0x50, 0x63, 0x0, 0x33}; actual = 2; retVal = SendIOCTL(&readerData[readerNum], socket, EXTRACT_CARD, sizeof(EXTRACT_CARD), response, &actual); } } else if (readerData[readerNum].cards[socket].activeProtocol == ATR_PROTOCOL_TYPE_RAW) { if (readerData[readerNum].cards[socket].status == 1 || readerData[readerNum].cards[socket].status == 0) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; /* not powered on or absent */ } retVal = MemoryCardCommand (&readerData[readerNum], socket, TxBuffer, TxLength, response, &actual); if (retVal < 0 || *RxLength < (DWORD)actual) { if (RxLength) *RxLength = 0; return IFD_COMMUNICATION_ERROR; } *RxLength = actual; if (*RxLength) memcpy(RxBuffer, response, *RxLength); } #ifdef ASE_DEBUG syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : exisiting IFDHControl\n"); syslog(LOG_INFO, "==============================================\n"); #endif return IFD_SUCCESS; } /***************************************************************************** * *****************************************************************************/ RESPONSECODE IFDHICCPresence( DWORD Lun ) { /* This function returns the status of the card inserted in the reader/slot specified by Lun. It will return either: returns: IFD_ICC_PRESENT IFD_ICC_NOT_PRESENT IFD_COMMUNICATION_ERROR */ UCHAR data[300]; int retVal, len, readerNum = (Lun & 0xFFFF0000) >> 16; uchar socket = Lun & 0x0000FFFF; /* syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : entering IFDHICCPresence Lun = 0x%04x%04x\n", (Lun >> 16) & 0xFFFF, Lun & 0xFFFF); syslog(LOG_INFO, "==============================================\n"); */ /* if (!readerData[readerNum].fd || !DeviceIsConnected(&readerData[readerNum])) { closeDriver(Lun); return IFD_COMMUNICATION_ERROR; } */ retVal = GetStatus(&readerData[readerNum], (char*)data, &len); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHICCPresence: Error! - in GetStatus\n"); #endif return IFD_COMMUNICATION_ERROR; } /* syslog(LOG_INFO, "==============================================\n"); syslog(LOG_INFO, "ASE IIIe USB Reader : exisiting IFDHICCPresence\n"); syslog(LOG_INFO, "==============================================\n"); */ #ifdef ASE_DEBUG syslog(LOG_INFO, "IFDHICCPresence: status = %d\n", readerData[readerNum].cards[socket].status); #endif return (readerData[readerNum].cards[socket].status ? IFD_ICC_PRESENT : IFD_ICC_NOT_PRESENT); } asedriveiiie-3.7/asedriveiiie-usb/Makefile0000755000175000017500000000207311441362720021221 0ustar rousseaurousseau include Makefile.inc DRIVER_DIR=${DESTDIR}/${USBDROPDIR}/ifd-ASEDriveIIIe-USB.bundle CC=${BUILD}-gcc SOURCES=usb.c atr.c DriverIO.c CommandTypes.c ReaderCommands.c T1Protocol.c MemoryCards.c InitCardParams.c ifdhandler.c all: libASEDriveIIIe-USB.so libASEDriveIIIe-USB.so: ${SOURCES} ${CC} -o libASEDriveIIIe-USB.so ${SOURCES} -fPIC -D_REENTRANT -DIFDHANDLERv2 -Wall -I. ${CFLAGS} ${LDFLAGS} -lusb -shared clean-all: clean rm Makefile.inc || true clean: rm -f *~ *.o *.so || true install: all install -c -d "${DRIVER_DIR}/Contents" install -c -m 0644 ifd-ASEDriveIIIe-USB.bundle/Contents/Info.plist ifd-ASEDriveIIIe-USB.bundle/Contents/PkgInfo "${DRIVER_DIR}/Contents" install -c -d "${DRIVER_DIR}/Contents/Resources/English.lproj" install -c -m 0644 ifd-ASEDriveIIIe-USB.bundle/Contents/Resources/English.lproj/InfoPlist.strings "${DRIVER_DIR}/Contents/Resources/English.lproj" install -c -d "${DRIVER_DIR}/Contents/Linux" install -c -m 0755 libASEDriveIIIe-USB.so "${DRIVER_DIR}/Contents/Linux" install -c -m 0644 50-pcscd-asedriveiiie.rules /etc/udev/rules.d/. asedriveiiie-3.7/asedriveiiie-usb/usb.c0000755000175000017500000002621111441357117020522 0ustar rousseaurousseau/***************************************************************** / / File : usb.c / Date : April 9, 2001 / Purpose: This provides reader specific low-level calls / for the ASE-III (USB) reader of Athena Smartcard Solutions. / License: See file LICENSE / ******************************************************************/ #include #include #include #include "Ase.h" /***************************************************************************** * *****************************************************************************/ #define USB_INEP 0 #define USB_OUTEP 1 /* ok */ #define USB_TIMEOUT 60000 /* 1 minute timeout */ #define MAX_USB_RESPONSE 300 /* the maximal size of any response coming from the reader */ /***************************************************************************** * *****************************************************************************/ typedef struct { int kMyVendorID; int kMyProductID; } _usbID; static _usbID UsbIDs[] = { { 0x0DC3, 0x0802 }, { 0x0DC3, 0x1104 }, }; /***************************************************************************** * *****************************************************************************/ bool OpenUSB(reader* allReaders, reader* globalData) { static struct usb_bus* busses = NULL; int id, id_number; struct usb_bus* bus; struct usb_dev_handle* dev_handle; #ifdef ASE_DEBUG int k; syslog(LOG_INFO, "OpenUSB: "); #endif if (busses == NULL) { usb_init(); } usb_find_busses(); usb_find_devices(); busses = usb_get_busses(); if (busses == NULL) { #ifdef ASE_DEBUG syslog(LOG_INFO, "No USB busses found"); #endif return FALSE; } if (globalData->io.handle != NULL) { #ifdef ASE_DEBUG syslog(LOG_INFO, "USB driver in use"); #endif return FALSE; } /* find any device corresponding to a UsbIDs entry */ id_number = sizeof(UsbIDs)/sizeof(UsbIDs[0]); /* for any supported reader */ for (id = 0; id < id_number ; id++) { /* on any USB buses */ for (bus = busses; bus; bus = bus->next) { struct usb_device *dev; /* any device on this bus */ for (dev = bus->devices; dev; dev = dev->next) { if (dev->descriptor.idVendor == UsbIDs[id].kMyVendorID && dev->descriptor.idProduct == UsbIDs[id].kMyProductID) { int r, already_used; char bus_device[BUS_DEVICE_STRSIZE]; if (snprintf(bus_device, BUS_DEVICE_STRSIZE, "%s/%s", bus->dirname, dev->filename) < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "Device name too long: %s", bus_device); #endif return FALSE; } already_used = FALSE; for (r = 0; r < MAX_READER_NUM ; r++) { #ifdef ASE_DEBUG syslog(LOG_INFO, "Checking new device '%s' against old '%s'", bus_device, allReaders[r].io.bus_device); #endif if (strcmp(allReaders[r].io.bus_device, bus_device) == 0) already_used = TRUE; } if (!already_used) { dev_handle = usb_open(dev); if (dev_handle) { int interface; int retVal; int interfaceNum = 0; #ifdef ASE_DEBUG syslog(LOG_INFO, "Trying to open USB bus/device: %s", bus_device); #endif if (dev->config == NULL) { #ifdef ASE_DEBUG syslog(LOG_INFO, "No dev->config found for %s", bus_device); #endif return FALSE; } interface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber; retVal = usb_claim_interface(dev_handle, interface); if ((retVal < 0) && (EPERM == errno)) { usb_close(dev_handle); return FALSE; } if (retVal < 0 || dev->config[0].interface[0].altsetting[0].bNumEndpoints != 2) { #ifdef ASE_DEBUG syslog(LOG_INFO, "Can't claim interface 0 %s: %s (or not the correct one (KB))", globalData->io.bus_device, strerror(errno)); #endif if (retVal == 0) usb_release_interface(dev_handle, interface); // try the second interface interface = dev->config[0].interface[1].altsetting[0].bInterfaceNumber; if (usb_claim_interface(dev_handle, interface) < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "Can't claim interface 1 %s: %s", globalData->io.bus_device, strerror(errno)); #endif return FALSE; } #ifdef ASE_DEBUG syslog(LOG_INFO, "Using interface 1 (dev->config[0].interface[1].altsetting[0].bInterfaceNumber = %d)", dev->config[0].interface[1].altsetting[0].bInterfaceNumber); #endif interfaceNum = 1; } #ifdef ASE_DEBUG syslog(LOG_INFO, "Using USB bus/device: %s", bus_device); for (k = 0 ; k < dev->config[0].interface[interfaceNum].altsetting[0].bNumEndpoints ; k++) syslog(LOG_INFO, "ep[%d] -> bDescriptorType = %X bEndpointAddress = %X bmAttributes = %X wMaxPacketSize = %X bLength = %x\n", k, dev->config[0].interface[interfaceNum].altsetting[0].endpoint[k].bDescriptorType, dev->config[0].interface[interfaceNum].altsetting[0].endpoint[k].bEndpointAddress, dev->config[0].interface[interfaceNum].altsetting[0].endpoint[k].bmAttributes, dev->config[0].interface[interfaceNum].altsetting[0].endpoint[k].bmAttributes, dev->config[0].interface[interfaceNum].altsetting[0].endpoint[k].bLength); #endif /* store device information */ globalData->io.curPos = globalData->io.lastPos = globalData->io.stopReading = 0; globalData->io.handle = dev_handle; globalData->io.dev = dev; strncpy(globalData->io.bus_device, bus_device, BUS_DEVICE_STRSIZE); globalData->io.interface = interface; globalData->io.bulk_in = globalData->io.dev->config[0].interface[interfaceNum].altsetting[0].endpoint[USB_INEP].bEndpointAddress; globalData->io.bulk_out = globalData->io.dev->config[0].interface[interfaceNum].altsetting[0].endpoint[USB_OUTEP].bEndpointAddress; #ifdef ASE_DEBUG syslog(LOG_INFO, "globalData->io.bulk_in = 0x%x globalData->io.bulk_out = 0x%x", globalData->io.bulk_in, globalData->io.bulk_out); #endif return TRUE; } else { #ifdef ASE_DEBUG syslog(LOG_INFO, "Can't usb_open(%s): %s", bus_device, strerror(errno)); #endif } } else { #ifdef ASE_DEBUG syslog(LOG_INFO, "USB device %s already in use. Checking next one.", bus_device); #endif } } } } } if (globalData->io.handle == NULL) return FALSE; return TRUE; } /***************************************************************************** * *****************************************************************************/ int WriteUSB(reader* globalData, int writesize, unsigned char* data) { int i, remain = writesize; i = usb_bulk_write(globalData->io.handle, globalData->io.bulk_out, (char*)data, remain, USB_TIMEOUT); if (i < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "WriteUSB: Error! (i = %d)\n", i); #endif return 0; } return writesize; } /***************************************************************************** * *****************************************************************************/ int ReadUSB(reader* globalData, unsigned long timeout, int len, unsigned char *buf) { unsigned int saveLast = globalData->io.lastPos; unsigned int remain=len; int ret = 0, count, rval, k; // unsigned long timeoutChunk = 100000; // 0.1 sec unsigned char temp[MAX_USB_RESPONSE]; saveLast = globalData->io.lastPos; // no data available - try reading from reader if (globalData->io.curPos == saveLast) { // read at most RESPONSE_BUFFER_SIZE bytes rval = usb_bulk_read(globalData->io.handle, globalData->io.bulk_in, (char*)temp, MAX_USB_RESPONSE, timeout); // dealing with the zero data frame - resend the request if no data arrived if (rval <= 0) rval = usb_bulk_read(globalData->io.handle, globalData->io.bulk_in, (char*)temp, MAX_USB_RESPONSE, timeout); if (rval > 0) { // copy the data read to the buffer saveLast = globalData->io.lastPos; for (k = 0 ; k < rval ; ++k) { globalData->io.response[saveLast++] = temp[k]; saveLast %= RESPONSE_BUFFER_SIZE; #ifdef ASE_DEBUG syslog(LOG_INFO, "<=== 0x%02x\n", temp[k]); #endif } globalData->io.lastPos = saveLast; } } saveLast = globalData->io.lastPos; // some data read is waiting to be returned if (globalData->io.curPos != saveLast) { if (globalData->io.curPos < saveLast) { count = (saveLast - globalData->io.curPos) > remain ? remain : (saveLast - globalData->io.curPos); memcpy((unsigned char*)buf, &(globalData->io.response[globalData->io.curPos]), count); ret += count; remain -= count; globalData->io.curPos += count; globalData->io.curPos %= RESPONSE_BUFFER_SIZE; } else { count = (RESPONSE_BUFFER_SIZE - globalData->io.curPos) > remain ? remain : (RESPONSE_BUFFER_SIZE - globalData->io.curPos); memcpy((unsigned char*)buf, &(globalData->io.response[globalData->io.curPos]), count); globalData->io.curPos += count; globalData->io.curPos %= RESPONSE_BUFFER_SIZE; ret += count; remain -= count; if (remain > 0) { // more bytes to copy (len-ret at most) count = (saveLast < remain) ? saveLast : remain; if (count) { memcpy((unsigned char*)(&buf[ret]), globalData->io.response, count); ret += count; remain -= count; } globalData->io.curPos = count; globalData->io.curPos %= RESPONSE_BUFFER_SIZE; } } } #ifdef ASE_DEBUG syslog(LOG_INFO, "ReadUSB: ret = %d length = %d timeout = %d\n", ret, len, (int)timeout); #endif return ret; } //***************************************************************************** // //***************************************************************************** void CleanReadBufferUSB(reader* globalData) { // unsigned char temp[700]; // // usb_bulk_read(globalData->io.handle, // globalData->io.dev->config[0].interface[0].altsetting[0].endpoint[USB_INEP].bEndpointAddress, // temp, 300, 1000 /* 1 sec */); globalData->io.curPos = globalData->io.lastPos = 0; } /***************************************************************************** * *****************************************************************************/ bool CloseUSB(reader* globalData) { #ifdef ASE_DEBUG syslog(LOG_INFO, "CloseUSB: device = %s", globalData->io.bus_device); #endif usb_release_interface(globalData->io.handle, globalData->io.interface); usb_reset(globalData->io.handle); usb_close(globalData->io.handle); /* mark the resource unused */ globalData->io.handle = NULL; globalData->io.dev = NULL; globalData->io.bus_device[0] = '\0'; globalData->io.stopReading = 1; return TRUE; } asedriveiiie-3.7/asedriveiiie-usb/InitCardParams.c0000755000175000017500000006671211441351126022576 0ustar rousseaurousseau#include "Ase.h" #include /***************************************************************************** * *****************************************************************************/ #define ASE_PPS_DEFAULT_USED -1000 #define ASE_PPS_FAILED -1001 /***************************************************************************** * *****************************************************************************/ #define EPSILON 0.001 static int fi[16] = { 372, 372, 558, 744, 1116, 1488, 1860, 1, 1, 512, 768, 1024, 1536, 2048, 1, 1 }; static int di[16] = { 1, 1, 2, 4, 8, 16, 32, 1, 12, 20, 1, 1, 1, 1, 1, 1 }; static long fs[16] = {4000000, 5000000, 6000000, 8000000, 12000000, 16000000, 20000000, 0, 0, 5000000, 7500000, 10000000, 15000000, 20000000, 0, 0}; /***************************************************************************** * *****************************************************************************/ static void GetDefaultReaderParams (reader* globalData, struct card_params* params) { params->protocol = 0; params->N = 0x03; params->CWT[0] = 0x00; params->CWT[1] = 0x25/*0x85*/; params->CWT[2] = 0x85/*0xF0*/; params->BWT[0] = 0x00; params->BWT[1] = 0x3A/*0x38*/; params->BWT[2] = 0x34/*0xA4*/; /* 372 */ params->A = 0x01; params->B = 0x74; params->freq = 0x02; params->fTod = 372.0; } /***************************************************************************** * *****************************************************************************/ static int MatchReaderParams(reader* globalData, char socket, struct card_params* params, ATR* atr, uchar Fi, uchar Di, uchar WI, uchar N, char protocol) { uchar found = 0; int F, D, WWT; float cardFToD = GetFToDFactor(Fi, Di); float readerFToD; int etuFactor; long maxFreq = fs[Fi]; int etus; #ifdef ASE_DEBUG syslog(LOG_INFO, "MatchReaderParams: card Fi = %d, Di = %d, Wi = %d, cardFToD = %f\n",Fi, Di, WI, cardFToD); #endif if (maxFreq >= 16000000) { params->freq = 0; //f = 16000000; } else if (maxFreq >= 8000000) { params->freq = 1; //f = 8000000; } else if (maxFreq >= 4000000) { params->freq = 2; //f = 4000000; } else { params->freq = 3; //f = 2000000; } /* check to see if the card parameters are supported by the reader: if readerFToD is smaller than cardFToD */ readerFToD = (float)(globalData->dataMemory[14]) * 256.0 + (float)(globalData->dataMemory[13]); if ((readerFToD - EPSILON) <= cardFToD) { found = 1; F = fi[Fi]; D = di[Di]; params->fTod = cardFToD; globalData->cards[(int)socket].FiDi = (Fi << 4) | Di; etus = (int)(cardFToD + 0.5); params->A = (etus & 0xFF00) >> 8; params->B = etus & 0x00FF; } if (!found) return ASE_READER_NO_MATCHING_PARAMS; params->protocol = protocol; params->N = N; if (protocol == ATR_PROTOCOL_TYPE_T0) { WWT = WI * 960 * D + ASE_READER_ETU_DELTA; params->CWT[0] = (uchar)((WWT & 0x00FF0000) >> 16); params->CWT[1] = (uchar)((WWT & 0x0000FF00) >> 8); params->CWT[2] = (uchar)(WWT & 0x000000FF); /* for T=0 they are identical */ params->BWT[0] = params->CWT[0]; params->BWT[1] = params->CWT[1]; params->BWT[2] = params->CWT[2]; } else { /* T = 1 */ WWT = 11 + (1 << GetT1CWI(atr)) + ASE_READER_ETU_DELTA; params->CWT[0] = (uchar)((WWT & 0x00FF0000) >> 16); params->CWT[1] = (uchar)((WWT & 0x0000FF00) >> 8); params->CWT[2] = (uchar)(WWT & 0x000000FF); etuFactor = (int)((float)(372.0 / cardFToD) + 0.5); if (etuFactor == 0) etuFactor = 1; #ifdef ASE_DEBUG syslog(LOG_INFO, "MatchReaderParams: etuFactor = %d\n", etuFactor); #endif WWT = 11 + (1 << GetT1BWI(atr)) * 960 * etuFactor + ASE_READER_ETU_DELTA; params->BWT[0] = (uchar)((WWT & 0x00FF0000) >> 16); params->BWT[1] = (uchar)((WWT & 0x0000FF00) >> 8); params->BWT[2] = (uchar)(WWT & 0x000000FF); } #ifdef ASE_DEBUG syslog(LOG_INFO, "MatchReaderParams: freq = %d, A = %d, B = %d, WWT = %d, protocol = %d, N = %d\n", params->freq, params->A, params->B, WWT, params->protocol, params->N); #endif return ASE_OK; } /***************************************************************************** * *****************************************************************************/ static int PPS (reader* globalData, char socket, uchar protocol, uchar* PPS1, uchar* PPS2, uchar* PPS3) { int retVal, len, actual, PPS1echoed, PPS2echoed, PPS3echoed; uchar request[6], response[6]; uchar PPSSreq, PPS0req, PCKreq, checksum; #ifdef ASE_DEBUG int i; syslog(LOG_INFO, "\n PPS - Enter - protocol = %d\n", protocol); #endif PPSSreq = request[0] = 0xFF; PPS0req = request[1] = 0x00 | protocol; /* PPS1 must always appear -> if not passed as a parameter, take from the globalData!!! otherwise, we propose to work with Fd and Dd - and that's not usually the intention */ /* if (PPS1) */ PPS0req = request[1] = PPS0req | 0x10; if (PPS2) PPS0req = request[1] = PPS0req | 0x20; if (PPS3) PPS0req = request[1] = PPS0req | 0x40; PCKreq = request[0] ^ request[1]; len = 2; if (PPS1) { request[len] = *PPS1; } else { request[len] = globalData->cards[(int)socket].FiDi; } PCKreq ^= request[len]; len++; if (PPS2) { request[len] = *PPS2; PCKreq ^= request[len]; len++; } if (PPS3) { request[len] = *PPS3; PCKreq ^= request[len]; len++; } request[len] = PCKreq; len++; if ((retVal = cardCommandInit(globalData, socket, 0))) return retVal; /* init the protocol if it's a PPS to T=1 */ if (protocol == ATR_PROTOCOL_TYPE_T1) T1InitProtocol(globalData, socket, 0); retVal = PPSTransact(globalData, socket, (char*)request, len, (char*)response, &actual); if (retVal < 0) { #ifdef ASE_DEBUG syslog(LOG_INFO, "PPS - Error!.\n"); #endif return retVal; } #ifdef ASE_DEBUG syslog(LOG_INFO, "PPS: response = "); for (i = 0 ; i < actual ; ++i) syslog(LOG_INFO, "0x%x%x ", PRINT_CHAR(response[i])); syslog(LOG_INFO, "\n"); #endif /* parse the reuslt */ if (actual < 3) /* must return at least 3 bytes */ return ASE_PPS_FAILED; len = 2; if (response[0] == PPSSreq) { /* PPSS */ checksum = response[0]; if ((response[1] & 0x0F) == (PPS0req & 0x0F)) { /* PPS0 */ checksum ^= response[1]; PPS1echoed = response[1] & 0x10; PPS2echoed = response[1] & 0x20; PPS3echoed = response[1] & 0x40; if (PPS1echoed) { /* if (PPS1 && response[len] == *PPS1) // if echoed, should be identical */ if (response[len] == request[2]) /* if echoed, should be identical */ checksum ^= response[len]; else return ASE_PPS_FAILED; len++; } if (PPS2echoed) { if (PPS2 && response[len] == *PPS2) /* if echoed, should be identical */ checksum ^= response[len]; else return ASE_PPS_FAILED; len++; } if (PPS3echoed) { if (PPS3 && response[len] == *PPS3) /* if echoed, should be identical */ checksum ^= response[len]; else return ASE_PPS_FAILED; len++; } if (response[len] == checksum) { if (!PPS1echoed) return ASE_PPS_DEFAULT_USED; return ASE_OK; } else return ASE_PPS_FAILED; } else return ASE_PPS_FAILED; } else return ASE_PPS_FAILED; } /***************************************************************************** * *****************************************************************************/ static int DoPPS (reader* globalData, char socket, struct card_params* params, uchar protocol, int voltage) { int retVal; ATR* atr = &(globalData->cards[(int)socket].atr); float cardFToD; float readerFToD; uchar PPS1; int cardDi = GetDi(atr), cardFi = GetFi(atr), divisionFactor; long cardClock = fs[cardFi], myClock; cardClock = (cardClock >= 16000000 ? 16000000 : cardClock >= 8000000 ? 8000000 : 4000000); myClock = cardClock; divisionFactor = (myClock == 4000000 ? 1 : myClock == 8000000 ? 2 : 4); #ifdef ASE_DEBUG syslog(LOG_INFO, "DoPPS: initial clock = %d\n", (int)myClock); #endif /* check to see if the card parameters are supported by the reader: if readerFToD is smaller than cardFToD */ readerFToD = (float)(globalData->dataMemory[14]) * 256.0 + (float)(globalData->dataMemory[13]); while (myClock >= 4000000) { cardDi = GetDi(atr); while (cardDi >= 1) { /* use only permitted values */ if (cardDi != 7 && cardDi <= 9) { /* calculate the card's f/d factor */ cardFToD = GetFToDFactor(cardFi, cardDi); if (divisionFactor != 1) cardFToD /= (float)divisionFactor; #ifdef ASE_DEBUG syslog(LOG_INFO, "DoPPS: card Fi = %d, Di = %d, F = %d, D = %d cardFToD = %f\n", cardFi, cardDi, fi[cardFi], di[cardDi], cardFToD); #endif if ((readerFToD - EPSILON) <= cardFToD) { #ifdef ASE_DEBUG syslog(LOG_INFO, "DoPPS: F = %d, D = %d\n", cardFi, cardDi); #endif PPS1 = (cardFi << 4) | cardDi; retVal = PPS(globalData, socket, protocol, &PPS1, NULL, NULL); if (retVal == ASE_OK) { /* PPS succeeded - compute the reader's params */ retVal = MatchReaderParams(globalData, socket, params, atr, cardFi, cardDi, GetWI(atr), GetN(atr), protocol); /* force the reader's clock to current clock */ params->freq = (myClock == 16000000 ? 0 : myClock == 8000000 ? 1 : 2); return retVal; } else { /* PPS failed */ #ifdef ASE_DEBUG syslog(LOG_INFO, "DoPPS: PPS failed - retVal = %d.\n", retVal); #endif myClock /= 2; divisionFactor /= 2; /* to exit the do-while loop over cardDi */ cardDi = 0; } } /* if */ } /* if */ cardDi--; } /* while (cardDi >= 1) */ } /* while myClock */ #ifdef ASE_DEBUG syslog(LOG_INFO, "\n********DoPPS: No parameters found in PPS - default parameters will be used.\n\n"); #endif /* proceed with default baudrate - it must succeed */ MatchReaderParams(globalData, socket, params, atr, 1 /*Fi*/, 1 /*Di*/, GetWI(atr), GetN(atr), protocol); usleep(10000); /* wait at least 10ms between two cold resets */ /* must do a Cold Reset before proceeding with default values */ return CardPowerOn(globalData, socket, 0, voltage); } /***************************************************************************** * *****************************************************************************/ int InitCard (reader* globalData, char socket, char coldReset, char* protocol) { int retVal, actual, working = 0, retryTimes = 3, voltage = 3; uchar s[300], r[300]; struct card_params params; double freq, wwt; ATR* atr = &(globalData->cards[(int)socket].atr); // bit 0 -> 5V, bit 1 -> 3V, bit 2 -> 1.8V support uchar readerVoltage = globalData->dataMemory[9]; GetDefaultReaderParams(globalData, ¶ms); ////////////////// retVal = SetCardParameters(globalData, socket, params); /* Check to see if we have a card in the socket */ if (globalData->cards[(int)socket].status) { globalData->cards[(int)socket].cwt = 3000000; /* 3sec */ globalData->cards[(int)socket].activeProtocol = ATR_PROTOCOL_TYPE_T0; /* Call CardPowerOn to do a cold reset. Store and parse the ATR returned. (first call it with 3V and if no answer is returned, try with 5V) */ if (coldReset) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n Trying CardPowerOn with %dV\n\n", voltage); #endif retVal = CardPowerOn(globalData, socket, 0, voltage); /* if the card supports 1.8V and the reader too - > switch to 1.8V */ if (retVal == ASE_OK && (GetClassIndicator(atr) & 0x04) && (readerVoltage & 0x04)) { voltage = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with %dV classIndicator = %d\n\n", voltage,(GetClassIndicator(atr) & 0x01)); #endif usleep(10000); /* wait at least 10ms between two cold resets */ retVal = CardPowerOn(globalData, socket, 0, voltage); if (retVal < 0) { voltage = 3; /* return to 3V since this already works */ usleep(10000); #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with %dV classIndicator = %d\n\n", voltage,(GetClassIndicator(atr) & 0x01)); #endif retVal = CardPowerOn(globalData, socket, 0, voltage); } } else { /* if the card supports 3V and the reader too -> we're done */ if (retVal == ASE_OK && (GetClassIndicator(atr) & 0x02) && (readerVoltage & 0x02)) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n 3V it is\n\n"); #endif } /* if the card supports only 5V and the reader doesnt -> we cannot power on this card */ if (retVal == ASE_OK && !(GetClassIndicator(atr) & 0x02) && (GetClassIndicator(atr) & 0x01) && !(readerVoltage & 0x01)) return ASE_READER_CARD_REJECTED; } /* We should switch to 5V if either we didnt get a valid atr or the class indicator in the atr supports 5V (class A) and the reader too */ /* NOTE: we check here that the card doesnt support 3V so that we dont enter the cond if we're done */ if (retVal < 0 || (!(GetClassIndicator(atr) & 0x02) && (GetClassIndicator(atr) & 0x01) && (readerVoltage & 0x01))) { voltage = 5; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with %dV classIndicator = %d\n\n", voltage,(GetClassIndicator(atr) & 0x01)); #endif usleep(10000); /* wait at least 10ms between two cold resets */ retVal = CardPowerOn(globalData, socket, 0, voltage); /* if the card supports 1.8V and the reader too - > switch to 1.8V */ if (retVal == ASE_OK && (GetClassIndicator(atr) & 0x04) && (readerVoltage & 0x04)) { voltage = 2; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with %dV classIndicator = %d\n\n", voltage,(GetClassIndicator(atr) & 0x01)); #endif usleep(10000); /* wait at least 10ms between two cold resets */ retVal = CardPowerOn(globalData, socket, 0, voltage); if (retVal < 0) { voltage = 5; /* return to 5V since this already works */ usleep(10000); #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with %dV classIndicator = %d\n\n", voltage,(GetClassIndicator(atr) & 0x01)); #endif retVal = CardPowerOn(globalData, socket, 0, voltage); } } if (retVal < 0) { voltage = 5; #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with 2BUS memory card\n\n"); #endif retVal = CardPowerOn(globalData, socket, 0x12, voltage); if (retVal < 0 || (atr->data[0] != 0xA2 && atr->data[0] != 0x92)) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with I2C memory card\n\n"); #endif retVal = CardPowerOn(globalData, socket, 0x21, voltage); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } /* To check if this card is supported by the reader, we send a read command. If the command doesnt succeed, we reject the card. */ { unsigned char curStatus = globalData->cards[(int)socket].status; globalData->cards[(int)socket].memCard.memType = MEM_CARD_MAIN_MEM_MODE; globalData->cards[(int)socket].status = 2; /* temporarilly */ globalData->cards[(int)socket].memCard.protocolType = PROTOCOL_MEM_I2C; s[0] = 0x0; s[1] = 0xB0; s[2] = 0x0; s[3] = 0x0; s[4] = 0x4; retVal = MemoryCardCommand(globalData, socket, s, 5, r, &actual); if (retVal < 0 || (actual >= 2 && r[actual - 2] != 0x90)) { // try with XI2C #ifdef ASE_DEBUG syslog(LOG_INFO, "\n ReTrying CardPowerOn with XI2C memory card\n\n"); #endif params.protocol = 0x22; retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { globalData->cards[(int)socket].status = curStatus; return ASE_READER_CARD_REJECTED; } { globalData->cards[(int)socket].memCard.protocolType = PROTOCOL_MEM_XI2C; s[0] = 0x0; s[1] = 0xB0; s[2] = 0x0; s[3] = 0x0; s[4] = 0x4; retVal = MemoryCardCommand(globalData, socket, s, 5, r, &actual); globalData->cards[(int)socket].status = curStatus; if (retVal < 0 || (actual >= 2 && r[actual - 2] != 0x90)) { return ASE_READER_CARD_REJECTED; } } globalData->cards[(int)socket].status = curStatus; return ASE_READER_CARD_REJECTED; } globalData->cards[(int)socket].status = curStatus; } } globalData->cards[(int)socket].activeProtocol = ATR_PROTOCOL_TYPE_RAW; } } } /* Warm reset */ else { retVal = CPUCardReset(globalData, socket); if (retVal < 0) { return ASE_READER_NOT_CPU_CARD; } } /* Check if it's a memory card */ if (globalData->cards[(int)socket].activeProtocol == ATR_PROTOCOL_TYPE_RAW) { if ( atr->data[0] == 0xA2 /*&& atr->data[1] == 0x13 && atr->data[2] == 0x10 && atr->data[3] == 0x91*/) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\nInitCard - this is a 2BUS card\n\n"); #endif params.protocol = 0x11; /* 2BUS */ globalData->cards[(int)socket].memCard.protocolType = PROTOCOL_MEM_2BUS; } else if ( atr->data[0] == 0x92) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\nInitCard - this is a 3BUS card\n\n"); #endif params.protocol = 0x12; /* 3BUS */ globalData->cards[(int)socket].memCard.protocolType = PROTOCOL_MEM_3BUS; } else { /* X/I2C */ #ifdef ASE_DEBUG syslog(LOG_INFO, "\nInitCard - this is an I2C card\n\n"); #endif params.protocol = 0x21; globalData->cards[(int)socket].memCard.protocolType = PROTOCOL_MEM_I2C; } retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } /* set ATR to dummy value */ memset(atr, 0x00, sizeof(ATR)); /* atr->data[0] = 0x3B; atr->data[1] = 0x00; atr->length = 2; */ /* set bwt and cwt */ globalData->cards[(int)socket].cwt = globalData->cards[(int)socket].bwt = 1510000; /* ~1.5sec */ globalData->cards[(int)socket].memCard.memType = MEM_CARD_MAIN_MEM_MODE; globalData->cards[(int)socket].status = 2; /* card is powered on and ready for work */ return ASE_OK; } /* Do the following until a working state has been found, or after retrying enough times: */ while (!working && retryTimes) { /* In SPECIFIC_MODE, try to match the reader params to that of the card */ if (GetCurrentMode(atr) == SPECIFIC_MODE) { #ifdef ASE_DEBUG syslog(LOG_INFO, "\n***** SPECIFIC_MODE: Fi = %d, Di = %d, WI = %d, N = %d, protocol = %d\n\n", GetFi(atr), GetDi(atr), GetWI(atr), GetN(atr), GetSpecificModeProtocol(atr)); #endif globalData->cards[(int)socket].activeProtocol = GetSpecificModeProtocol(atr); retVal = MatchReaderParams(globalData, socket, ¶ms, atr, GetFi(atr), GetDi(atr), GetWI(atr), GetN(atr), globalData->cards[(int)socket].activeProtocol); if (retVal < 0) { /* reader params could not be matched */ /* check if a warm reset can change modes */ if (CapableOfChangingMode(atr)) { retVal = CPUCardReset(globalData, socket); /* try a warm reset */ if (retVal < 0) { return ASE_READER_CARD_REJECTED; } } else { return ASE_READER_CARD_REJECTED; } } else { /* a match found */ retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } working = 1; } } /* In NEGOTIABLE_MODE, if we cannot match the reader params to that of the card, we can do a PPS */ else { /* NEGOTIABLE_MODE */ #ifdef ASE_DEBUG syslog(LOG_INFO, "\n***** NEGOTIABLE_MODE: Fi = %d, Di = %d, WI = %d, N = %d, protocol = %d\n\n", GetFi(atr), GetDi(atr), GetWI(atr), GetN(atr), (protocol ? *protocol : GetFirstOfferedProtocol(atr))); #endif /* if the values are the default, no PPS should be done */ if ( (GetFi(atr) == 0 || GetFi(atr) == 1) && GetDi(atr) == 1) { #ifdef ASE_DEBUG syslog(LOG_INFO, "DEFAULT PARAMETERS will be used\n"); #endif globalData->cards[(int)socket].activeProtocol = (protocol ? *protocol : GetFirstOfferedProtocol(atr)); retVal = MatchReaderParams(globalData, socket, ¶ms, atr, GetFi(atr), GetDi(atr), GetWI(atr), GetN(atr), globalData->cards[(int)socket].activeProtocol); if (retVal < 0) return ASE_READER_CARD_REJECTED; else { retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } working = 1; } } else { globalData->cards[(int)socket].activeProtocol = (protocol ? *protocol : GetFirstOfferedProtocol(atr)); usleep(10000); /* wait at least 10ms before sending PPS */ retVal = DoPPS(globalData, socket, ¶ms, globalData->cards[(int)socket].activeProtocol, voltage); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } else { /* success */ retVal = SetCardParameters(globalData, socket, params); if (retVal < 0) { return ASE_READER_CARD_REJECTED; } working= 1; } } } retryTimes--; } if (working) { globalData->cards[(int)socket].status = 2; /* card is powered on and ready for work */ /* compute the character waiting time max delay */ wwt = params.CWT[0] * 65536 + params.CWT[1] * 256 + params.CWT[2]; freq = globalData->dataMemory[12] * 256 + globalData->dataMemory[11]; freq *= 1000; freq /= (params.freq == 0 ? 1.0 : params.freq == 1 ? 2.0 : params.freq == 2 ? 4.0 : 8.0); globalData->cards[(int)socket].cwt = (long)( (params.fTod * wwt) / freq * 1000000.0 ); /* in microsec */ /* compute the max delay for the first response character */ wwt = params.BWT[0] * 65536 + params.BWT[1] * 256 + params.BWT[2]; freq = globalData->dataMemory[12] * 256 + globalData->dataMemory[11]; freq *= 1000; freq /= (params.freq == 0 ? 1.0 : params.freq == 1 ? 2.0 : params.freq == 2 ? 4.0 : 8.0); globalData->cards[(int)socket].bwt = (long)( (params.fTod * wwt) / freq * 1000000.0 ); /* in microsec */ #ifdef ASE_DEBUG syslog(LOG_INFO, "InitCard: protocol = %d cwt = %d bwt = %d (each 1000 == 1ms)\n", globalData->cards[(int)socket].activeProtocol, (int)globalData->cards[(int)socket].cwt, (int)globalData->cards[(int)socket].bwt); #endif /* if it's T=1, the protocol must be inited */ if (globalData->cards[(int)socket].activeProtocol == ATR_PROTOCOL_TYPE_T1) T1InitProtocol(globalData, socket, 1); return ASE_OK; } else { return ASE_READER_CARD_REJECTED; } } return ASE_READER_NO_CARD_ERROR; }