QHash<DRIVER_FEATURES,quint32> QPCSCReader::Private::features() { if(!featuresList.isEmpty()) return featuresList; DWORD size = 0; BYTE feature[256]; LONG rv = SC(Control, card, DWORD(CM_IOCTL_GET_FEATURE_REQUEST), nullptr, 0u, feature, DWORD(sizeof(feature)), &size); if(rv != SCARD_S_SUCCESS) return featuresList; for(unsigned char *p = feature; DWORD(p-feature) < size; ) { unsigned int tag = *p++, len = *p++, value = 0; for(unsigned int i = 0; i < len; ++i) value |= *p++ << 8 * i; featuresList[DRIVER_FEATURES(tag)] = qFromBigEndian<quint32>(value); } return featuresList; }
QPCSCReader::QPCSCReader( const QString &reader, QPCSC *parent ) : QObject( parent ) , d( new QPCSCReaderPrivate( parent->d ) ) { d->reader = reader.toUtf8(); d->state.szReader = d->reader.constData(); if( !d->updateState() ) return; /* Use DIRECT mode only if there is no card in the reader */ if( !isPresent() ) { #ifndef Q_OS_WIN /* Apple 10.5.7 and pcsc-lite previous to v1.5.5 do not support 0 as protocol identifier */ DWORD proto = SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1; #else DWORD proto = 0; #endif LONG rv = SCardConnect( d->d->context, d->state.szReader, SCARD_SHARE_DIRECT, proto, &d->card, &d->proto ); // Assume that there is a card in the reader in shared mode if direct communcation failed if( rv == LONG(SCARD_E_SHARING_VIOLATION) && !connect() ) return; } else if( !connect() ) return; d->friendlyName = d->attrib( SCARD_ATTR_DEVICE_FRIENDLY_NAME_A ); #if 0 qDebug() << "SCARD_ATTR_DEVICE_FRIENDLY_NAME:" << d->attrib( SCARD_ATTR_DEVICE_FRIENDLY_NAME_A ); qDebug() << "SCARD_ATTR_DEVICE_SYSTEM_NAME:" << d->attrib( SCARD_ATTR_DEVICE_SYSTEM_NAME_A ); qDebug() << "SCARD_ATTR_DEVICE_UNIT:" << d->attrib( SCARD_ATTR_DEVICE_UNIT ); qDebug() << "SCARD_ATTR_VENDOR_IFD_SERIAL_NO:" << d->attrib( SCARD_ATTR_VENDOR_IFD_SERIAL_NO ); qDebug() << "SCARD_ATTR_VENDOR_IFD_TYPE:" << d->attrib( SCARD_ATTR_VENDOR_IFD_TYPE ); qDebug() << "SCARD_ATTR_VENDOR_IFD_VERSION:" << d->attrib( SCARD_ATTR_VENDOR_IFD_VERSION ); qDebug() << "SCARD_ATTR_VENDOR_NAME:" << d->attrib( SCARD_ATTR_VENDOR_NAME ); #endif DWORD size = 0; BYTE feature[256]; LONG rv = SCardControl( d->card, CM_IOCTL_GET_FEATURE_REQUEST, 0, 0, feature, sizeof(feature), &size ); if( rv == SCARD_S_SUCCESS && (size % sizeof(PCSC_TLV_STRUCTURE)) == 0 ) { size /= sizeof(PCSC_TLV_STRUCTURE); PCSC_TLV_STRUCTURE *pcsc_tlv = (PCSC_TLV_STRUCTURE *)feature; for( DWORD i = 0; i < size; i++ ) d->ioctl[DRIVER_FEATURES(pcsc_tlv[i].tag)] = ntohl( pcsc_tlv[i].value ); } if( DWORD ioctl = d->ioctl.value(FEATURE_GET_TLV_PROPERTIES) ) { DWORD size = 0; BYTE recv[256]; rv = SCardControl( d->card, ioctl, 0, 0, recv, sizeof(recv), &size ); unsigned char *p = recv; while( DWORD(p-recv) < size ) { int tag = *p++, len = *p++, value = -1; switch( len ) { case 1: value = *p; break; case 2: value = *p + (*(p+1)<<8); break; case 4: value = *p + (*(p+1)<<8) + (*(p+2)<<16) + (*(p+3)<<24); break; default: break; } p += len; d->properties[Properties(tag)] = value; } } if( DWORD ioctl = d->ioctl.value(FEATURE_IFD_PIN_PROPERTIES) ) { DWORD size = 0; BYTE recv[256]; DWORD rv = SCardControl( d->card, ioctl, 0, 0, recv, sizeof(recv), &size ); if( rv == SCARD_S_SUCCESS ) { PIN_PROPERTIES_STRUCTURE *caps = (PIN_PROPERTIES_STRUCTURE *)recv; d->display = caps->wLcdLayout > 0; } } disconnect(); }