Reputation: 1496
I'm working on a printer, trying to read and write a contactless card.
This is the manual of the hardware and software I'm using: manual contactless
The process to ineract with the smart card (read and write in it), if I understood correctly, is:
Is that correct?
Points 1 and 2 works ok and return 0 (SCARD_S_SUCCESS), but I have problems with SCardTransmit.
If I want to read block 5 for example, this is the code I use:
SCARD_IO_REQUEST pioRecvPci;
DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
BYTE pbRecvBuffer[16];
BYTE pbSendBuffer[] = {(BYTE)0xFC, (BYTE)0xB0,(BYTE)0x05, (BYTE)0x00, (BYTE)0x00};
dwSendLength = sizeof(pbSendBuffer);
dwRecvLength = sizeof(pbRecvBuffer);
SCARD_IO_REQUEST pioSendPci;
pioSendPci.dwProtocol=SCARD_PROTOCOL_T0;
pioSendPci.cbPciLength= sizeof(pioSendPci);
ret = SCardTransmit(cardHandle, // SCard API
&pioSendPci,
pbSendBuffer, dwSendLength,
NULL, pbRecvBuffer, &dwRecvLength);
It returns an error code 22.
If I change SCARD_PROTOCOL_T0 to SCARD_PROTOCOL_T1, it seems to work (I don't know if pbRecvBuffer values are correct): pbRecvBuffer has 2 bytes with values: 6e 00 and ret = 0.
Have these values sense?
I read SCardTransmit api (SCardTransmit) and there I understand I have to use protocol T=0, does it mean I have to put SCARD_PROTOCOL_T0 to work? In that case, why I receive an errror 22? What I'm doing wrong?
If I want to write in block 5, I follow the same process: SCardEstablishContext, SCardConnect and SCardTransmit. I change pbSendBuffer to: {(BYTE)0xFC, (BYTE)0xD0,(BYTE)0x05, (BYTE)0x00, 0x10};, but I don't understand well where is the data, and what params I should put on SCardTransmit. Could you provide me an example of this?
Thank you very much!
Upvotes: 5
Views: 6627
Reputation: 830
I know this post is old but I had the same problem with error code 22 on the transmit function. The problem was related to the protocol used.
And actually the simplest is to use the return from the connect function to the card to determine which protocol structure to use with the transmit function.
I am therefore sharing the piece of code which works well and solves the problem of error code 22. Afterwards it remains to use the correct APDU command to obtain the correct result, depending on the card used. The example in the code should allow you to select the AID of a bank card.
hope this can help those who are facing the same error code 22
// Initialization
LONG responceCardFonc = 0;
SCARDCONTEXT contextManager;
LPCSTR readerName = "";
SCARDHANDLE identConnCard;
DWORD m_dwActiveProtocol;
SCARD_IO_REQUEST protocolStruct;
BYTE apduCommand[] = {0x00,0xA4,0x04,0x00,0x07,0xA0,0x00,0x00,0x00,0x03,0x10,0x10};
DWORD nbDataCommand = sizeof(apduCommand);
BYTE dataRecept[256];
DWORD nbDataRecept = sizeof(dataRecept);
QString stringDisplay;
// Determination Name Reader
readerName = "SCM Microsystems Inc. SCR331-DI Smart Card Reader 0";
// Creating a Context
responceCardFonc = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &contextManager);
// If Context Established
if(responceCardFonc==SCARD_S_SUCCESS)
{
// Card Connection
responceCardFonc = SCardConnectA(contextManager,readerName,SCARD_SHARE_SHARED,SCARD_PROTOCOL_Tx,&identConnCard,&m_dwActiveProtocol);
// If Card Connection Successful
if(responceCardFonc==SCARD_S_SUCCESS)
{
// Determining the Protocol Structure to Use
if(m_dwActiveProtocol==SCARD_PROTOCOL_T0) protocolStruct = *SCARD_PCI_T0;
if(m_dwActiveProtocol==SCARD_PROTOCOL_T1) protocolStruct = *SCARD_PCI_T1;
// Transmission to Card
responceCardFonc = SCardTransmit(identConnCard,&protocolStruct,apduCommand,nbDataCommand,NULL,dataRecept,&nbDataRecept);
// If Transmission Successful
if(responceCardFonc==SCARD_S_SUCCESS)
{
// Construct String to Display
for(int i=0;i<nbDataRecept;i++) stringDisplay += QString::number( dataRecept[i], 16 ).toUpper()+((i<nbDataRecept-1)?" ":"");
// Display String
qDebug() << stringDisplay;
}
// End - If Transmission Successful
else qDebug() << "Transmission Error - Error Code ["+QString::number(responceCardFonc)+"]";
}
// End - If Card Connection Successful
else qDebug() << "Card Connection Error on "+(QString)readerName+"\nError Code ["+QString::number(responceCardFonc)+"]";
}
// End - If Context Established
else qDebug() << "Context Creation Error"+QString("\n")+"Code Erreur ["+QString::number(responceCardFonc)+"]";
Of course this piece of code is integrated into a project correctly configured with the “winscard” APIs
Upvotes: 1
Reputation: 45
`enter code here` we must check protocol using switch case and transmit like :
switch ( m_dwAP )
{
case SCARD_PROTOCOL_T0:
dwErrorFlags = SCardTransmit(this->m_hCardHandle,
SCARD_PCI_T0,
rgbIN,
bIN,
NULL,
rgbOUTTra,
&uwBufferLen);
break;
case SCARD_PROTOCOL_T1:
dwErrorFlags = SCardTransmit(this->m_hCardHandle,
SCARD_PCI_T1,
rgbIN,
bIN,
NULL,
rgbOUTTra,
&uwBufferLen);
break;
}
here m_dwAP is active protocol.
Upvotes: -1