/***************************************************************************** * * ReadUSB * ****************************************************************************/ status_t ReadUSB(unsigned int reader_index, unsigned int * length, unsigned char *buffer) { int rv; int actual_length; char debug_header[] = "<- 121234 "; _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); int duplicate_frame = 0; read_again: (void)snprintf(debug_header, sizeof(debug_header), "<- %06X ", (int)reader_index); rv = libusb_bulk_transfer(usbDevice[reader_index].dev_handle, usbDevice[reader_index].bulk_in, buffer, *length, &actual_length, usbDevice[reader_index].ccid.readTimeout); if (rv < 0) { *length = 0; DEBUG_CRITICAL5("read failed (%d/%d): %d %s", usbDevice[reader_index].bus_number, usbDevice[reader_index].device_address, rv, libusb_error_name(rv)); if (LIBUSB_ERROR_NO_DEVICE == rv) return STATUS_NO_SUCH_DEVICE; return STATUS_UNSUCCESSFUL; } *length = actual_length; DEBUG_XXD(debug_header, buffer, *length); #define BSEQ_OFFSET 6 if ((*length >= BSEQ_OFFSET) && (buffer[BSEQ_OFFSET] < *ccid_descriptor->pbSeq -1)) { duplicate_frame++; if (duplicate_frame > 10) { DEBUG_CRITICAL("Too many duplicate frame detected"); return STATUS_UNSUCCESSFUL; } DEBUG_INFO1("Duplicate frame detected"); goto read_again; } return STATUS_SUCCESS; } /* ReadUSB */
/***************************************************************************** * * dump_gemalto_firmware_features * ****************************************************************************/ static void dump_gemalto_firmware_features(struct GEMALTO_FIRMWARE_FEATURES *gff) { DEBUG_INFO2("Dumping Gemalto firmware features (%zd bytes):", sizeof(struct GEMALTO_FIRMWARE_FEATURES)); #define YESNO(x) (x) ? "yes" : "no" DEBUG_INFO2(" bLogicalLCDLineNumber: %d", gff->bLogicalLCDLineNumber); DEBUG_INFO2(" bLogicalLCDRowNumber: %d", gff->bLogicalLCDRowNumber); DEBUG_INFO2(" bLcdInfo: 0x%02X", gff->bLcdInfo); DEBUG_INFO2(" bEntryValidationCondition: 0x%02X", gff->bEntryValidationCondition); DEBUG_INFO1(" Reader supports PC/SCv2 features:"); DEBUG_INFO2(" VerifyPinStart: %s", YESNO(gff->VerifyPinStart)); DEBUG_INFO2(" VerifyPinFinish: %s", YESNO(gff->VerifyPinFinish)); DEBUG_INFO2(" ModifyPinStart: %s", YESNO(gff->ModifyPinStart)); DEBUG_INFO2(" ModifyPinFinish: %s", YESNO(gff->ModifyPinFinish)); DEBUG_INFO2(" GetKeyPressed: %s", YESNO(gff->GetKeyPressed)); DEBUG_INFO2(" VerifyPinDirect: %s", YESNO(gff->VerifyPinDirect)); DEBUG_INFO2(" ModifyPinDirect: %s", YESNO(gff->ModifyPinDirect)); DEBUG_INFO2(" Abort: %s", YESNO(gff->Abort)); DEBUG_INFO2(" GetKey: %s", YESNO(gff->GetKey)); DEBUG_INFO2(" WriteDisplay: %s", YESNO(gff->WriteDisplay)); DEBUG_INFO2(" SetSpeMessage: %s", YESNO(gff->SetSpeMessage)); DEBUG_INFO2(" bTimeOut2: %s", YESNO(gff->bTimeOut2)); DEBUG_INFO2(" bPPDUSupportOverXferBlock: %s", YESNO(gff->bPPDUSupportOverXferBlock)); DEBUG_INFO2(" bPPDUSupportOverEscape: %s", YESNO(gff->bPPDUSupportOverEscape)); DEBUG_INFO2(" bListSupportedLanguages: %s", YESNO(gff->bListSupportedLanguages)); DEBUG_INFO2(" bNumberMessageFix: %s", YESNO(gff->bNumberMessageFix)); DEBUG_INFO2(" VersionNumber: 0x%02X", gff->VersionNumber); DEBUG_INFO2(" MinimumPINSize: %d", gff->MinimumPINSize); DEBUG_INFO2(" MaximumPINSize: %d", gff->MaximumPINSize); DEBUG_INFO2(" Firewall: %s", YESNO(gff->Firewall)); if (gff->Firewall && gff->FirewalledCommand_SW1 && gff->FirewalledCommand_SW2) { DEBUG_INFO2(" FirewalledCommand_SW1: 0x%02X", gff->FirewalledCommand_SW1); DEBUG_INFO2(" FirewalledCommand_SW2: 0x%02X", gff->FirewalledCommand_SW2); } } /* dump_gemalto_firmware_features */
/***************************************************************************** * * close_libusb_if_needed * ****************************************************************************/ static void close_libusb_if_needed(void) { int i, to_exit = TRUE; /* if at least 1 reader is still in use we do not exit libusb */ for (i=0; i<CCID_DRIVER_MAX_READERS; i++) { if (usbDevice[i].dev_handle != NULL) to_exit = FALSE; } if (to_exit) { DEBUG_INFO1("libusb_exit"); libusb_exit(ctx); ctx = NULL; } } /* close_libusb_if_needed */
/***************************************************************************** * * ccid_open_hack_pre * ****************************************************************************/ int ccid_open_hack_pre(unsigned int reader_index) { _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); switch (ccid_descriptor->readerID) { case MYSMARTPAD: ccid_descriptor->dwMaxIFSD = 254; break; case CL1356D: /* the firmware needs some time to initialize */ (void)sleep(1); ccid_descriptor->readTimeout = 60*1000; /* 60 seconds */ break; case GEMPCTWIN: case GEMPCKEY: case DELLSCRK: /* Only the chipset with firmware version 2.00 is "bogus" * The reader may send packets of 0 bytes when the reader is * connected to a USB 3 port */ if (0x0200 == ccid_descriptor->IFD_bcdDevice) { ccid_descriptor->zlp = TRUE; DEBUG_INFO1("ZLP fixup"); } break; case OZ776_7772: ccid_descriptor->dwMaxDataRate = 9600; break; case SCR331NTTCOM: ccid_descriptor->bInterfaceProtocol = 0; break; } /* CCID */ if ((PROTOCOL_CCID == ccid_descriptor->bInterfaceProtocol) && (3 == ccid_descriptor -> bNumEndpoints)) { #ifndef TWIN_SERIAL /* just wait for 100ms in case a notification is in the pipe */ (void)InterruptRead(reader_index, 100); #endif } /* ICCD type A */ if (PROTOCOL_ICCD_A == ccid_descriptor->bInterfaceProtocol) { unsigned char tmp[MAX_ATR_SIZE]; unsigned int n = sizeof(tmp); DEBUG_COMM("ICCD type A"); (void)CmdPowerOff(reader_index); (void)CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE); (void)CmdPowerOff(reader_index); } /* ICCD type B */ if (PROTOCOL_ICCD_B == ccid_descriptor->bInterfaceProtocol) { unsigned char tmp[MAX_ATR_SIZE]; unsigned int n = sizeof(tmp); DEBUG_COMM("ICCD type B"); if (CCID_CLASS_SHORT_APDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)) { /* use the extended APDU comm alogorithm */ ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK; ccid_descriptor->dwFeatures |= CCID_CLASS_EXTENDED_APDU; } (void)CmdPowerOff(reader_index); (void)CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE); (void)CmdPowerOff(reader_index); } return 0; } /* ccid_open_hack_pre */
double delayImpl(DATA* data, int exprNumber, double exprValue, double time, double delayTime, double delayMax) { RINGBUFFER* delayStruct = data->simulationInfo.delayStructure[exprNumber]; int length = ringBufferLength(delayStruct); DEBUG_INFO4(LOG_EVENTS, "delayImpl: exprNumber = %d, exprValue = %g, time = %g, delayTime = %g", exprNumber, exprValue, time, delayTime); /* Check for errors */ ASSERT1(0 <= exprNumber, "invalid exprNumber = %d", exprNumber); ASSERT1(exprNumber < data->modelData.nDelayExpressions, "invalid exprNumber = %d", exprNumber); if(time <= data->simulationInfo.tStart) { DEBUG_INFO1(LOG_EVENTS, "delayImpl: Entered at time < starting time: %g.", exprValue); return (exprValue); } if(delayTime < 0.0) { ASSERT1(0.0 < delayTime, "Negative delay requested: delayTime = %g", delayTime); THROW("Negative delay requested"); } if(length == 0) { /* This occurs in the initialization phase */ DEBUG_INFO1(LOG_EVENTS, "delayImpl: Missing initial value, using argument value %g instead.", exprValue); return (exprValue); } /* * Returns: expr(time?delayTime) for time>time.start + delayTime and * expr(time.start) for time <= time.start + delayTime. * The arguments, i.e., expr, delayTime and delayMax, need to be subtypes of Real. * DelayMax needs to be additionally a parameter expression. * The following relation shall hold: 0 <= delayTime <= delayMax, * otherwise an error occurs. If delayMax is not supplied in the argument list, * delayTime need to be a parameter expression. See also Section 3.7.2.1. * For non-scalar arguments the function is vectorized according to Section 10.6.12. */ if(time <= data->simulationInfo.tStart + delayTime) { double res = ((TIME_AND_VALUE*)getRingData(delayStruct, 0))->value; DEBUG_INFO2(LOG_EVENTS, "findTime: time <= tStart + delayTime: [%d] = %g",exprNumber, res); return res; } else { /* return expr(time-delayTime) */ double timeStamp = time - delayTime; double time0, time1, value0, value1; int i; ASSERT1(0.0 <= delayTime, "Negative delay requested: delayTime = %g", delayTime); /* find the row for the lower limit */ if(timeStamp > ((TIME_AND_VALUE*)getRingData(delayStruct, length - 1))->time) { /* delay between the last accepted time step and the current time */ time0 = ((TIME_AND_VALUE*)getRingData(delayStruct, length - 1))->time; value0 = ((TIME_AND_VALUE*)getRingData(delayStruct, length - 1))->value; time1 = time; value1 = exprValue; } else { i = findTime(timeStamp, delayStruct); ASSERT2(i < length, "%d = i < length = %d", i, length); time0 = ((TIME_AND_VALUE*)getRingData(delayStruct, i))->time; value0 = ((TIME_AND_VALUE*)getRingData(delayStruct, i))->value; /* was it the last value? */ if(i+1 == length) { if(0 < i && delayMax == delayTime) dequeueNFirstRingDatas(delayStruct, i-1); DEBUG_INFO3(LOG_EVENTS, "delayImpl: dequeueNFirstRingDatas[%d] %g = %g", i, delayMax, delayTime); return value0; } time1 = ((TIME_AND_VALUE*)getRingData(delayStruct, i+1))->time; value1 = ((TIME_AND_VALUE*)getRingData(delayStruct, i+1))->value; if(0 < i && delayMax == delayTime) dequeueNFirstRingDatas(delayStruct, i-1); } /* was it an exact match?*/ if(time0 == timeStamp){ DEBUG_INFO2(LOG_EVENTS, "delayImpl: Exact match at %g = %g", timeStamp, value0); return value0; } else if(time1 == timeStamp) { DEBUG_INFO2(LOG_EVENTS, "delayImpl: Exact match at %g = %g", timeStamp, value1); return value1; } else { /* linear interpolation */ double timedif = time1 - time0; double dt0 = time1 - timeStamp; double dt1 = timeStamp - time0; double retVal = (value0 * dt0 + value1 * dt1) / timedif; DEBUG_INFO3(LOG_EVENTS, "delayImpl: Linear interpolation of %g between %g and %g", timeStamp, time0, time1); DEBUG_INFO4(LOG_EVENTS, "delayImpl: Linear interpolation of %g value: %g and %g = %g", timeStamp, value0, value1, retVal); return retVal; } } }
/***************************************************************************** * * OpenUSBByName * ****************************************************************************/ status_t OpenUSBByName(unsigned int reader_index, /*@null@*/ char *device) { unsigned int alias; struct libusb_device_handle *dev_handle; char infofile[FILENAME_MAX]; #ifndef __APPLE__ unsigned int device_vendor, device_product; unsigned int device_bus = 0; unsigned int device_addr = 0; #else /* 100 ms delay */ struct timespec sleep_time = { 0, 100 * 1000 * 1000 }; int count_libusb = 10; #endif int interface_number = -1; int i; static int previous_reader_index = -1; libusb_device **devs, *dev; ssize_t cnt; list_t plist, *values, *ifdVendorID, *ifdProductID, *ifdFriendlyName; int rv; int claim_failed = FALSE; int return_value = STATUS_SUCCESS; DEBUG_COMM3("Reader index: %X, Device: %s", reader_index, device); #ifndef __APPLE__ /* device name specified */ if (device) { char *dirname; /* format: usb:%04x/%04x, vendor, product */ if (strncmp("usb:", device, 4) != 0) { DEBUG_CRITICAL2("device name does not start with \"usb:\": %s", device); return STATUS_UNSUCCESSFUL; } if (sscanf(device, "usb:%x/%x", &device_vendor, &device_product) != 2) { DEBUG_CRITICAL2("device name can't be parsed: %s", device); return STATUS_UNSUCCESSFUL; } /* format usb:%04x/%04x:libudev:%d:%s * with %d set to * 01 (or whatever the interface number is) * and %s set to * /dev/bus/usb/008/004 */ if ((dirname = strstr(device, "libudev:")) != NULL) { /* convert the interface number, bus and device ids */ if (sscanf(dirname + 8, "%d:/dev/bus/usb/%d/%d", &interface_number, &device_bus, &device_addr) == 3) { DEBUG_COMM2("interface_number: %d", interface_number); DEBUG_COMM3("usb bus/device: %d/%d", device_bus, device_addr); } } } #endif /* is the reader_index already used? */ if (usbDevice[reader_index].dev_handle != NULL) { DEBUG_CRITICAL2("USB driver with index %X already in use", reader_index); return STATUS_UNSUCCESSFUL; } /* Info.plist full patch filename */ (void)snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist", PCSCLITE_HP_DROPDIR, BUNDLE); DEBUG_INFO2("Using: %s", infofile); rv = bundleParse(infofile, &plist); if (rv) return STATUS_UNSUCCESSFUL; #define GET_KEY(key, values) \ rv = LTPBundleFindValueWithKey(&plist, key, &values); \ if (rv) \ { \ DEBUG_CRITICAL2("Value/Key not defined for " key " in %s", infofile); \ return_value = STATUS_UNSUCCESSFUL; \ goto end1; \ } \ else \ DEBUG_INFO2(key ": %s", (char *)list_get_at(values, 0)); /* general driver info */ GET_KEY("ifdManufacturerString", values) GET_KEY("ifdProductString", values) GET_KEY("Copyright", values) if (NULL == ctx) { rv = libusb_init(&ctx); if (rv != 0) { DEBUG_CRITICAL2("libusb_init failed: %s", libusb_error_name(rv)); return_value = STATUS_UNSUCCESSFUL; goto end1; } } #define GET_KEYS(key, values) \ rv = LTPBundleFindValueWithKey(&plist, key, values); \ if (rv) \ { \ DEBUG_CRITICAL2("Value/Key not defined for " key " in %s", infofile); \ return_value = STATUS_UNSUCCESSFUL; \ goto end1; \ } GET_KEYS("ifdVendorID", &ifdVendorID) GET_KEYS("ifdProductID", &ifdProductID); GET_KEYS("ifdFriendlyName", &ifdFriendlyName) /* The 3 lists do not have the same size */ if ((list_size(ifdVendorID) != list_size(ifdProductID)) || (list_size(ifdVendorID) != list_size(ifdFriendlyName))) { DEBUG_CRITICAL2("Error parsing %s", infofile); return_value = STATUS_UNSUCCESSFUL; goto end1; } #ifdef __APPLE__ again_libusb: #endif cnt = libusb_get_device_list(ctx, &devs); if (cnt < 0) { DEBUG_CRITICAL("libusb_get_device_list() failed\n"); return_value = STATUS_UNSUCCESSFUL; goto end1; } /* for any supported reader */ for (alias=0; alias<list_size(ifdVendorID); alias++) { unsigned int vendorID, productID; char *friendlyName; vendorID = strtoul(list_get_at(ifdVendorID, alias), NULL, 0); productID = strtoul(list_get_at(ifdProductID, alias), NULL, 0); friendlyName = list_get_at(ifdFriendlyName, alias); #ifndef __APPLE__ /* the device was specified but is not the one we are trying to find */ if (device && (vendorID != device_vendor || productID != device_product)) continue; #else /* Leopard puts the friendlyname in the device argument */ if (device && strcmp(device, friendlyName)) continue; #endif /* for every device */ i = 0; while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor desc; struct libusb_config_descriptor *config_desc; uint8_t bus_number = libusb_get_bus_number(dev); uint8_t device_address = libusb_get_device_address(dev); #ifndef __APPLE__ if ((device_bus || device_addr) && ((bus_number != device_bus) || (device_address != device_addr))) { /* not USB the device we are looking for */ continue; } #endif DEBUG_COMM3("Try device: %d/%d", bus_number, device_address); int r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { DEBUG_INFO3("failed to get device descriptor for %d/%d", bus_number, device_address); continue; } DEBUG_COMM3("vid/pid : %04X/%04X", desc.idVendor, desc.idProduct); if (desc.idVendor == vendorID && desc.idProduct == productID) { int already_used; const struct libusb_interface *usb_interface = NULL; int interface; int num = 0; const unsigned char *device_descriptor; int readerID = (vendorID << 16) + productID; #ifdef USE_COMPOSITE_AS_MULTISLOT static int static_interface = 1; /* simulate a composite device as when libudev is used */ if ((GEMALTOPROXDU == readerID) || (GEMALTOPROXSU == readerID) || (FEITIANR502DUAL == readerID)) { /* * We can't talk to the two CCID interfaces * at the same time (the reader enters a * dead lock). So we simulate a multi slot * reader. By default multi slot readers * can't use the slots at the same time. See * TAG_IFD_SLOT_THREAD_SAFE * * One side effect is that the two readers * are seen by pcscd as one reader so the * interface name is the same for the two. * * So we have: * 0: Gemalto Prox-DU [Prox-DU Contact_09A00795] (09A00795) 00 00 * 1: Gemalto Prox-DU [Prox-DU Contact_09A00795] (09A00795) 00 01 * instead of * 0: Gemalto Prox-DU [Prox-DU Contact_09A00795] (09A00795) 00 00 * 1: Gemalto Prox-DU [Prox-DU Contactless_09A00795] (09A00795) 01 00 */ /* the CCID interfaces are 1 and 2 */ interface_number = static_interface; } #endif /* is it already opened? */ already_used = FALSE; DEBUG_COMM3("Checking device: %d/%d", bus_number, device_address); for (r=0; r<CCID_DRIVER_MAX_READERS; r++) { if (usbDevice[r].dev_handle) { /* same bus, same address */ if (usbDevice[r].bus_number == bus_number && usbDevice[r].device_address == device_address) already_used = TRUE; } } /* this reader is already managed by us */ if (already_used) { if ((previous_reader_index != -1) && usbDevice[previous_reader_index].dev_handle && (usbDevice[previous_reader_index].bus_number == bus_number) && (usbDevice[previous_reader_index].device_address == device_address) && usbDevice[previous_reader_index].ccid.bCurrentSlotIndex < usbDevice[previous_reader_index].ccid.bMaxSlotIndex) { /* we reuse the same device * and the reader is multi-slot */ usbDevice[reader_index] = usbDevice[previous_reader_index]; /* The other slots of GemCore SIM Pro firmware * 1.0 do not have the same data rates. * Firmware 2.0 do not have this limitation */ if ((GEMCOREPOSPRO == readerID) || ((GEMCORESIMPRO == readerID) && (usbDevice[reader_index].ccid.IFD_bcdDevice < 0x0200))) { usbDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialCustomDataRates; usbDevice[reader_index].ccid.dwMaxDataRate = 125000; } *usbDevice[reader_index].nb_opened_slots += 1; usbDevice[reader_index].ccid.bCurrentSlotIndex++; usbDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT; DEBUG_INFO2("Opening slot: %d", usbDevice[reader_index].ccid.bCurrentSlotIndex); /* This is a multislot reader * Init the multislot stuff for this next slot */ usbDevice[reader_index].multislot_extension = Multi_CreateNextSlot(previous_reader_index); goto end; } else { /* if an interface number is given by HAL we * continue with this device. */ if (-1 == interface_number) { DEBUG_INFO3("USB device %d/%d already in use." " Checking next one.", bus_number, device_address); continue; } } } DEBUG_COMM3("Trying to open USB bus/device: %d/%d", bus_number, device_address); r = libusb_open(dev, &dev_handle); if (r < 0) { DEBUG_CRITICAL4("Can't libusb_open(%d/%d): %s", bus_number, device_address, libusb_error_name(r)); continue; } again: r = libusb_get_active_config_descriptor(dev, &config_desc); if (r < 0) { #ifdef __APPLE__ /* Some early Gemalto Ezio CB+ readers have * bDeviceClass, bDeviceSubClass and bDeviceProtocol set * to 0xFF (proprietary) instead of 0x00. * * So on Mac OS X the reader configuration is not done * by the OS/kernel and we do it ourself. */ if ((0xFF == desc.bDeviceClass) && (0xFF == desc.bDeviceSubClass) && (0xFF == desc.bDeviceProtocol)) { r = libusb_set_configuration(dev_handle, 1); if (r < 0) { (void)libusb_close(dev_handle); DEBUG_CRITICAL4("Can't set configuration on %d/%d: %s", bus_number, device_address, libusb_error_name(r)); continue; } } /* recall */ r = libusb_get_active_config_descriptor(dev, &config_desc); if (r < 0) { #endif (void)libusb_close(dev_handle); DEBUG_CRITICAL4("Can't get config descriptor on %d/%d: %s", bus_number, device_address, libusb_error_name(r)); continue; } #ifdef __APPLE__ } #endif usb_interface = get_ccid_usb_interface(config_desc, &num); if (usb_interface == NULL) { (void)libusb_close(dev_handle); if (0 == num) DEBUG_CRITICAL3("Can't find a CCID interface on %d/%d", bus_number, device_address); interface_number = -1; continue; } device_descriptor = get_ccid_device_descriptor(usb_interface); if (NULL == device_descriptor) { (void)libusb_close(dev_handle); DEBUG_CRITICAL3("Unable to find the device descriptor for %d/%d", bus_number, device_address); return_value = STATUS_UNSUCCESSFUL; goto end2; } interface = usb_interface->altsetting->bInterfaceNumber; if (interface_number >= 0 && interface != interface_number) { /* an interface was specified and it is not the * current one */ DEBUG_INFO3("Found interface %d but expecting %d", interface, interface_number); DEBUG_INFO3("Wrong interface for USB device %d/%d." " Checking next one.", bus_number, device_address); /* check for another CCID interface on the same device */ num++; goto again; } r = libusb_claim_interface(dev_handle, interface); if (r < 0) { (void)libusb_close(dev_handle); DEBUG_CRITICAL4("Can't claim interface %d/%d: %s", bus_number, device_address, libusb_error_name(r)); claim_failed = TRUE; interface_number = -1; continue; } DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)", desc.idVendor, desc.idProduct, friendlyName); DEBUG_INFO3("Using USB bus/device: %d/%d", bus_number, device_address); /* check for firmware bugs */ if (ccid_check_firmware(&desc)) { (void)libusb_close(dev_handle); return_value = STATUS_UNSUCCESSFUL; goto end2; } #ifdef USE_COMPOSITE_AS_MULTISLOT /* use the next interface for the next "slot" */ static_interface++; /* reset for a next reader */ if (static_interface > 2) static_interface = (FEITIANR502DUAL == readerID) ? 0: 1; #endif /* Get Endpoints values*/ (void)get_end_points(config_desc, &usbDevice[reader_index], num); /* store device information */ usbDevice[reader_index].dev_handle = dev_handle; usbDevice[reader_index].bus_number = bus_number; usbDevice[reader_index].device_address = device_address; usbDevice[reader_index].interface = interface; usbDevice[reader_index].real_nb_opened_slots = 1; usbDevice[reader_index].nb_opened_slots = &usbDevice[reader_index].real_nb_opened_slots; usbDevice[reader_index].polling_transfer = NULL; /* CCID common informations */ usbDevice[reader_index].ccid.real_bSeq = 0; usbDevice[reader_index].ccid.pbSeq = &usbDevice[reader_index].ccid.real_bSeq; usbDevice[reader_index].ccid.readerID = (desc.idVendor << 16) + desc.idProduct; usbDevice[reader_index].ccid.dwFeatures = dw2i(device_descriptor, 40); usbDevice[reader_index].ccid.wLcdLayout = (device_descriptor[51] << 8) + device_descriptor[50]; usbDevice[reader_index].ccid.bPINSupport = device_descriptor[52]; usbDevice[reader_index].ccid.dwMaxCCIDMessageLength = dw2i(device_descriptor, 44); usbDevice[reader_index].ccid.dwMaxIFSD = dw2i(device_descriptor, 28); usbDevice[reader_index].ccid.dwDefaultClock = dw2i(device_descriptor, 10); usbDevice[reader_index].ccid.dwMaxDataRate = dw2i(device_descriptor, 23); usbDevice[reader_index].ccid.bMaxSlotIndex = device_descriptor[4]; usbDevice[reader_index].ccid.bCurrentSlotIndex = 0; usbDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT; if (device_descriptor[27]) usbDevice[reader_index].ccid.arrayOfSupportedDataRates = get_data_rates(reader_index, config_desc, num); else { usbDevice[reader_index].ccid.arrayOfSupportedDataRates = NULL; DEBUG_INFO1("bNumDataRatesSupported is 0"); } usbDevice[reader_index].ccid.bInterfaceProtocol = usb_interface->altsetting->bInterfaceProtocol; usbDevice[reader_index].ccid.bNumEndpoints = usb_interface->altsetting->bNumEndpoints; usbDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT; usbDevice[reader_index].ccid.bVoltageSupport = device_descriptor[5]; usbDevice[reader_index].ccid.sIFD_serial_number = NULL; usbDevice[reader_index].ccid.gemalto_firmware_features = NULL; if (desc.iSerialNumber) { unsigned char serial[128]; int ret; ret = libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, serial, sizeof(serial)); if (ret > 0) usbDevice[reader_index].ccid.sIFD_serial_number = strdup((char *)serial); } usbDevice[reader_index].ccid.sIFD_iManufacturer = NULL; if (desc.iManufacturer) { unsigned char iManufacturer[128]; int ret; ret = libusb_get_string_descriptor_ascii(dev_handle, desc.iManufacturer, iManufacturer, sizeof(iManufacturer)); if (ret > 0) usbDevice[reader_index].ccid.sIFD_iManufacturer = strdup((char *)iManufacturer); } usbDevice[reader_index].ccid.IFD_bcdDevice = desc.bcdDevice; /* If this is a multislot reader, init the multislot stuff */ if (usbDevice[reader_index].ccid.bMaxSlotIndex) usbDevice[reader_index].multislot_extension = Multi_CreateFirstSlot(reader_index); else usbDevice[reader_index].multislot_extension = NULL; goto end; } } } end: if (usbDevice[reader_index].dev_handle == NULL) { /* free the libusb allocated list & devices */ libusb_free_device_list(devs, 1); #ifdef __APPLE__ /* give some time to libusb to detect the new USB devices on Mac OS X */ if (count_libusb > 0) { count_libusb--; DEBUG_INFO2("Wait after libusb: %d", count_libusb); nanosleep(&sleep_time, NULL); goto again_libusb; } #endif /* failed */ close_libusb_if_needed(); if (claim_failed) return STATUS_COMM_ERROR; DEBUG_INFO1("Device not found?"); return STATUS_NO_SUCH_DEVICE; } /* memorise the current reader_index so we can detect * a new OpenUSBByName on a multi slot reader */ previous_reader_index = reader_index; end2: /* free the libusb allocated list & devices */ libusb_free_device_list(devs, 1); end1: /* free bundle list */ bundleRelease(&plist); if (return_value != STATUS_SUCCESS) close_libusb_if_needed(); return return_value; } /* OpenUSBByName */
/*! \fn ipopt_initialization * * This function is used if ipopt is choosen for initialization. * * \param [ref] [data] * \param [ref] [initData] * \param [in] [useScaling] * * \author lochel */ int ipopt_initialization(DATA *data, INIT_DATA *initData, int useScaling) { int n = initData->nz; /* number of variables */ int m = (initData->nInitResiduals > initData->nz) ? 0 : initData->nInitResiduals; /* number of constraints */ double* x_L = NULL; /* lower bounds on x */ double* x_U = NULL; /* upper bounds on x */ double* g_L = NULL; /* lower bounds on g */ double* g_U = NULL; /* upper bounds on g */ double* x = NULL; /* starting point and solution vector */ double* mult_g = NULL; /* constraint multipliers at the solution */ double* mult_x_L = NULL; /* lower bound multipliers at the solution */ double* mult_x_U = NULL; /* upper bound multipliers at the solution */ double obj; /* objective value */ int i; /* generic counter */ int nele_jac = n*m; /* number of nonzeros in the Jacobian of the constraints */ int nele_hess = 0; /* number of nonzeros in the Hessian of the Lagrangian (lower or upper triangual part only) */ IpoptProblem nlp = NULL; /* ipopt-problem */ enum ApplicationReturnStatus status; /* solve return code */ IPOPT_DATA ipopt_data; ipopt_data.data = data; ipopt_data.initData = initData; ipopt_data.useScaling = useScaling; ipopt_data.useSymbolic = (initialAnalyticJacobianG(data) == 0 ? 1 : 0); if(ipopt_data.useSymbolic == 1) { nele_jac = data->simulationInfo.analyticJacobians[INDEX_JAC_G].sparsePattern.leadindex[n-1]; // sparse DEBUG_INFO1(LOG_INIT, "number of zeros in the Jacobian of the constraints (jac_g): %d", n*m-nele_jac); DEBUG_INFO1(LOG_INIT, "number of nonzeros in the Jacobian of the constraints (jac_g): %d", nele_jac); } /* allocate space for the variable bounds */ x_L = (double*)malloc(n * sizeof(double)); x_U = (double*)malloc(n * sizeof(double)); /* allocate space for the constraint bounds */ g_L = (double*)malloc(m * sizeof(double)); g_U = (double*)malloc(m * sizeof(double)); /* allocate space for the initial point */ x = (double*)malloc(n * sizeof(double)); /* set values of optimization variable bounds */ for(i=0; i<n; ++i) { x[i] = initData->start[i]; x_L[i] = initData->min[i]; x_U[i] = initData->max[i]; } /* set values of constraint bounds */ for(i=0; i<m; ++i) { g_L[i] = 0.0; g_U[i] = 0.0; } /* create the IpoptProblem */ nlp = CreateIpoptProblem( n, /* Number of optimization variables */ x_L, /* Lower bounds on variables */ x_U, /* Upper bounds on variables */ m, /* Number of constraints */ g_L, /* Lower bounds on constraints */ g_U, /* Upper bounds on constraints */ nele_jac, /* Number of non-zero elements in constraint Jacobian */ nele_hess, /* Number of non-zero elements in Hessian of Lagrangian */ 0, /* indexing style for iRow & jCol; 0 for C style, 1 for Fortran style */ &ipopt_f, /* Callback function for evaluating objective function */ &ipopt_g, /* Callback function for evaluating constraint functions */ &ipopt_grad_f, /* Callback function for evaluating gradient of objective function */ &ipopt_jac_g, /* Callback function for evaluating Jacobian of constraint functions */ &ipopt_h); /* Callback function for evaluating Hessian of Lagrangian function */ ASSERT(nlp, "creating of ipopt problem has failed"); /* We can free the memory now - the values for the bounds have been copied internally in CreateIpoptProblem */ free(x_L); free(x_U); free(g_L); free(g_U); /* Set some options. Note the following ones are only examples, they might not be suitable for your problem. */ AddIpoptNumOption(nlp, "tol", 1e-7); AddIpoptIntOption(nlp, "print_level", DEBUG_FLAG(LOG_INIT) ? 5 : 0); AddIpoptIntOption(nlp, "max_iter", 5000); AddIpoptStrOption(nlp, "mu_strategy", "adaptive"); AddIpoptStrOption(nlp, "hessian_approximation", "limited-memory"); /* allocate space to store the bound multipliers at the solution */ mult_g = (double*)malloc(m*sizeof(double)); mult_x_L = (double*)malloc(n*sizeof(double)); mult_x_U = (double*)malloc(n*sizeof(double)); /* solve the problem */ status = IpoptSolve( nlp, /* Problem that is to be optimized */ x, /* Input: Starting point; Output: Optimal solution */ NULL, /* Values of constraint at final point */ &obj, /* Final value of objective function */ mult_g, /* Final multipliers for constraints */ mult_x_L, /* Final multipliers for lower variable bounds */ mult_x_U, /* Final multipliers for upper variable bounds */ &ipopt_data); /* Pointer to user data */ setZ(initData, x); /* free allocated memory */ FreeIpoptProblem(nlp); free(x); free(mult_g); free(mult_x_L); free(mult_x_U); /* debug output */ DEBUG_INFO1(LOG_INIT, "ending with funcValue = %g", obj); DEBUG_INFO_AL(LOG_INIT, "| unfixed variables"); for(i=0; i<initData->nz; i++) DEBUG_INFO_AL4(LOG_INIT, "| | [%ld] %s = %g [scaled: %g]", i+1, initData->name[i], initData->z[i], initData->zScaled[i]); DEBUG_INFO_AL(LOG_INIT, "| residuals (> 0.001)"); for(i=0; i<data->modelData.nInitResiduals; i++) if(fabs(initData->initialResiduals[i]) > 1e-3) DEBUG_INFO_AL3(LOG_INIT, "| | [%ld] %g [scaled: %g]", i+1, initData->initialResiduals[i], (initData->residualScalingCoefficients[i] != 0.0) ? initData->initialResiduals[i]/initData->residualScalingCoefficients[i] : 0.0); if(status != Solve_Succeeded && status != Solved_To_Acceptable_Level) THROW("ipopt failed. see last warning. use [-lv LOG_INIT] for more output."); return (int)status; }