Hello, Writing a an USB smartcard driver, I choose to start a new thread instead of continue the last thread i ve initiated. I have written the configuration for the LPC2368. Here the configuration:
const BYTE USB_ConfigDescriptor[] = { /* Configuration 1 */ USB_CONFIGUARTION_DESC_SIZE, /* bDescriptorType */ USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL( /* wTotalLength */ USB_CONFIGUARTION_DESC_SIZE + USB_INTERFACE_DESC_SIZE + SMARTCARD_CLASS_DESC_SIZE + 3*USB_ENDPOINT_DESC_SIZE ), 0x01, /* bNumInterfaces */ 0x01, /* bConfigurationValue */ 0x03, /* iConfiguration */ /*USB_CONFIG_BUS_POWERED */ /* bmAttributes */ 0x80, USB_CONFIG_POWER_MA(100), /* bMaxPower */ /* Interface 0, Alternate Setting 0, HID Class */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x00, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ 0x03, /* bNumEndpoints */ 0x0b, /* bInterfaceClass */ //USB_DEVICE_CLASS_HUMAN_INTERFACE, /* bInterfaceClass */ 0x00, /* bInterfaceSubClass */ 0x00, /* bInterfaceProtocol */ 0x00, /* iInterface */ /* Smartcard Class Descriptor */ SMARTCARD_CLASS_DESC_SIZE, /* bLength */ SMARTCARD_SMARTCARD_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(0x0100), /* 1.00 */ /* bcdCCID */ 0x00, /* bMaxSlotIndex */ 0x07, /* bVoltageSupport: 5v, 3v and 1.8v */ 0x03,0x00,0x00,0x00, // dwProtocols: supports T=0 and T=1 0xF8,0x34,0x00,0x00, // dwDefaultClock: 13,56 Mhz (0x00000FA0) 0xF8,0x34,0x00,0x00, // dwMaximumClock: 13,56 Mhz (0x00000FA0) 0x00, // bNumClockSupported => no manual setting 0x00,0x2A,0x00,0x00, // dwDataRate: 10752 bps (0x00002A00) 0x08,0xF8,0x01,0x00, // dwMaxDataRate: 129032 bps (0x0001F808) 0x00, // bNumDataRatesSupported => no manual setting 0xFE,0x00,0x00,0x00, /* IFSD */ 0x00,0x00,0x00,0x00, /* Synchron Protocol */ 0x00,0x00,0x00,0x00, /* Mechanical Features, DWORD */ (0x04 | 0x08 | 0x10 | 0x40 | 0x02),(0x01 | 0x02),0x02,0x00, /* Features - Automatic activation - clk, baud rate, voltage :automatic - short APDU level exchange*/ // CCID can set ICC in clock stop mode - Automatic IFSD exchange(for T=1) 0x0F,0x01,0x00,0x00, /* Max CCID Message Length : Maximun block size + header (261 + 10)*/ 0xFF, /* Class Get Response */ 0XFF, /* Class enveloppe */ 0x00,0x00, /* wLayout */ 0x00, /* Pin Support */ 0x01, /* Max CCID Busy Slots */ /* Endpoint, INTERRUPT In */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x81, /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL(0x0008), /* wMaxPacketSize */ 0x18, /* 32ms */ /* bInterval */ /* Endpoint, SMART CARD Bulk In */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x82, /* bEndpointAddress */ USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ WBVAL(0x0040), /* wMaxPacketSize */ 0x00, /* 32ms */ /* bInterval */ /* Endpoint, SMART CARD BULK Out (from the host to the device) */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x02, /* bEndpointAddress */ USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ WBVAL(0x0040), /* wMaxPacketSize */ 0x00, /* 32ms */ /* bInterval */ /* Terminator */ 0 /* bLength */ };
The endpoints seem to be well configured since I can write {50, 03, 00, 00} on the Interrupt EP IN :
BYTE smcSlotStatusChange (void) { BYTE msg[4]; msg[0] = RDR_to_PC_NotifySlotChange; //bMessageType : 50 msg[1] = 0x03; //bmSlotICCstate 00000011 - slot 0 status changed and slot 0 current state is ICC present (manual that I linked page 56) EP1DataSnd.pData = msg; EP1DataSnd.Count = 4; USB_DataInStage1(); //write to the EP IN 0x81 return 0; }
The host respond successfully with the telegram {63, 00, 00, 00, 00, 00, 01, 00, 00, 00} (PC_to_RDR_ICCPowerOff).
Then I successfully sended the RDR_to_PC_Slotstatus in the Bulk IN (0x82) {81, 00, 00, 00, 00, 00, 01, 01, 00, 01}
The host respond successfully with the telegram {62, 00, 00, 00, 00, 00, 02, 00, 00, 00} (PC_to_RDR_ICCPowerON).
THEN I TRIED TO SEND A RDR_to_PC_Datablock but the host doesn't catch it! I tried with the telegramms: BYTE FirstDataBlock[14] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xXX, 0x40, 0xFE, 0x00}; // BYTE FirstDataBlock[14] = {0x80, 0x04, 0x00, 0x00, 0x00, 0xXX, 0xFF, 0x40, 0xFE, 0x00, 0x03, 0x00, 0x00,0x00};
where 0xXX ist the last BULK-OUT received bSeq BYTE but the Host does'nt take it! I can't see it on the USBLYzer!
Has anybody an Idea about it?
Here the protocol functions:
void smcDispatchMessage() { BYTE ErrorCode; //Initialize the pointers UsbMessageBuffer = EP2DataRcv.pData; UsbInMessageBuffer = EP2DataRcv.pData; switch (*UsbMessageBuffer) { case PC_to_RDR_IccPowerOn: //0x62 ErrorCode = PC_to_RDR_IccPowerON(); smcDataBlock(ErrorCode, FirstDataBlock); break; case PC_to_RDR_IccPowerOff: //0x63 ErrorCode = PC_to_RDR_IccPowerOFF(); smcSlotStatus(ErrorCode, IccPowerON); break; } } Thanks in advance!
Hello, Thanks for replying Tsuneo
Looking in the sniffer log closely, you'll be aware that URBs (USB Request Blocks) are shown in a pair. In some sniffer, the pair is called down and up. If you see the first one, but don't see the second one, the device doesn't put the packet into the IN EP. It suggests an error on the firmware side.
Well this is the case for me since the "down" URb says: "URB Bulk or Interrupt Transfer issued" and then the next URB says "URB Bulk or Interrupt Transfer failed"
This is the and the (I assume) unique tranfer failure I get from the USBlyzer! URB status is: "USBD_STATUS_BUFFER_OVERRUN", It a bit weird because its about 4 byte data even though Im trying to send at least 10 bytes data on the Bulk IN EP.
Send back just 2 byte of RDR_to_PC_NotifySlotChange message, {0x50, 0x03} I changed it but still get the same problem: BYTE FirstDataBlock[10] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, bSeqByte, 0x40, 0xFE, 0x00}; cannot be sent!
Here the definitions of USB_DataInStage1() and USB_DataInStage2():
void USB_DataInStage1 (void) { DWORD cnt; /*if the number of bytes is more than 1024, then cut it */ if (EP1DataSnd.Count > USB_MAX_PACKET0) { cnt = USB_MAX_PACKET0; } else { cnt = EP1DataSnd.Count; } cnt = USB_WriteEP(0x81, EP1DataSnd.pData,cnt); EP1DataSnd.pData += cnt; //increment the pointer to the datas to be transfered EP1DataSnd.Count -= cnt; //actualize the number of datas left to be transfered } void USB_DataInStage2 (void) { BYTE cnt; if (EP2DataSnd.Count > USB_MAX_PACKET0) { cnt = USB_MAX_PACKET0; } else { cnt = EP2DataSnd.Count; } cnt = USB_WriteEP(0x82, EP2DataSnd.pData,cnt); /********* this is for debugging purpose ************/ if ((*EP2DataSnd.pData == 0x80)&&(cnt>1)) { Result[0] = *(EP2DataSnd.pData); Result[1] = *(EP2DataSnd.pData+1); Result[2] = *(EP2DataSnd.pData+2); Result[3] = *(EP2DataSnd.pData+3); Result[4] = *(EP2DataSnd.pData+4); Result[5] = *(EP2DataSnd.pData+5); Result[6] = *(EP2DataSnd.pData+6); Result[7] = *(EP2DataSnd.pData+7); Result[8] = *(EP2DataSnd.pData+8); Result[9] = *(EP2DataSnd.pData+9);; set_cursor (0, 1); lcd_print ("RDR_to_PC_DataBlock sent"); } /****************** ***********************/ EP2DataSnd.pData += cnt; EP2DataSnd.Count -= cnt; }
Well I can't see any bug in these function definitions. By debbugging, I could see the datas to be sent in the Result array (USB_DataInStage2) and Im struggling to see where is the problem in the code!
I change the USB_writeEP as a SWI just exactly according to your recommendations in http://www.keil.com/forum/docs/thread15613.asp , IN VAIN!
I assume there is no problem in the bIntervals of the EP Configuration since the Full-Speed mode simply ignores these points. See www.usb.org/.../DWG_Smart-Card_CCID_Rev110.pdf page 21
Do you have any Idea on how to fix the problem?
Thank you very much
Oh sorry, USB_MAX_PACKET0 ist of course 64 (as configured) and not 1024. I slightly changed USB_DataInStage2 for Data greater as 64:
void USB_DataInStage2 (void) { BYTE cnt; BYTE temp; temp = EP2DataSnd.Count; if (EP2DataSnd.Count > USB_MAX_PACKET0) { while(temp>USB_MAX_PACKET0) { temp-=USB_MAX_PACKET0; cnt = USB_WriteEP(0x82, EP2DataSnd.pData,USB_MAX_PACKET0); EP2DataSnd.pData += cnt; } cnt = USB_WriteEP(0x82, EP2DataSnd.pData,temp); } else { cnt = EP2DataSnd.Count; cnt = USB_WriteEP(0x82, EP2DataSnd.pData,cnt); } /********* this is for debugging purpose ************/ if ((*EP2DataSnd.pData == 0x80)&&(cnt>1)) { Result[0] = *(EP2DataSnd.pData); Result[1] = *(EP2DataSnd.pData+1); Result[2] = *(EP2DataSnd.pData+2); Result[3] = *(EP2DataSnd.pData+3); Result[4] = *(EP2DataSnd.pData+4); Result[5] = *(EP2DataSnd.pData+5); Result[6] = *(EP2DataSnd.pData+6); Result[7] = *(EP2DataSnd.pData+7); Result[8] = *(EP2DataSnd.pData+8); Result[9] = *(EP2DataSnd.pData+9);; set_cursor (0, 1); lcd_print ("RDR_to_PC_DataBlock sent"); } /****************** reinitialyze EP2DataSnd.Count ***********************/ EP2DataSnd.Count = 0; }
and here the while loop in the main.c:
while (1) // Loop forever { ///*****************USB****************** if (EP2DataSnd.Count>2) USB_DataInStage2(); smcDispatchMessage(); }
Well the problem still remains...