/** * Close a communication channel to the IFD. */ LONG IFDCloseIFD(PREADER_CONTEXT rContext) { RESPONSECODE rv = IFD_SUCCESS; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IO_close_channel) (void) = NULL; RESPONSECODE(*IFDH_close_channel) (DWORD) = NULL; if (rContext->dwVersion == IFD_HVERSION_1_0) IO_close_channel = rContext->psFunctions.psFunctions_v1.pvfCloseChannel; else IFDH_close_channel = rContext->psFunctions.psFunctions_v2.pvfCloseChannel; #endif /* LOCK THIS CODE REGION */ (void)SYS_MutexLock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER if (rContext->dwVersion == IFD_HVERSION_1_0) rv = (*IO_close_channel) (); else rv = (*IFDH_close_channel) (rContext->dwSlot); #else if (rContext->dwVersion == IFD_HVERSION_1_0) rv = IO_Close_Channel(); else rv = IFDHCloseChannel(rContext->dwSlot); #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(rContext->mMutex); return rv; }
LONG IFDControl(PREADER_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->dwVersion < 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)SYS_MutexLock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER rv = (*IFDH_control) (rContext->dwSlot, ControlCode, TxBuffer, TxLength, RxBuffer, RxLength, BytesReturned); #else rv = IFDHControl(rContext->dwSlot, ControlCode, TxBuffer, TxLength, RxBuffer, RxLength, BytesReturned); #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(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; return SCARD_E_NOT_TRANSACTED; } }
/** * Close a communication channel to the IFD. */ LONG IFDCloseIFD(PREADER_CONTEXT rContext) { RESPONSECODE rv = IFD_SUCCESS; int repeat; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IO_close_channel) (void) = NULL; RESPONSECODE(*IFDH_close_channel) (DWORD) = NULL; if (rContext->dwVersion == IFD_HVERSION_1_0) IO_close_channel = rContext->psFunctions.psFunctions_v1.pvfCloseChannel; else IFDH_close_channel = rContext->psFunctions.psFunctions_v2.pvfCloseChannel; #endif /* TRY TO LOCK THIS CODE REGION */ repeat = 5; again: rv = SYS_MutexTryLock(rContext->mMutex); if (EBUSY == rv) { Log1(PCSC_LOG_ERROR, "Locking failed"); repeat--; if (repeat) { (void)SYS_USleep(100*1000); /* 100 ms */ goto again; } } #ifndef PCSCLITE_STATIC_DRIVER if (rContext->dwVersion == IFD_HVERSION_1_0) rv = (*IO_close_channel) (); else rv = (*IFDH_close_channel) (rContext->dwSlot); #else if (rContext->dwVersion == IFD_HVERSION_1_0) rv = IO_Close_Channel(); else rv = IFDHCloseChannel(rContext->dwSlot); #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(rContext->mMutex); return rv; }
static LONG HPRemoveHotPluggable(int reader_index) { SYS_MutexLock(&usbNotifierMutex); Log3(PCSC_LOG_INFO, "Removing USB device[%d]: %s", reader_index, readerTracker[reader_index].bus_device); RFRemoveReader(readerTracker[reader_index].fullName, PCSCLITE_HP_BASE_PORT + reader_index); free(readerTracker[reader_index].fullName); readerTracker[reader_index].status = READER_ABSENT; readerTracker[reader_index].bus_device[0] = '\0'; readerTracker[reader_index].fullName = NULL; SYS_MutexUnLock(&usbNotifierMutex); return 1; } /* End of function */
LONG IFDControl_v2(PREADER_CONTEXT rContext, PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength) { RESPONSECODE rv = IFD_SUCCESS; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFDH_control_v2) (DWORD, PUCHAR, DWORD, /*@out@*/ PUCHAR, PDWORD); #endif if (rContext->dwVersion != IFD_HVERSION_2_0) return SCARD_E_UNSUPPORTED_FEATURE; #ifndef PCSCLITE_STATIC_DRIVER IFDH_control_v2 = rContext->psFunctions.psFunctions_v2.pvfControl; #endif /* LOCK THIS CODE REGION */ (void)SYS_MutexLock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER rv = (*IFDH_control_v2) (rContext->dwSlot, TxBuffer, TxLength, RxBuffer, RxLength); #else rv = IFDHControl_v2(rContext->dwSlot, TxBuffer, TxLength, RxBuffer, RxLength); #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(rContext->mMutex); if (rv == IFD_SUCCESS) return SCARD_S_SUCCESS; else { Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength); LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *RxLength); return SCARD_E_NOT_TRANSACTED; } }
/** * Get's capabilities in the reader. * Other functions int this file will call * the driver directly to not cause a deadlock. */ LONG IFDGetCapabilities(PREADER_CONTEXT rContext, DWORD dwTag, PDWORD pdwLength, PUCHAR pucValue) { RESPONSECODE rv = IFD_SUCCESS; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFD_get_capabilities) (DWORD, /*@out@*/ PUCHAR) = NULL; RESPONSECODE(*IFDH_get_capabilities) (DWORD, DWORD, PDWORD, /*@out@*/ PUCHAR) = NULL; if (rContext->dwVersion == IFD_HVERSION_1_0) IFD_get_capabilities = rContext->psFunctions.psFunctions_v1.pvfGetCapabilities; else IFDH_get_capabilities = rContext->psFunctions.psFunctions_v2.pvfGetCapabilities; #endif /* LOCK THIS CODE REGION */ (void)SYS_MutexLock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER if (rContext->dwVersion == IFD_HVERSION_1_0) rv = (*IFD_get_capabilities) (dwTag, pucValue); else rv = (*IFDH_get_capabilities) (rContext->dwSlot, dwTag, pdwLength, pucValue); #else if (rContext->dwVersion == IFD_HVERSION_1_0) rv = IFD_Get_Capabilities(dwTag, pucValue); else rv = IFDHGetCapabilities(rContext->dwSlot, dwTag, pdwLength, pucValue); #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(rContext->mMutex); return rv; }
static LONG HPAddHotPluggable(struct usb_device *dev, const char bus_device[], struct _driverTracker *driver) { int i; char deviceName[MAX_DEVICENAME]; Log2(PCSC_LOG_INFO, "Adding USB device: %s", bus_device); snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libusb:%s", dev->descriptor.idVendor, dev->descriptor.idProduct, bus_device); deviceName[sizeof(deviceName) -1] = '\0'; SYS_MutexLock(&usbNotifierMutex); /* find a free entry */ for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++) { if (readerTracker[i].fullName == NULL) break; } if (i==PCSCLITE_MAX_READERS_CONTEXTS) { Log2(PCSC_LOG_ERROR, "Not enough reader entries. Already found %d readers", i); SYS_MutexUnLock(&usbNotifierMutex); return 0; } strncpy(readerTracker[i].bus_device, bus_device, sizeof(readerTracker[i].bus_device)); readerTracker[i].bus_device[sizeof(readerTracker[i].bus_device) - 1] = '\0'; #ifdef ADD_SERIAL_NUMBER if (dev->descriptor.iSerialNumber) { usb_dev_handle *device; char serialNumber[MAX_READERNAME]; char fullname[MAX_READERNAME]; int ret; device = usb_open(dev); ret = usb_get_string_simple(device, dev->descriptor.iSerialNumber, serialNumber, MAX_READERNAME); usb_close(device); if (ret < 0) { Log2(PCSC_LOG_ERROR, "usb_get_string_simple failed: %s", usb_strerror()); readerTracker[i].fullName = strdup(driver->readerName); } else { snprintf(fullname, sizeof(fullname), "%s (%s)", driver->readerName, serialNumber); readerTracker[i].fullName = strdup(fullname); } } else #endif readerTracker[i].fullName = strdup(driver->readerName); if (RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i, driver->libraryPath, deviceName) == SCARD_S_SUCCESS) readerTracker[i].status = READER_PRESENT; else { readerTracker[i].status = READER_FAILED; (void)CheckForOpenCT(); } SYS_MutexUnLock(&usbNotifierMutex); return 1; } /* End of function */
static void HPEstablishUSBNotifications(void) { int i, j, usbDeviceStatus; DIR *dir, *dirB; struct dirent *entry, *entryB; int deviceNumber; int suspectDeviceNumber; char dirpath[FILENAME_MAX]; char filename[FILENAME_MAX]; int fd, ret; struct usb_device_descriptor usbDescriptor; usbDeviceStatus = 0; suspectDeviceNumber = 0; while (1) { for (i = 0; i < bundleSize; i++) { usbDeviceStatus = 0; suspectDeviceNumber = 0; for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++) /* clear rollcall */ bundleTracker[i].deviceNumber[j].status = 0; dir = NULL; dir = opendir(PCSCLITE_USB_PATH); if (dir == NULL) { Log1(PCSC_LOG_ERROR, "Cannot open USB path directory: " PCSCLITE_USB_PATH); return; } entry = NULL; while ((entry = readdir(dir)) != 0) { /* * Skip anything starting with a */ if (entry->d_name[0] == '.') continue; if (!strchr("0123456789", entry->d_name[strlen(entry->d_name) - 1])) { continue; } sprintf(dirpath, "%s/%s", PCSCLITE_USB_PATH, entry->d_name); dirB = opendir(dirpath); if (dirB == NULL) { Log2(PCSC_LOG_ERROR, "USB path seems to have disappeared %s", dirpath); closedir(dir); return; } while ((entryB = readdir(dirB)) != NULL) { /* * Skip anything starting with a */ if (entryB->d_name[0] == '.') continue; /* Get the device number so we can distinguish multiple readers */ sprintf(filename, "%s/%s", dirpath, entryB->d_name); sscanf(entryB->d_name, "%d", &deviceNumber); fd = open(filename, O_RDONLY); if (fd < 0) continue; ret = read(fd, (void *) &usbDescriptor, sizeof(usbDescriptor)); close(fd); if (ret < 0) continue; /* * Device is found and we don't know about it */ if (usbDescriptor.idVendor == bundleTracker[i].manuID && usbDescriptor.idProduct == bundleTracker[i].productID && usbDescriptor.idVendor !=0 && usbDescriptor.idProduct != 0) { for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++) { if (bundleTracker[i].deviceNumber[j].id == deviceNumber && bundleTracker[i].deviceNumber[j].id != 0) { bundleTracker[i].deviceNumber[j].status = 1; /* i'm here */ break; } } if (j == PCSCLITE_MAX_READERS_CONTEXTS) { usbDeviceStatus = 1; suspectDeviceNumber = deviceNumber; } } } /* End of while */ closedir(dirB); } /* End of while */ if (usbDeviceStatus == 1) { SYS_MutexLock(&usbNotifierMutex); for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++) { if (bundleTracker[i].deviceNumber[j].id == 0) break; } if (j == PCSCLITE_MAX_READERS_CONTEXTS) Log1(PCSC_LOG_ERROR, "Too many identical readers plugged in"); else { HPAddHotPluggable(i, j+1); bundleTracker[i].deviceNumber[j].id = suspectDeviceNumber; } SYS_MutexUnLock(&usbNotifierMutex); } else if (usbDeviceStatus == 0) { for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++) { if (bundleTracker[i].deviceNumber[j].id != 0 && bundleTracker[i].deviceNumber[j].status == 0) { SYS_MutexLock(&usbNotifierMutex); HPRemoveHotPluggable(i, j+1); bundleTracker[i].deviceNumber[j].id = 0; SYS_MutexUnLock(&usbNotifierMutex); } } } else { /* * Do nothing - no USB devices found */ } if (dir) closedir(dir); } /* End of for..loop */ SYS_Sleep(1); if (AraKiriHotPlug) { int retval; Log1(PCSC_LOG_INFO, "Hotplug stopped"); pthread_exit(&retval); } } /* End of while loop */ }
/** * 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, const unsigned char *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; // Defensive measure if (!IFDH_icc_presence) return SCARD_E_SYSTEM_CANCELLED; } #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, (unsigned char *)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, const unsigned char *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, (unsigned char *)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; }
/** * Open a communication channel to the IFD. */ LONG IFDOpenIFD(PREADER_CONTEXT rContext) { RESPONSECODE rv = 0; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IO_create_channel) (DWORD) = NULL; RESPONSECODE(*IFDH_create_channel) (DWORD, DWORD) = NULL; RESPONSECODE(*IFDH_create_channel_by_name) (DWORD, LPSTR) = NULL; if (rContext->dwVersion == IFD_HVERSION_1_0) IO_create_channel = rContext->psFunctions.psFunctions_v1.pvfCreateChannel; else if (rContext->dwVersion == IFD_HVERSION_2_0) IFDH_create_channel = rContext->psFunctions.psFunctions_v2.pvfCreateChannel; else { IFDH_create_channel = rContext->psFunctions.psFunctions_v3.pvfCreateChannel; IFDH_create_channel_by_name = rContext->psFunctions.psFunctions_v3.pvfCreateChannelByName; } #endif /* LOCK THIS CODE REGION */ (void)SYS_MutexLock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER if (rContext->dwVersion == IFD_HVERSION_1_0) { rv = (*IO_create_channel) (rContext->dwPort); } else if (rContext->dwVersion == IFD_HVERSION_2_0) { rv = (*IFDH_create_channel) (rContext->dwSlot, rContext->dwPort); } else { /* use device name only if defined */ if (rContext->lpcDevice[0] != '\0') rv = (*IFDH_create_channel_by_name) (rContext->dwSlot, rContext->lpcDevice); else rv = (*IFDH_create_channel) (rContext->dwSlot, rContext->dwPort); } #else if (rContext->dwVersion == IFD_HVERSION_1_0) { rv = IO_Create_Channel(rContext->dwPort); } else if (rContext->dwVersion == IFD_HVERSION_2_0) { rv = IFDHCreateChannel(rContext->dwSlot, rContext->dwPort); } else { /* Use device name only if defined */ if (rContext->lpcDevice[0] != '\0') rv = IFDHCreateChannelByName(rContext->dwSlot, rContext->lpcDevice); else rv = IFDHCreateChannel(rContext->dwSlot, rContext->dwPort); } #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(rContext->mMutex); return rv; }
LONG SCardConnect(/*@unused@*/ SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) { LONG rv; PREADER_CONTEXT rContext = NULL; DWORD dwStatus; (void)hContext; PROFILE_START /* * Check for NULL parameters */ if (szReader == NULL || phCard == NULL || pdwActiveProtocol == NULL) return SCARD_E_INVALID_PARAMETER; else *phCard = 0; if ((dwShareMode != SCARD_SHARE_DIRECT) && !(dwPreferredProtocols & SCARD_PROTOCOL_T0) && !(dwPreferredProtocols & SCARD_PROTOCOL_T1) && !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) && !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)) return SCARD_E_PROTO_MISMATCH; if (dwShareMode != SCARD_SHARE_EXCLUSIVE && dwShareMode != SCARD_SHARE_SHARED && dwShareMode != SCARD_SHARE_DIRECT) return SCARD_E_INVALID_VALUE; Log3(PCSC_LOG_DEBUG, "Attempting Connect to %s using protocol: %d", szReader, dwPreferredProtocols); rv = RFReaderInfo((LPSTR) szReader, &rContext); if (rv != SCARD_S_SUCCESS) { Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader); return rv; } /* * Make sure the reader is working properly */ rv = RFCheckReaderStatus(rContext); if (rv != SCARD_S_SUCCESS) return rv; /******************************************* * * This section checks for simple errors * *******************************************/ /* * Connect if not exclusive mode */ if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT) { Log1(PCSC_LOG_ERROR, "Error Reader Exclusive"); return SCARD_E_SHARING_VIOLATION; } /* * wait until a possible transaction is finished */ if (rContext->dwLockId != 0) { Log1(PCSC_LOG_INFO, "Waiting for release of lock"); while (rContext->dwLockId != 0) (void)SYS_USleep(PCSCLITE_LOCK_POLL_RATE); Log1(PCSC_LOG_INFO, "Lock released"); } /* the reader has been removed while we were waiting */ if (NULL == rContext->readerState) return SCARD_E_NO_SMARTCARD; /******************************************* * * This section tries to determine the * presence of a card or not * *******************************************/ dwStatus = rContext->readerState->readerState; if (dwShareMode != SCARD_SHARE_DIRECT) { if (!(dwStatus & SCARD_PRESENT)) { Log1(PCSC_LOG_ERROR, "Card Not Inserted"); return SCARD_E_NO_SMARTCARD; } if (dwStatus & SCARD_SWALLOWED) { Log1(PCSC_LOG_ERROR, "Card Not Powered"); return SCARD_W_UNPOWERED_CARD; } } /******************************************* * * This section tries to decode the ATR * and set up which protocol to use * *******************************************/ if (dwPreferredProtocols & SCARD_PROTOCOL_RAW) rContext->readerState->cardProtocol = SCARD_PROTOCOL_RAW; else { if (dwShareMode != SCARD_SHARE_DIRECT) { /* lock here instead in IFDSetPTS() to lock up to * setting rContext->readerState->cardProtocol */ (void)SYS_MutexLock(rContext->mMutex); /* the protocol is not yet set (no PPS yet) */ if (SCARD_PROTOCOL_UNDEFINED == rContext->readerState->cardProtocol) { UCHAR ucAvailable, ucDefault; int ret; ucDefault = PHGetDefaultProtocol(rContext->readerState->cardAtr, rContext->readerState->cardAtrLength); ucAvailable = PHGetAvailableProtocols(rContext->readerState->cardAtr, rContext->readerState->cardAtrLength); /* * If it is set to ANY let it do any of the protocols */ if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD) dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1; ret = PHSetProtocol(rContext, dwPreferredProtocols, ucAvailable, ucDefault); /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error */ if (SET_PROTOCOL_PPS_FAILED == ret) { (void)SYS_MutexUnLock(rContext->mMutex); return SCARD_W_UNRESPONSIVE_CARD; } if (SET_PROTOCOL_WRONG_ARGUMENT == ret) { (void)SYS_MutexUnLock(rContext->mMutex); return SCARD_E_PROTO_MISMATCH; } /* use negotiated protocol */ rContext->readerState->cardProtocol = ret; (void)SYS_MutexUnLock(rContext->mMutex); } else { (void)SYS_MutexUnLock(rContext->mMutex); if (! (dwPreferredProtocols & rContext->readerState->cardProtocol)) return SCARD_E_PROTO_MISMATCH; } } else rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; } *pdwActiveProtocol = rContext->readerState->cardProtocol; if (dwShareMode != SCARD_SHARE_DIRECT) { if ((*pdwActiveProtocol != SCARD_PROTOCOL_T0) && (*pdwActiveProtocol != SCARD_PROTOCOL_T1)) Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %d", *pdwActiveProtocol); else Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d", (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1); } else Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected"); /* * Prepare the SCARDHANDLE identity */ *phCard = RFCreateReaderHandle(rContext); Log2(PCSC_LOG_DEBUG, "hCard Identity: %x", *phCard); /******************************************* * * This section tries to set up the * exclusivity modes. -1 is exclusive * *******************************************/ if (dwShareMode == SCARD_SHARE_EXCLUSIVE) { if (rContext->dwContexts == SCARD_NO_CONTEXT) { rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT; (void)RFLockSharing(*phCard); } else { (void)RFDestroyReaderHandle(*phCard); *phCard = 0; return SCARD_E_SHARING_VIOLATION; } } else { /* * Add a connection to the context stack */ rContext->dwContexts += 1; } /* * Add this handle to the handle list */ rv = RFAddReaderHandle(rContext, *phCard); if (rv != SCARD_S_SUCCESS) { /* * Clean up - there is no more room */ (void)RFDestroyReaderHandle(*phCard); if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT) rContext->dwContexts = SCARD_NO_CONTEXT; else if (rContext->dwContexts > SCARD_NO_CONTEXT) rContext->dwContexts -= 1; *phCard = 0; PROFILE_END return SCARD_F_INTERNAL_ERROR; }