LONG IFDControl(READER_CONTEXT * rContext, DWORD ControlCode, LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength, LPDWORD BytesReturned) { RESPONSECODE rv = IFD_SUCCESS; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFDH_control) (DWORD, DWORD, LPCVOID, DWORD, LPVOID, DWORD, LPDWORD); #endif if (rContext->version < IFD_HVERSION_3_0) return SCARD_E_UNSUPPORTED_FEATURE; #ifndef PCSCLITE_STATIC_DRIVER IFDH_control = rContext->psFunctions.psFunctions_v3.pvfControl; #endif /* LOCK THIS CODE REGION */ (void)pthread_mutex_lock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER rv = (*IFDH_control) (rContext->slot, ControlCode, TxBuffer, TxLength, RxBuffer, RxLength, BytesReturned); #elif defined(IFDHANDLERv3) rv = IFDHControl(rContext->slot, ControlCode, TxBuffer, TxLength, RxBuffer, RxLength, BytesReturned); #endif /* END OF LOCKED REGION */ (void)pthread_mutex_unlock(rContext->mMutex); if (rv == IFD_SUCCESS) return SCARD_S_SUCCESS; else { Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); Log3(PCSC_LOG_DEBUG, "ControlCode: 0x%.8lX BytesReturned: %ld", ControlCode, *BytesReturned); LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength); LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *BytesReturned); if (rv == IFD_NO_SUCH_DEVICE) { (void)SendHotplugSignal(); return SCARD_E_READER_UNAVAILABLE; } if ((IFD_ERROR_NOT_SUPPORTED == rv) || (IFD_NOT_SUPPORTED == rv)) return SCARD_E_UNSUPPORTED_FEATURE; if (IFD_ERROR_INSUFFICIENT_BUFFER ==rv) return SCARD_E_INSUFFICIENT_BUFFER; return SCARD_E_NOT_TRANSACTED; } }
int ProcessHotplugRequest() { #ifdef USE_RUN_PID /* read the pid file to get the old pid and test if the old pcscd is * still running */ if (GetDaemonPid() != -1) return SendHotplugSignal(); Log1(PCSC_LOG_CRITICAL, "file " USE_RUN_PID " does not exist"); Log1(PCSC_LOG_CRITICAL, "Perhaps pcscd is not running?"); #else struct stat tmpStat; if (SYS_Stat(PCSCLITE_CSOCK_NAME, &tmpStat) == 0) // socket file exists, so maybe pcscd is running return SendHotplugSignal(); Log1(PCSC_LOG_CRITICAL, "pcscd was not configured with --enable-runpid=FILE"); #endif Log1(PCSC_LOG_CRITICAL, "Hotplug failed"); return EXIT_FAILURE; }
/** * Transmit an APDU to the ICC. */ LONG IFDTransmit(READER_CONTEXT * rContext, SCARD_IO_HEADER pioTxPci, PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer, PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci) { RESPONSECODE rv; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFDH_transmit_to_icc) (DWORD, SCARD_IO_HEADER, PUCHAR, DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL; #endif /* log the APDU */ DebugLogCategory(DEBUG_CATEGORY_APDU, pucTxBuffer, dwTxLength); #ifndef PCSCLITE_STATIC_DRIVER IFDH_transmit_to_icc = rContext->psFunctions.psFunctions_v2.pvfTransmitToICC; #endif /* LOCK THIS CODE REGION */ (void)pthread_mutex_lock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER rv = (*IFDH_transmit_to_icc) (rContext->slot, pioTxPci, (LPBYTE) pucTxBuffer, dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci); #else rv = IFDHTransmitToICC(rContext->slot, pioTxPci, (LPBYTE) pucTxBuffer, dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci); #endif /* END OF LOCKED REGION */ (void)pthread_mutex_unlock(rContext->mMutex); /* log the returned status word */ DebugLogCategory(DEBUG_CATEGORY_SW, pucRxBuffer, *pdwRxLength); if (rv == IFD_SUCCESS) return SCARD_S_SUCCESS; else { Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); if (rv == IFD_NO_SUCH_DEVICE) { (void)SendHotplugSignal(); return SCARD_E_READER_UNAVAILABLE; } return SCARD_E_NOT_TRANSACTED; } }
/** * Provide statistical information about the IFD and ICC including insertions, * atr, powering status/etc. */ LONG IFDStatusICC(READER_CONTEXT * rContext, PDWORD pdwStatus) { RESPONSECODE rv; DWORD dwCardStatus = 0; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFDH_icc_presence) (DWORD) = NULL; IFDH_icc_presence = rContext->psFunctions.psFunctions_v2.pvfICCPresence; #endif /* LOCK THIS CODE REGION */ (void)pthread_mutex_lock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER rv = (*IFDH_icc_presence) (rContext->slot); #else rv = IFDHICCPresence(rContext->slot); #endif /* END OF LOCKED REGION */ (void)pthread_mutex_unlock(rContext->mMutex); if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT) dwCardStatus |= SCARD_PRESENT; else if (rv == IFD_ICC_NOT_PRESENT) dwCardStatus |= SCARD_ABSENT; else { Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); *pdwStatus = SCARD_UNKNOWN; if (rv == IFD_NO_SUCH_DEVICE) { (void)SendHotplugSignal(); return SCARD_E_READER_UNAVAILABLE; } return SCARD_E_NOT_TRANSACTED; } *pdwStatus = dwCardStatus; return SCARD_S_SUCCESS; }
int main(int argc, char **argv) { int rv; char setToForeground; char HotPlug; char *newReaderConfig; struct stat fStatBuf; int customMaxThreadCounter = 0; int customMaxReaderHandles = 0; int customMaxThreadCardHandles = 0; int opt; int limited_rights = FALSE; int r; #ifdef HAVE_GETOPT_LONG int option_index = 0; static struct option long_options[] = { {"config", 1, NULL, 'c'}, {"foreground", 0, NULL, 'f'}, {"color", 0, NULL, 'T'}, {"help", 0, NULL, 'h'}, {"version", 0, NULL, 'v'}, {"apdu", 0, NULL, 'a'}, {"debug", 0, NULL, 'd'}, {"info", 0, NULL, 0}, {"error", 0, NULL, 'e'}, {"critical", 0, NULL, 'C'}, {"hotplug", 0, NULL, 'H'}, {"force-reader-polling", optional_argument, NULL, 0}, {"max-thread", 1, NULL, 't'}, {"max-card-handle-per-thread", 1, NULL, 's'}, {"max-card-handle-per-reader", 1, NULL, 'r'}, {"auto-exit", 0, NULL, 'x'}, {"reader-name-no-serial", 0, NULL, 'S'}, {"reader-name-no-interface", 0, NULL, 'I'}, {NULL, 0, NULL, 0} }; #endif #define OPT_STRING "c:fTdhvaeCHt:r:s:xSI" newReaderConfig = NULL; setToForeground = FALSE; HotPlug = FALSE; /* * test the version */ if (strcmp(PCSCLITE_VERSION_NUMBER, VERSION) != 0) { printf("BUILD ERROR: The release version number PCSCLITE_VERSION_NUMBER\n"); printf(" in pcsclite.h (%s) does not match the release version number\n", PCSCLITE_VERSION_NUMBER); printf(" generated in config.h (%s) (see configure.in).\n", VERSION); return EXIT_FAILURE; } /* * By default we create a daemon (not connected to any output) * so log to syslog to have error messages. */ DebugLogSetLogType(DEBUGLOG_SYSLOG_DEBUG); /* if the process is setuid or setgid it may have some restrictions */ limited_rights = (getgid() != getegid()) && (getuid() != 0); /* * Handle any command line arguments */ #ifdef HAVE_GETOPT_LONG while ((opt = getopt_long (argc, argv, OPT_STRING, long_options, &option_index)) != -1) { #else while ((opt = getopt (argc, argv, OPT_STRING)) != -1) { #endif switch (opt) { #ifdef HAVE_GETOPT_LONG case 0: if (strcmp(long_options[option_index].name, "force-reader-polling") == 0) HPForceReaderPolling = optarg ? abs(atoi(optarg)) : 1; break; #endif case 'c': if (limited_rights) { Log1(PCSC_LOG_CRITICAL, "Can't use a user specified config file"); return EXIT_FAILURE; } Log2(PCSC_LOG_INFO, "using new config file: %s", optarg); newReaderConfig = optarg; break; case 'f': setToForeground = TRUE; /* debug to stdout instead of default syslog */ DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG); Log1(PCSC_LOG_INFO, "pcscd set to foreground with debug send to stdout"); break; case 'T': DebugLogSetLogType(DEBUGLOG_STDOUT_COLOR_DEBUG); Log1(PCSC_LOG_INFO, "Force colored logs"); break; case 'd': DebugLogSetLevel(PCSC_LOG_DEBUG); break; case 'e': DebugLogSetLevel(PCSC_LOG_ERROR); break; case 'C': DebugLogSetLevel(PCSC_LOG_CRITICAL); break; case 'h': print_usage (argv[0]); return EXIT_SUCCESS; case 'v': print_version (); return EXIT_SUCCESS; case 'a': if (limited_rights) { Log1(PCSC_LOG_CRITICAL, "Can't log APDU (restricted)"); return EXIT_FAILURE; } (void)DebugLogSetCategory(DEBUG_CATEGORY_APDU); break; case 'H': /* debug to stdout instead of default syslog */ DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG); HotPlug = TRUE; break; case 't': customMaxThreadCounter = optarg ? atoi(optarg) : 0; if (limited_rights && (customMaxThreadCounter < PCSC_MAX_CONTEXT_THREADS)) customMaxThreadCounter = PCSC_MAX_CONTEXT_THREADS; Log2(PCSC_LOG_INFO, "setting customMaxThreadCounter to: %d", customMaxThreadCounter); break; case 'r': customMaxReaderHandles = optarg ? atoi(optarg) : 0; if (limited_rights && (customMaxReaderHandles < PCSC_MAX_READER_HANDLES)) customMaxReaderHandles = PCSC_MAX_READER_HANDLES; Log2(PCSC_LOG_INFO, "setting customMaxReaderHandles to: %d", customMaxReaderHandles); break; case 's': customMaxThreadCardHandles = optarg ? atoi(optarg) : 0; if (limited_rights && (customMaxThreadCardHandles < PCSC_MAX_CONTEXT_CARD_HANDLES)) customMaxThreadCardHandles = PCSC_MAX_CONTEXT_CARD_HANDLES; Log2(PCSC_LOG_INFO, "setting customMaxThreadCardHandles to: %d", customMaxThreadCardHandles); break; case 'x': AutoExit = TRUE; Log2(PCSC_LOG_INFO, "Auto exit after %d seconds of inactivity", TIME_BEFORE_SUICIDE); break; case 'S': Add_Serial_In_Name = FALSE; break; case 'I': Add_Interface_In_Name = FALSE; break; default: print_usage (argv[0]); return EXIT_FAILURE; } } if (argv[optind]) { printf("Unknown option: %s\n", argv[optind]); print_usage(argv[0]); return EXIT_FAILURE; } /* * Check if systemd passed us any file descriptors */ rv = sd_listen_fds(0); if (rv > 1) { Log1(PCSC_LOG_CRITICAL, "Too many file descriptors received"); return EXIT_FAILURE; } else { if (rv == 1) { SocketActivated = TRUE; Log1(PCSC_LOG_INFO, "Started by systemd"); } else SocketActivated = FALSE; } /* * test the presence of /var/run/pcscd/pcscd.comm */ rv = stat(PCSCLITE_CSOCK_NAME, &fStatBuf); if (rv == 0) { pid_t pid; /* read the pid file to get the old pid and test if the old pcscd is * still running */ pid = GetDaemonPid(); if (pid != -1) { if (HotPlug) return SendHotplugSignal(); rv = kill(pid, 0); if (0 == rv) { Log1(PCSC_LOG_CRITICAL, "file " PCSCLITE_CSOCK_NAME " already exists."); Log2(PCSC_LOG_CRITICAL, "Another pcscd (pid: %d) seems to be running.", pid); return EXIT_FAILURE; } else if (ESRCH == errno) { /* the old pcscd is dead. make some cleanup */ clean_temp_files(); } else { /* permission denied or other error */ Log2(PCSC_LOG_CRITICAL, "kill failed: %s", strerror(errno)); return EXIT_FAILURE; } } else { if (HotPlug) { Log1(PCSC_LOG_CRITICAL, "file " PCSCLITE_RUN_PID " do not exist"); Log1(PCSC_LOG_CRITICAL, "Hotplug failed"); return EXIT_FAILURE; } } } else if (HotPlug) { Log1(PCSC_LOG_CRITICAL, "Hotplug failed: pcscd is not running"); return EXIT_FAILURE; } /* like in daemon(3): changes the current working directory to the * root ("/") */ r = chdir("/"); if (r < 0) { Log2(PCSC_LOG_CRITICAL, "chdir() failed: %s", strerror(errno)); return EXIT_FAILURE; } /* * If this is set to one the user has asked it not to fork */ if (!setToForeground) { int pid; int fd; if (pipe(pipefd) == -1) { Log2(PCSC_LOG_CRITICAL, "pipe() failed: %s", strerror(errno)); return EXIT_FAILURE; } pid = fork(); if (-1 == pid) { Log2(PCSC_LOG_CRITICAL, "fork() failed: %s", strerror(errno)); return EXIT_FAILURE; } /* like in daemon(3): redirect standard input, standard output * and standard error to /dev/null */ fd = open("/dev/null", O_RDWR); if (fd != -1) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); /* do not close stdin, stdout or stderr */ if (fd > 2) close(fd); } if (pid) /* in the father */ { char buf; int ret; /* close write side */ close(pipefd[1]); /* wait for the son to write the return code */ ret = read(pipefd[0], &buf, 1); if (ret <= 0) return 2; close(pipefd[0]); /* exit code */ return buf; } else /* in the son */ { /* close read side */ close(pipefd[0]); } } /* * cleanly remove /var/run/pcscd/files when exiting * signal_trap() does just set a global variable used by the main loop */ (void)signal(SIGQUIT, signal_trap); (void)signal(SIGTERM, signal_trap); /* default kill signal & init round 1 */ (void)signal(SIGINT, signal_trap); /* sent by Ctrl-C */ /* exits on SIGALARM to allow pcscd to suicide if not used */ (void)signal(SIGALRM, signal_trap); /* * If PCSCLITE_IPC_DIR does not exist then create it */ { int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU; rv = mkdir(PCSCLITE_IPC_DIR, mode); if ((rv != 0) && (errno != EEXIST)) { Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_IPC_DIR ": %s", strerror(errno)); return EXIT_FAILURE; } /* set mode so that the directory is world readable and * executable even is umask is restrictive * The directory containes files used by libpcsclite */ (void)chmod(PCSCLITE_IPC_DIR, mode); } /* * Allocate memory for reader structures */ rv = RFAllocateReaderSpace(customMaxReaderHandles); if (SCARD_S_SUCCESS != rv) at_exit(); #ifdef USE_SERIAL /* * Grab the information from the reader.conf */ if (newReaderConfig) { rv = RFStartSerialReaders(newReaderConfig); if (rv != 0) { Log3(PCSC_LOG_CRITICAL, "invalid file %s: %s", newReaderConfig, strerror(errno)); at_exit(); } } else { rv = RFStartSerialReaders(PCSCLITE_CONFIG_DIR); if (rv == -1) at_exit(); } #endif Log1(PCSC_LOG_INFO, "pcsc-lite " VERSION " daemon ready."); /* * Record our pid to make it easier * to kill the correct pcscd * * Do not fork after this point or the stored pid will be wrong */ { int f; int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; f = open(PCSCLITE_RUN_PID, O_RDWR | O_CREAT, mode); if (f != -1) { char pid[PID_ASCII_SIZE]; ssize_t rr; (void)snprintf(pid, sizeof(pid), "%u\n", (unsigned) getpid()); rr = write(f, pid, strlen(pid) + 1); if (rr < 0) { Log2(PCSC_LOG_CRITICAL, "writing " PCSCLITE_RUN_PID " failed: %s", strerror(errno)); } (void)close(f); /* set mode so that the file is world readable even is umask is * restrictive * The file is used by libpcsclite */ (void)chmod(PCSCLITE_RUN_PID, mode); } else Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_RUN_PID ": %s", strerror(errno)); } /* * post initialistion */ Init = FALSE; /* * Hotplug rescan */ (void)signal(SIGUSR1, signal_reload); /* * Initialize the comm structure */ if (SocketActivated) rv = ListenExistingSocket(SD_LISTEN_FDS_START + 0); else rv = InitializeSocket(); if (rv) { Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd."); at_exit(); } /* * Initialize the contexts structure */ rv = ContextsInitialize(customMaxThreadCounter, customMaxThreadCardHandles); if (rv == -1) { Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd."); at_exit(); } (void)signal(SIGPIPE, SIG_IGN); (void)signal(SIGHUP, SIG_IGN); /* needed for Solaris. The signal is sent * when the shell is existed */ #if !defined(PCSCLITE_STATIC_DRIVER) && defined(USE_USB) /* * Set up the search for USB/PCMCIA devices */ rv = HPSearchHotPluggables(); #ifndef USE_SERIAL if (rv) at_exit(); #endif rv = HPRegisterForHotplugEvents(); if (rv) { Log1(PCSC_LOG_ERROR, "HPRegisterForHotplugEvents failed"); at_exit(); } RFWaitForReaderInit(); #endif /* * Set up the power management callback routine */ (void)PMRegisterForPowerEvents(); /* initialisation succeeded */ if (pipefd[1] >= 0) { char buf = 0; ssize_t rr; /* write a 0 (success) to father process */ rr = write(pipefd[1], &buf, 1); if (rr < 0) { Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno)); } close(pipefd[1]); } SVCServiceRunLoop(); Log1(PCSC_LOG_ERROR, "SVCServiceRunLoop returned"); return EXIT_FAILURE; } static void at_exit(void) { Log1(PCSC_LOG_INFO, "cleaning " PCSCLITE_IPC_DIR); clean_temp_files(); if (pipefd[1] >= 0) { char buf; ssize_t r; /* write the error code to father process */ buf = ExitValue; r = write(pipefd[1], &buf, 1); if (r < 0) { Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno)); } close(pipefd[1]); } exit(ExitValue); }
/** * Transmit an APDU to the ICC. */ LONG IFDTransmit(PREADER_CONTEXT rContext, SCARD_IO_HEADER pioTxPci, PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer, PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci) { RESPONSECODE rv = IFD_SUCCESS; UCHAR ucValue[1] = "\x00"; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFD_transmit_to_icc) (SCARD_IO_HEADER, PUCHAR, DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL; RESPONSECODE(*IFDH_transmit_to_icc) (DWORD, SCARD_IO_HEADER, PUCHAR, DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL; #endif /* log the APDU */ DebugLogCategory(DEBUG_CATEGORY_APDU, pucTxBuffer, dwTxLength); #ifndef PCSCLITE_STATIC_DRIVER if (rContext->dwVersion == IFD_HVERSION_1_0) IFD_transmit_to_icc = rContext->psFunctions.psFunctions_v1.pvfTransmitToICC; else IFDH_transmit_to_icc = rContext->psFunctions.psFunctions_v2.pvfTransmitToICC; #endif /* LOCK THIS CODE REGION */ (void)SYS_MutexLock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER if (rContext->dwVersion == IFD_HVERSION_1_0) { ucValue[0] = rContext->dwSlot; (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); rv = (*IFD_transmit_to_icc) (pioTxPci, (LPBYTE) pucTxBuffer, dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci); } else rv = (*IFDH_transmit_to_icc) (rContext->dwSlot, pioTxPci, (LPBYTE) pucTxBuffer, dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci); #else if (rContext->dwVersion == IFD_HVERSION_1_0) { ucValue[0] = rContext->dwSlot; (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); rv = IFD_Transmit_to_ICC(pioTxPci, (LPBYTE) pucTxBuffer, dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci); } else rv = IFDHTransmitToICC(rContext->dwSlot, pioTxPci, (LPBYTE) pucTxBuffer, dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci); #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(rContext->mMutex); /* log the returned status word */ DebugLogCategory(DEBUG_CATEGORY_SW, pucRxBuffer, *pdwRxLength); if (rv == IFD_SUCCESS) return SCARD_S_SUCCESS; else { Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); if (rv == IFD_NO_SUCH_DEVICE) { (void)SendHotplugSignal(); return SCARD_E_READER_UNAVAILABLE; } return SCARD_E_NOT_TRANSACTED; } }
/** * Provide statistical information about the IFD and ICC including insertions, * atr, powering status/etc. */ LONG IFDStatusICC(PREADER_CONTEXT rContext, PDWORD pdwStatus, PUCHAR pucAtr, PDWORD pdwAtrLen) { RESPONSECODE rv = IFD_SUCCESS; DWORD dwTag = 0, dwCardStatus = 0; SMARTCARD_EXTENSION sSmartCard; UCHAR ucValue[1] = "\x00"; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFD_is_icc_present) (void) = NULL; RESPONSECODE(*IFDH_icc_presence) (DWORD) = NULL; RESPONSECODE(*IFD_get_capabilities) (DWORD, /*@out@*/ PUCHAR) = NULL; if (rContext->dwVersion == IFD_HVERSION_1_0) { IFD_is_icc_present = rContext->psFunctions.psFunctions_v1.pvfICCPresence; IFD_get_capabilities = rContext->psFunctions.psFunctions_v1.pvfGetCapabilities; } else IFDH_icc_presence = rContext->psFunctions.psFunctions_v2.pvfICCPresence; #endif /* LOCK THIS CODE REGION */ (void)SYS_MutexLock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER if (rContext->dwVersion == IFD_HVERSION_1_0) { ucValue[0] = rContext->dwSlot; (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); rv = (*IFD_is_icc_present) (); } else rv = (*IFDH_icc_presence) (rContext->dwSlot); #else if (rContext->dwVersion == IFD_HVERSION_1_0) { ucValue[0] = rContext->dwSlot; (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); rv = IFD_Is_ICC_Present(); } else rv = IFDHICCPresence(rContext->dwSlot); #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(rContext->mMutex); if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT) dwCardStatus |= SCARD_PRESENT; else if (rv == IFD_ICC_NOT_PRESENT) dwCardStatus |= SCARD_ABSENT; else { Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); *pdwStatus = SCARD_UNKNOWN; if (rv == IFD_NO_SUCH_DEVICE) { (void)SendHotplugSignal(); return SCARD_E_READER_UNAVAILABLE; } return SCARD_E_NOT_TRANSACTED; } /* * Now lets get the ATR and process it if IFD Handler version 1.0. * IFD Handler version 2.0 does this immediately after reset/power up * to conserve resources */ if (rContext->dwVersion == IFD_HVERSION_1_0) { if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT) { short ret; dwTag = TAG_IFD_ATR; /* LOCK THIS CODE REGION */ (void)SYS_MutexLock(rContext->mMutex); ucValue[0] = rContext->dwSlot; (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); #ifndef PCSCLITE_STATIC_DRIVER rv = (*IFD_get_capabilities) (dwTag, pucAtr); #else rv = IFD_Get_Capabilities(dwTag, pucAtr); #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(rContext->mMutex); /* * FIX :: This is a temporary way to return the correct size * of the ATR since most of the drivers return MAX_ATR_SIZE */ ret = ATRDecodeAtr(&sSmartCard, pucAtr, MAX_ATR_SIZE); /* * Might be a memory card without an ATR */ if (ret == 0) *pdwAtrLen = 0; else *pdwAtrLen = sSmartCard.ATR.Length; } else { /* * No card is inserted - Atr length is 0 */ *pdwAtrLen = 0; } /* * End of FIX */ } *pdwStatus = dwCardStatus; return SCARD_S_SUCCESS; }
/** * Power up/down or reset's an ICC located in the IFD. */ LONG IFDPowerICC(PREADER_CONTEXT rContext, DWORD dwAction, PUCHAR pucAtr, PDWORD pdwAtrLen) { RESPONSECODE rv; short ret; SMARTCARD_EXTENSION sSmartCard; DWORD dwStatus; UCHAR ucValue[1]; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFD_power_icc) (DWORD) = NULL; RESPONSECODE(*IFDH_power_icc) (DWORD, DWORD, PUCHAR, PDWORD) = NULL; #endif /* * Zero out everything */ rv = IFD_SUCCESS; dwStatus = 0; ucValue[0] = 0; /* * Check that the card is inserted first */ (void)IFDStatusICC(rContext, &dwStatus, pucAtr, pdwAtrLen); if (dwStatus & SCARD_ABSENT) return SCARD_W_REMOVED_CARD; #ifndef PCSCLITE_STATIC_DRIVER if (rContext->dwVersion == IFD_HVERSION_1_0) IFD_power_icc = rContext->psFunctions.psFunctions_v1.pvfPowerICC; else IFDH_power_icc = rContext->psFunctions.psFunctions_v2.pvfPowerICC; #endif /* LOCK THIS CODE REGION */ (void)SYS_MutexLock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER if (rContext->dwVersion == IFD_HVERSION_1_0) { ucValue[0] = rContext->dwSlot; (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); rv = (*IFD_power_icc) (dwAction); } else { rv = (*IFDH_power_icc) (rContext->dwSlot, dwAction, pucAtr, pdwAtrLen); ret = ATRDecodeAtr(&sSmartCard, pucAtr, *pdwAtrLen); } #else if (rContext->dwVersion == IFD_HVERSION_1_0) { ucValue[0] = rContext->dwSlot; (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); rv = IFD_Power_ICC(dwAction); } else rv = IFDHPowerICC(rContext->dwSlot, dwAction, pucAtr, pdwAtrLen); #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(rContext->mMutex); /* use clean values in case of error */ if (rv != IFD_SUCCESS) { *pdwAtrLen = 0; pucAtr[0] = '\0'; if (rv == IFD_NO_SUCH_DEVICE) { (void)SendHotplugSignal(); return SCARD_E_READER_UNAVAILABLE; } return SCARD_E_NOT_TRANSACTED; } /* * Get the ATR and it's length */ if (rContext->dwVersion == IFD_HVERSION_1_0) (void)IFDStatusICC(rContext, &dwStatus, pucAtr, pdwAtrLen); return rv; }
/** * Power up/down or reset's an ICC located in the IFD. */ LONG IFDPowerICC(READER_CONTEXT * rContext, DWORD dwAction, PUCHAR pucAtr, PDWORD pdwAtrLen) { RESPONSECODE rv; DWORD dwStatus; UCHAR dummyAtr[MAX_ATR_SIZE]; DWORD dummyAtrLen = sizeof(dummyAtr); #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFDH_power_icc) (DWORD, DWORD, PUCHAR, PDWORD) = NULL; #endif /* * Zero out everything */ dwStatus = 0; if (NULL == pucAtr) pucAtr = dummyAtr; if (NULL == pdwAtrLen) pdwAtrLen = &dummyAtrLen; /* * Check that the card is inserted first */ rv = IFDStatusICC(rContext, &dwStatus); if (rv != IFD_SUCCESS) { if (rv == IFD_NO_SUCH_DEVICE) return SCARD_E_READER_UNAVAILABLE; return SCARD_E_NOT_TRANSACTED; } if (dwStatus & SCARD_ABSENT) return SCARD_W_REMOVED_CARD; #ifndef PCSCLITE_STATIC_DRIVER IFDH_power_icc = rContext->psFunctions.psFunctions_v2.pvfPowerICC; #endif /* LOCK THIS CODE REGION */ (void)pthread_mutex_lock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER rv = (*IFDH_power_icc) (rContext->slot, dwAction, pucAtr, pdwAtrLen); #else rv = IFDHPowerICC(rContext->slot, dwAction, pucAtr, pdwAtrLen); #endif /* END OF LOCKED REGION */ (void)pthread_mutex_unlock(rContext->mMutex); /* use clean values in case of error */ if (rv != IFD_SUCCESS) { *pdwAtrLen = 0; pucAtr[0] = '\0'; if (rv == IFD_NO_SUCH_DEVICE) { (void)SendHotplugSignal(); return SCARD_E_READER_UNAVAILABLE; } return SCARD_E_NOT_TRANSACTED; } return rv; }