Created
May 13, 2013 13:18
-
-
Save yrezgui/5568249 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "StdAfx.h" | |
#include "CDirectUSB.h" | |
#include "CTools.h" | |
#ifdef _DEBUG | |
using namespace System::Diagnostics; | |
#endif | |
#define OUTPUT_SIZE 512 // Buffer TX size | |
// Device configuration | |
#define MY_CONFIG 1 | |
__declspec(align(2))struct CCID_MESSAGE | |
{ | |
BYTE bMessageType; | |
BYTE bLen1; | |
BYTE bLen2; | |
BYTE bLen3; | |
BYTE bLen4; | |
BYTE bSlot; | |
BYTE bSeq; | |
BYTE Msg1; | |
BYTE Msg2; | |
BYTE Msg3; | |
}; | |
CDirectUSB::~CDirectUSB() | |
{ | |
if (hdevice != NULL) | |
{ | |
ShutDownCard(); | |
usb_release_interface(hdevice, MyInterface); | |
usb_close(hdevice); | |
} | |
} | |
void CDirectUSB::Init(char* com_port) | |
{ | |
struct usb_bus *bus; | |
struct usb_device *dev; | |
String^ MY_VID; | |
String^ MY_PID; | |
String^ MY_NUM; | |
size_t iPosition; | |
int ret; | |
BYTE BufOUT[10]; | |
hdevice = NULL; | |
#ifdef _DEBUG | |
usb_set_debug(3); | |
#endif | |
strcpy(readername, com_port); | |
// Recherche VID | |
iPosition = strcspn(com_port,"/"); | |
if (iPosition==strlen(com_port)) | |
{ | |
CTools::LogEvent("No VID found in %s",readername); | |
throw new CReaderException(CREADER_ERROR_MESSAGE,"No VID found in %s",readername); | |
} | |
MY_VID = gcnew String(com_port); | |
MY_VID = MY_VID->Substring(0,iPosition); | |
com_port+=iPosition; | |
com_port++; | |
// Recherche PID | |
iPosition = strcspn(com_port,"/"); | |
if (iPosition==strlen(com_port)) | |
{ | |
CTools::LogEvent("No PID found in %s",readername); | |
throw new CReaderException(CREADER_ERROR_MESSAGE,"No PID found in %s",readername); | |
} | |
MY_PID = gcnew String(com_port); | |
MY_PID=MY_PID->Substring(0,iPosition); | |
com_port+=iPosition; | |
com_port++; | |
// Recherche Num | |
MY_NUM = gcnew String(com_port); | |
// initialize the library | |
usb_init(); | |
// find all busses | |
usb_find_busses(); | |
// find all connected devices | |
usb_find_devices(); | |
// Search for devices | |
for (bus = usb_get_busses(); bus; bus = bus->next) | |
{ | |
for (dev = bus->devices; dev; dev = dev->next) | |
{ | |
#ifdef _DEBUG | |
Debug::WriteLine("VID: " + Convert::ToString(dev->descriptor.idVendor,16) + " - PID: " + Convert::ToString(dev->descriptor.idProduct,16) + " - Num: " + Convert::ToString(dev->devnum,10)); | |
#endif | |
if ((Convert::ToString(dev->descriptor.idVendor,16) == MY_VID->ToLower()) && (Convert::ToString(dev->descriptor.idProduct,16) == MY_PID->ToLower()) && (Convert::ToString(dev->devnum,10) == MY_NUM->ToLower())) | |
{ | |
hdevice = usb_open(dev); | |
break; | |
} | |
} | |
if (hdevice != NULL) | |
break; | |
} | |
if (hdevice == NULL) | |
{ | |
CTools::LogEvent("%s Reader not found",readername); | |
throw new CReaderException(CREADER_ERROR_MESSAGE,"%s Reader not found",readername); | |
} | |
// Set Configuration | |
ret = usb_set_configuration(hdevice,MY_CONFIG); | |
if (ret < 0) | |
{ | |
usb_close(hdevice); | |
CTools::LogEvent("usb_set_configuration : %d",ret); | |
throw new CReaderException(CREADER_ERROR_MESSAGE,"%s Reader not found",readername); | |
} | |
// Claim Interface | |
MyInterface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber; | |
ret = usb_claim_interface(hdevice,MyInterface); | |
if (ret < 0) | |
{ | |
usb_close(hdevice); | |
CTools::LogEvent("usb_claim_interface : %d",ret); | |
throw new CReaderException(CREADER_ERROR_MESSAGE,"%s Reader not found",readername); | |
} | |
// get bulk endpoints numbers | |
for (int i=0;i<dev->config[0].interface[0].altsetting[0].bNumEndpoints;i++) | |
{ | |
// Bulk ? | |
if (dev->config[0].interface[0].altsetting[0].endpoint[i].bmAttributes == USB_ENDPOINT_TYPE_BULK) | |
{ | |
// In or Out EndPoint ? | |
if ((dev->config[0].interface[0].altsetting[0].endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_DIR_MASK) | |
EndPoint_IN = dev->config[0].interface[0].altsetting[0].endpoint[i].bEndpointAddress; | |
else | |
EndPoint_OUT = dev->config[0].interface[0].altsetting[0].endpoint[i].bEndpointAddress; | |
} | |
// interrupt ? | |
else if (dev->config[0].interface[0].altsetting[0].endpoint[i].bmAttributes == USB_ENDPOINT_TYPE_INTERRUPT) | |
{ | |
if ((dev->config[0].interface[0].altsetting[0].endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_DIR_MASK) | |
EndPoint_IT = dev->config[0].interface[0].altsetting[0].endpoint[i].bEndpointAddress; | |
} | |
} | |
// Xiring Teo (Omnikey) - RDR_to_PC_NotifySlotChange | |
if ((MY_VID->ToUpper() == "76B") && (MY_PID->ToUpper() == "A022")) | |
{ | |
// Il y a un TimeOut si pas de changement du status de la carte... | |
ret = usb_interrupt_read(hdevice,EndPoint_IT,(char *)BufOUT,sizeof(BufOUT),10); | |
} | |
} | |
BOOL CDirectUSB::IsCardPresent() | |
{ | |
DWORD LnRep; | |
BYTE pDataRep[OUTPUT_SIZE]; | |
WORD SW; | |
try | |
{ | |
ResetCard(&LnRep, pDataRep, &SW); | |
} | |
catch(CReaderException *e) | |
{ | |
#ifdef _DEBUG | |
Debug::WriteLine(e->GetErrorMessage()->ToString()); | |
#endif | |
return FALSE; | |
} | |
return TRUE;} | |
void CDirectUSB::ShutDownCard() | |
{ | |
int ret; | |
DWORD MyLenOut; | |
BYTE BufOUT[OUTPUT_SIZE]; | |
ret = ControlUSB((BYTE *)"\x63\x00\x00\x00\x00\x00\x00\x00\x00\x00",10,BufOUT,&MyLenOut); | |
if (ret<=0) | |
{ | |
throw new CReaderException(CREADER_CARD_ABSENT, "PC_to_RDR_IccPowerOff %d %s",ret,strerror(errno)); | |
} | |
} | |
void CDirectUSB::ResetCard(DWORD * pLnRep, BYTE * pDataRep, WORD * SW) | |
{ | |
int ret; | |
DWORD MyLenOut; | |
BYTE BufOUT[OUTPUT_SIZE]; | |
*pLnRep = 0; | |
*SW = 0; | |
// PC_to_RDR_IccPowerOff | |
ShutDownCard(); | |
// PC_to_RDR_IccPowerOn | |
ret = ControlUSB((BYTE *)"\x62\x00\x00\x00\x00\x00\x01\x00\x00\x00",10,BufOUT,&MyLenOut); | |
if (ret<=0) | |
{ | |
throw new CReaderException(CREADER_CARD_ABSENT, "PC_to_RDR_IccPowerOn %d %s",ret,strerror(errno)); | |
} | |
struct CCID_MESSAGE *ptr; | |
ptr = (struct CCID_MESSAGE *) BufOUT; | |
if (BufOUT[7] == 0) | |
{ | |
*pLnRep = ptr->bLen1; | |
memcpy(pDataRep,&BufOUT[10],ptr->bLen1); | |
*SW = pDataRep[*pLnRep-2]*256 + pDataRep[*pLnRep-1]; | |
} | |
else | |
throw new CReaderException(CREADER_CARD_ABSENT, "PC_to_RDR_IccPowerOn Status : %x", BufOUT[7]); | |
bSlot = 0; | |
bSeq = 1; | |
} | |
void CDirectUSB::Reset(DWORD * pLnRep, BYTE * pDataRep, WORD * SW) | |
{ | |
ResetCard(pLnRep, pDataRep, SW); | |
} | |
void CDirectUSB::InCard(BYTE CLA, BYTE INS, BYTE P1, BYTE P2, BYTE Lc, BYTE * pDataBuf, WORD ExpectedSW, WORD * SW) | |
{ | |
int ret; | |
DWORD MyLenIn=0; | |
DWORD MyLenOut; | |
BYTE BufIn[OUTPUT_SIZE]; | |
BYTE BufOUT[OUTPUT_SIZE]; | |
DWORD MyCmdLen; | |
*SW = 0; | |
memset(BufIn,0,sizeof(BufIn)); | |
MyCmdLen = 5 + Lc; | |
BufIn[MyLenIn++]=0x6F; // bMessageType | |
BufIn[MyLenIn++]=(BYTE)((MyCmdLen>>0) & 0xFF); // dwLength | |
BufIn[MyLenIn++]=(BYTE)((MyCmdLen>>8) & 0xFF); // dwLength | |
BufIn[MyLenIn++]=(BYTE)((MyCmdLen>>16) & 0xFF); // dwLength | |
BufIn[MyLenIn++]=(BYTE)((MyCmdLen>>24) & 0xFF); // dwLength | |
BufIn[MyLenIn++]=bSlot; // bSlot | |
BufIn[MyLenIn++]=++bSeq; // bSeq | |
BufIn[MyLenIn++]=0x00; // bBWI | |
BufIn[MyLenIn++]=0x00; // wLevelParameter | |
BufIn[MyLenIn++]=0x00; // wLevelParameter | |
BufIn[MyLenIn++]=CLA; // abData... | |
BufIn[MyLenIn++]=INS; | |
BufIn[MyLenIn++]=P1; | |
BufIn[MyLenIn++]=P2; | |
BufIn[MyLenIn++]=Lc; | |
memcpy(&BufIn[MyLenIn],pDataBuf,Lc); | |
MyLenIn+=Lc; | |
ret = ControlUSB(BufIn,MyLenIn,BufOUT,&MyLenOut); | |
if (ret<=0) | |
{ | |
throw new CReaderException(CREADER_ERROR_MESSAGE, "PC_to_RDR_XfrBlock %d %s",ret,strerror(errno)); | |
} | |
struct CCID_MESSAGE *ptr; | |
ptr = (struct CCID_MESSAGE *) BufOUT; | |
if (BufOUT[7] == 0) | |
{ | |
*SW = BufOUT[10]*256 + BufOUT[11]; | |
} | |
else | |
throw new CReaderException(CREADER_ERROR_MESSAGE, "PC_to_RDR_XfrBlock Status : %x", BufOUT[7]); | |
// Contrôle SW | |
if (ExpectedSW!=0) | |
{ | |
if (*SW!=ExpectedSW) | |
{ | |
throw new CReaderException(CREADER_CARD_WRONG_SW, "InCard SW Error: Expected SW=0x%04X, Returned SW=0x%04X",ExpectedSW,*SW); | |
} | |
} | |
} | |
void CDirectUSB::OutCard(BYTE CLA, BYTE INS, BYTE P1, BYTE P2, BYTE Le, DWORD * pLnRep, BYTE * pDataRep, WORD ExpectedSW, WORD * SW) | |
{ | |
int ret; | |
DWORD MyLenIn=0; | |
DWORD MyLenOut; | |
BYTE BufIn[OUTPUT_SIZE]; | |
BYTE BufOUT[OUTPUT_SIZE]; | |
DWORD MyCmdLen; | |
*pLnRep = 0; | |
*SW = 0; | |
memset(BufIn,0,sizeof(BufIn)); | |
MyCmdLen = 5; | |
BufIn[MyLenIn++]=0x6F; // bMessageType | |
BufIn[MyLenIn++]=(BYTE)((MyCmdLen>>0) & 0xFF); // dwLength | |
BufIn[MyLenIn++]=(BYTE)((MyCmdLen>>8) & 0xFF); // dwLength | |
BufIn[MyLenIn++]=(BYTE)((MyCmdLen>>16) & 0xFF); // dwLength | |
BufIn[MyLenIn++]=(BYTE)((MyCmdLen>>24) & 0xFF); // dwLength | |
BufIn[MyLenIn++]=bSlot; // bSlot | |
BufIn[MyLenIn++]=++bSeq; // bSeq | |
BufIn[MyLenIn++]=0x00; // bBWI | |
BufIn[MyLenIn++]=0x00; // wLevelParameter | |
BufIn[MyLenIn++]=0x00; // wLevelParameter | |
BufIn[MyLenIn++]=CLA; // abData... | |
BufIn[MyLenIn++]=INS; | |
BufIn[MyLenIn++]=P1; | |
BufIn[MyLenIn++]=P2; | |
BufIn[MyLenIn++]=Le; | |
ret = ControlUSB(BufIn,MyLenIn,BufOUT,&MyLenOut); | |
if (ret<=0) | |
{ | |
throw new CReaderException(CREADER_ERROR_MESSAGE, "PC_to_RDR_XfrBlock %d %s",ret,strerror(errno)); | |
} | |
struct CCID_MESSAGE *ptr; | |
ptr = (struct CCID_MESSAGE *) BufOUT; | |
if (BufOUT[7] == 0) | |
{ | |
*pLnRep = ptr->bLen1; | |
memcpy(pDataRep,&BufOUT[10],ptr->bLen1); | |
*SW = pDataRep[*pLnRep-2]*256 + pDataRep[*pLnRep-1]; | |
*pLnRep-=2; | |
} | |
else | |
throw new CReaderException(CREADER_ERROR_MESSAGE, "PC_to_RDR_XfrBlock Status : %x", BufOUT[7]); | |
// Contrôle SW | |
if (ExpectedSW!=0) | |
{ | |
if (*SW!=ExpectedSW) | |
{ | |
throw new CReaderException(CREADER_CARD_WRONG_SW, "OutCard SW Error: Expected SW=0x%04X, Returned SW=0x%04X",ExpectedSW,*SW); | |
} | |
} | |
} | |
void CDirectUSB::InOutCard(BYTE CLA, BYTE INS, BYTE P1, BYTE P2, BYTE Lc, BYTE * pDataBuf, BYTE Le, DWORD * pLnRep, BYTE * pDataRep, WORD ExpectedSW, WORD * SW) | |
{ | |
*pLnRep = 0; | |
*SW = 0; | |
// En ISO 7816 | |
InCard(CLA,INS,P1,P2,Lc,pDataBuf,0,SW); | |
if ((*SW==0x9000) || (*SW==0x6200) || ((*SW&0xFF00)==0x6100)) | |
{ | |
if ((*SW&0xFF00)==0x6100) | |
Le = (BYTE)(*SW&0x00FF); | |
OutCard(0x00,0xC0,0x00,0x00,Le,pLnRep,pDataRep,ExpectedSW,SW); | |
} | |
// Contrôle SW | |
if (ExpectedSW!=0) | |
{ | |
if (*SW!=ExpectedSW) | |
{ | |
throw new CReaderException(CREADER_CARD_WRONG_SW, "InOutCard SW Error: Expected SW=0x%04X, Returned SW=0x%04X",ExpectedSW,*SW); | |
} | |
} | |
} | |
//***************************************************************************** | |
//* ControlUSB | |
//***************************************************************************** | |
DWORD CDirectUSB::ControlUSB(BYTE *DataIn, DWORD LenDataIn, BYTE *DataOut, DWORD *LenOut) | |
{ | |
int ret; | |
*LenOut = 0; | |
ret = usb_bulk_write(hdevice,EndPoint_OUT,(char *)DataIn,LenDataIn,5000); | |
if (ret != LenDataIn) | |
{ | |
CTools::LogEvent("usb_bulk_write : %d %s",ret,strerror(errno)); | |
} | |
else | |
{ | |
ret = usb_bulk_read(hdevice,EndPoint_IN,(char *)DataOut,OUTPUT_SIZE,5000); | |
if (ret < 0) | |
{ | |
CTools::LogEvent("usb_bulk_read : %d %s",ret,strerror(errno)); | |
} | |
else | |
{ | |
*LenOut = ret; | |
} | |
} | |
return ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment