This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Smartcard USB application

Hello,
Im writing a usb communication tool on the LPC2368 for smartcard devices. I still don't get any communication between the host and the smartcard device for couple of weeks know. It seems like the program is be missing something and i dont know what.

Do you Know where I can find any smartcard USB application for arm7 microcontroller?

Can anybody help me on it? If necessary I will post the fully commented code that I have written.

Thanks in advance

Parents
  • And here the header file that defines the macros

    
    #define SMARTCARDSLOTS                                          0x00
    #define SMARTCARDVOLTAGESUPPORTS                        0x07
    #define SMARTCARDCONTACTLESS_PROT                       0x00010000
    #define SMARTCARDICC_DEFAULTCLOCK                       0x000034F8 //0x000034C2
    #define SMARTCARDICC_MAXCLOCK                           0x401F0000 //0x000034C2 //
    #define SMARTCARDCCID_NUMcLOCKsUPPORTED         0x04 //0x00 //0x04 /* */
    #define SMARTCARDICC_DATARATE                           0x002A0000 //0x00019E10
    #define SMARTCARDICC_MAXDATARATE                        0xE74C0600 //0x00030D40 /* If the value is 00h, all data rates between the default data rate dwDataRate and the maximum data rate dwMaxDataRate are supported. */
    #define SMARTCARDICC_NUMdATARATEsUPPORTED       0x00 //0x6A  //0x00
    #define SMARTCARD_IFSD                                          0xFE000000 //0x00000000
    #define SMARTCARD_SyncProt                                      0x07000000
    #define SMARTCARDICC_MECHANICAL                         0x00000111
    #define SMARTCARDICC_FEATURES                       0xB2070200 //(0x00000002 | 0x00000004 | 0x00100000) //
    #define SMARTCARDCCID_MessageLength                     0x0F010000
    #define SMARTCARD_ClassGetResponse                      0xFF
    #define SMARTCARD_ClassEnvelope                         0xFF
    #define SMARTCARD_Layout                                        0x0000
    #define SMARTCARD_bPINSupport                           0x00
    #define SMARTCARD_bMaxCCIDBusySlots                     0x01
    #define SMARTCARD_Input(x)                      0x81,x
    
    /* SMARTCARD Request Codes */
    #define SMARTCARD_REQUEST_ABORT                         0x01
    #define SMARTCARD_REQUEST_GET_CLOCKFREQUENCIES  0x02
    #define SMARTCARD_REQUEST_GET_DATARATES         0x03
    #define SMARTCARD_REQUEST_SET_REPORT            0x09
    #define SMARTCARD_REQUEST_SET_IDLE              0x0A
    #define SMARTCARD_REQUEST_SET_PROTOCOL          0x0B
    
    

    And the defines in usbcfg.h:

    #define USB_POWER_EVENT     0
    #define USB_RESET_EVENT     1
    #define USB_SUSPEND_EVENT   0
    #define USB_RESUME_EVENT    0
    #define USB_WAKEUP_EVENT    0
    #define USB_SOF_EVENT       0
    #define USB_ERROR_EVENT     0
    #define USB_EP_EVENT        0x003B /*111011 - 0,1,3,4,5 activated */
    #define USB_CONFIGURE_EVENT 1
    #define USB_INTERFACE_EVENT 0
    #define USB_FEATURE_EVENT   0
    

    and the Interrupt service routine:

    void EINT0_ISR (void) __irq
    {
            EXTINT = EINT0;                 // clear interrupt
            /*---------------------------------------------- */
    
            if(!smcSlotStatusChange(0)) /*the function that writes bytes to the successfully configured Interrupt endpoint */
                    boolInterrupt0 = 1; //This will enable the LEDs on the board to blink
            else
                    boolInterrupt0 = 0;
    
            if (boolInterrupt0)
            {
                    if((FIO2PIN&0xFF)!=0x55)
                            FIO2SET=0x55;
                    else
                            FIO2CLR=0x55;
            }
    
            //----------------------------------------
            VICVectAddr = 0;                /* Acknowledge Interrupt */
    }
    
    BYTE smcSlotStatusChange (BYTE cnt)
    {
            BYTE msg[4];
            memset(msg, 0, 4);
            msg[0] = RDR_to_PC_NotifySlotChange; //bMessageType
            msg[1] = 0x03;  //bmSlotICCstate
            cnt = 4;
            /*Now write to the interrupt Endpoint*/
            cnt = USB_WriteEP(0x83, msg,cnt);
            if (cnt>0)
                    return 0;
    
            return 1;
    }
    

    Is there anything special to program in usbcore.c in the routines that fetches the configurations?? Or anywhere else?

    Has anybody an Idea on this matter?

    Thank you very much Tsuneo,

    Thanks in Advance

Reply
  • And here the header file that defines the macros

    
    #define SMARTCARDSLOTS                                          0x00
    #define SMARTCARDVOLTAGESUPPORTS                        0x07
    #define SMARTCARDCONTACTLESS_PROT                       0x00010000
    #define SMARTCARDICC_DEFAULTCLOCK                       0x000034F8 //0x000034C2
    #define SMARTCARDICC_MAXCLOCK                           0x401F0000 //0x000034C2 //
    #define SMARTCARDCCID_NUMcLOCKsUPPORTED         0x04 //0x00 //0x04 /* */
    #define SMARTCARDICC_DATARATE                           0x002A0000 //0x00019E10
    #define SMARTCARDICC_MAXDATARATE                        0xE74C0600 //0x00030D40 /* If the value is 00h, all data rates between the default data rate dwDataRate and the maximum data rate dwMaxDataRate are supported. */
    #define SMARTCARDICC_NUMdATARATEsUPPORTED       0x00 //0x6A  //0x00
    #define SMARTCARD_IFSD                                          0xFE000000 //0x00000000
    #define SMARTCARD_SyncProt                                      0x07000000
    #define SMARTCARDICC_MECHANICAL                         0x00000111
    #define SMARTCARDICC_FEATURES                       0xB2070200 //(0x00000002 | 0x00000004 | 0x00100000) //
    #define SMARTCARDCCID_MessageLength                     0x0F010000
    #define SMARTCARD_ClassGetResponse                      0xFF
    #define SMARTCARD_ClassEnvelope                         0xFF
    #define SMARTCARD_Layout                                        0x0000
    #define SMARTCARD_bPINSupport                           0x00
    #define SMARTCARD_bMaxCCIDBusySlots                     0x01
    #define SMARTCARD_Input(x)                      0x81,x
    
    /* SMARTCARD Request Codes */
    #define SMARTCARD_REQUEST_ABORT                         0x01
    #define SMARTCARD_REQUEST_GET_CLOCKFREQUENCIES  0x02
    #define SMARTCARD_REQUEST_GET_DATARATES         0x03
    #define SMARTCARD_REQUEST_SET_REPORT            0x09
    #define SMARTCARD_REQUEST_SET_IDLE              0x0A
    #define SMARTCARD_REQUEST_SET_PROTOCOL          0x0B
    
    

    And the defines in usbcfg.h:

    #define USB_POWER_EVENT     0
    #define USB_RESET_EVENT     1
    #define USB_SUSPEND_EVENT   0
    #define USB_RESUME_EVENT    0
    #define USB_WAKEUP_EVENT    0
    #define USB_SOF_EVENT       0
    #define USB_ERROR_EVENT     0
    #define USB_EP_EVENT        0x003B /*111011 - 0,1,3,4,5 activated */
    #define USB_CONFIGURE_EVENT 1
    #define USB_INTERFACE_EVENT 0
    #define USB_FEATURE_EVENT   0
    

    and the Interrupt service routine:

    void EINT0_ISR (void) __irq
    {
            EXTINT = EINT0;                 // clear interrupt
            /*---------------------------------------------- */
    
            if(!smcSlotStatusChange(0)) /*the function that writes bytes to the successfully configured Interrupt endpoint */
                    boolInterrupt0 = 1; //This will enable the LEDs on the board to blink
            else
                    boolInterrupt0 = 0;
    
            if (boolInterrupt0)
            {
                    if((FIO2PIN&0xFF)!=0x55)
                            FIO2SET=0x55;
                    else
                            FIO2CLR=0x55;
            }
    
            //----------------------------------------
            VICVectAddr = 0;                /* Acknowledge Interrupt */
    }
    
    BYTE smcSlotStatusChange (BYTE cnt)
    {
            BYTE msg[4];
            memset(msg, 0, 4);
            msg[0] = RDR_to_PC_NotifySlotChange; //bMessageType
            msg[1] = 0x03;  //bmSlotICCstate
            cnt = 4;
            /*Now write to the interrupt Endpoint*/
            cnt = USB_WriteEP(0x83, msg,cnt);
            if (cnt>0)
                    return 0;
    
            return 1;
    }
    

    Is there anything special to program in usbcore.c in the routines that fetches the configurations?? Or anywhere else?

    Has anybody an Idea on this matter?

    Thank you very much Tsuneo,

    Thanks in Advance

Children
  • With quick look,

    Endpoint address

    You've assigned improper EP addresses.
    LPC2368 limits the type of each endpoint, interrupt, bulk and isoc.
    For example, an interrupt IN EP is assigned to 1, 4, 7, 10, 13

    See this section of the user's manual,
    www.standardics.nxp.com/.../user.manual.lpc23xx.pdf
    Chapter 13, 5. Fixed endpoint configuration

    This is one of candidates for change,
    Interrupt IN: 0x83 <-- 0x81
    bulk IN: 0x84 <--0x82
    bulk OUT: 0x05 <--0x02

    When you move the EP addresses, modify setups on usbcfg.h, too.
    Of course, you'll change all references of endpoints address on your code.

    INF file

    Windows has in-box CCID class driver, but no default INF file.
    Did you supply an INF (INX) file for your device?

    Tsuneo

  • In closer look,

    a) Remote wakeup
    You enable remote wake up in the config descriptor.
    Do you support it properly on your firmware?

    /* Configuration 1 */
      /*USB_CONFIG_BUS_POWERED */       /* bmAttributes */
      0xA0,                                                <-- remote wakeup enabled
    

    b) Smartcard Class Descriptor

    What is WBVAL1 definition?
    Post the definition.

    The #defines values used for WBVAL1() are messed up.

             /* Smartcard Class Descriptor */
      WBVAL1(SMARTCARDCONTACTLESS_PROT),    /* dwProtocols */
      WBVAL1(SMARTCARDICC_DEFAULTCLOCK ),   /* dwDefaultClock */
      WBVAL1(SMARTCARDICC_MAXCLOCK),        /* dwMaximumClock */
    
    #define SMARTCARDCONTACTLESS_PROT                       0x00010000   <--- 0x00000001 ?
    #define SMARTCARDICC_DEFAULTCLOCK                       0x000034F8   = 13.56 MHz
    #define SMARTCARDICC_MAXDATARATE                        0xE74C0600   = 3.880519168 Tera Hz???
    ...
    

    Tsuneo

  • > Windows has in-box CCID class driver, but no default INF file.

    Ah, sorry
    INF file for CCID class driver (usbccid.inf) is supplied with the device driver file (usbccid.sys) over Windows Update, when we select "search internet" option in the "New Hardware" dialog.

    Microsoft Class Drivers for USB CCID Smart Cards
    www.microsoft.com/.../USB_CCID.mspx

    To confirm that you have the latest USB CCID driver, the following components must be included in your system:

    INF (this INF will be an OEM*.inf file if obtained from Windows Update):
    - DriverVer: 04/01/2003,5.2.3790.0
    - ID match: USB\Class_0B&SubClass_00
    Driver file (Usbccid.sys):
    - File Version: 5.2.3788.0

    Driver or INF version information that is newer (later date or higher version number) than the information listed above is acceptable.

    On my PC, it was renamed to OEMxx.inf. So, I've thought it comes from other vendor.

    Tsuneo

  • Hello Tsuneo,
    thanks for your quick reply.
    Yes I have verified the reader is bus-powered!
    Here the definition of WBVAL1:

    #define WBVAL1(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF) //DWORD to 4 bytes
    

    Talking about the endpoint configurations, I leaned on that fixed endpoint configuration of the LPC23xx manual but I refered to the physical Endpoints (second column) instead of the logical ones. Hmmm. I will try now to follow your recommendations and reconfigure the endpoints accordingly. I will let you know throughout the day whether any change happens.
    Here is the definitions of the endpoints events. I wondered why the Programm doesnt reach the configured endpoints!

    /*
     *  USB Endpoint 3 Event Callback
     *   Called automatically on USB Endpoint 3 Event
     *    Parameter:       event
     */
     void USB_EndPoint3 (DWORD event) {
            Biib(50);
      switch (event) {
        case USB_EVT_IN:
    
                    USB_DataInStage3();
    
          break;
            case USB_EVT_OUT:
    
                    USB_DataOutStage3();
    
                    break;
      }
    }
    
    void USB_DataInStage3 (void) {
      DWORD cnt;
    
      if (EP1DataSnd.Count > USB_MAX_PACKET0) {
        cnt = USB_MAX_PACKET0;
      } else {
        cnt = EP1DataSnd.Count;
      }
    
      cnt = USB_WriteEP(0x83, EP1DataSnd.pData,cnt);
      EP1DataSnd.pData += cnt;
      EP1DataSnd.Count -= cnt;
    }
    
    void USB_DataOutStage3 (void) {
      DWORD cnt;
      if(EP1DataRcv.Count==0)
        EP1DataRcv.pData = (unsigned char*)RXBuffer;
    
      cnt = USB_ReadEP(0x03, EP1DataRcv.pData);
      EP1DataRcv.pData += cnt;
      EP1DataRcv.Count += cnt;
    
      if(EP1DataRcv.Count >= RECEIVE_BUFFER_MAX)
      {
                    EP1DataRcv.pData = (unsigned char*)RXBuffer;
                    EP1DataRcv.Count = 0;
      }
    }
    
    
    /*
     *  USB Endpoint 4 Event Callback
     *   Called automatically on USB Endpoint 4 Event
     *    Parameter:       event
     */
     void USB_DataInStage4 (void) {
      DWORD cnt;
    
      if (EP1DataSnd.Count > USB_MAX_PACKET0) {
        cnt = USB_MAX_PACKET0;
      } else {
        cnt = EP1DataSnd.Count;
      }
    
      cnt = USB_WriteEP(0x84, EP1DataSnd.pData,cnt);
      EP1DataSnd.pData += cnt;
      EP1DataSnd.Count -= cnt;
    }
    
    void USB_EndPoint4 (DWORD event) {
    Biib(50);
     USB_DataInStage4();
    }
    
    
    /*
     *  USB Endpoint 5 Event Callback
     *   Called automatically on USB Endpoint 5 Event
     *    Parameter:       event
     */
    
     /* Receive the datas from the Host (Bulk-Out Endpoint, 0x05) */
     BYTE USB_DataOutStage5 (void) {
      DWORD cnt;
      if(EP1DataRcv.Count==0)
        EP1DataRcv.pData = (unsigned char*)RXBuffer;
    
      cnt = USB_ReadEP(0x05, EP1DataRcv.pData);
      if (cnt > 0)
      {
            EP1DataRcv.pData += cnt;
            EP1DataRcv.Count += cnt;
            /* if(EP1DataRcv.Count >= RECEIVE_BUFFER_MAX)
              {
                    EP1DataRcv.pData = (unsigned char*)RXBuffer;
                    EP1DataRcv.Count = 0;
              }      */
              return 0;
      }
      return 1;
    }
    
    
    void USB_EndPoint5 (DWORD event) {
    Biib(50);
    //if (event == USB_EVT_OUT)
            if (!USB_DataOutStage5())
                    return;
    }
    
    BYTE USBEndP5 (void) {
            if (!USB_DataOutStage5())
                    return 0;
            else
                    return 1;
    }
    

    Im very grateful about the fact that you spend your time trying to release me from a problem that seems to try to bring me down!
    Thanks a lot Tsuneo!!

  •  #define SMARTCARDCONTACTLESS_PROT                       0x00010000
    


    This is for contactless protocol.
    see www.pcscworkgroup.com/.../pcsc3_v2.01.09.pdf page 17.

    Now I will try 0x00000003 (for T=0 and T=1)

    Thanks

  • Hello Tsuneo,

    You were right, the main problem was the endpoint configuration.I have changed it to 0x81(Interrupt IN), 0x02(Bulk OUT) and 0x82(Bulk IN). besides that, I changed in usbcfg.h:

    #define USB_EP_EVENT        0x0007
    


    The Interrupt IN seems to work, since I can catch the IN message in the USB Sniffer but the BULK endpoints don't work!! The program does'nt reach the Bulk interrupt Events in usbuser.c!

    void USB_EndPoint2 (DWORD event) {
    
    Biib(250);
      switch (event) {
    
        case USB_EVT_IN:
                    USB_DataInStage2();
          break;
    
            case USB_EVT_OUT:
                    USB_DataOutStage2();
                    break;
      }
    }
    
    void USB_DataInStage2 (void) {
      DWORD cnt;
    
      if (EP2DataSnd.Count > USB_MAX_PACKET0) {
        cnt = USB_MAX_PACKET0;
      } else {
        cnt = EP2DataSnd.Count;
      }
    
      cnt = USB_WriteEP(0x82, EP2DataSnd.pData,cnt);
      EP2DataSnd.pData += cnt;
      EP2DataSnd.Count -= cnt;
    }
    
    /* Receive the datas from the Host (Bulk-Out Endpoint, 0x02) */
    void USB_DataOutStage2 (void) {
      DWORD cnt;
      if(EP2DataRcv.Count==0)
        EP2DataRcv.pData = (unsigned char*)RXBuffer;
    
      cnt = USB_ReadEP(0x02, EP2DataRcv.pData);
      EP2DataRcv.pData += cnt;
      EP2DataRcv.Count += cnt;
    
      if(EP2DataRcv.Count >= RECEIVE_BUFFER_MAX)
      {
                    EP2DataRcv.pData = (unsigned char*)RXBuffer;
                    EP2DataRcv.Count = 0;
      }
    }
    


    Do you have any idea about how to fix it?

    Thanks a lot

  • > The Interrupt IN seems to work, since I can catch the IN message in the USB Sniffer but the BULK endpoints don't work!!

    The interrupt IN EP is always polled by host to notify event from the device.
    When you write some data to the EP, it is always sent to host at the next interval.

    Bulk IN/OUT EP are used to exchange command - response.
    Until host sends a command to the device over bulk OUT EP, no data (response) is transfered from bulk IN EP.

    I recommend you to establish the descriptor first.
    Wrong parameters on the descriptor may block the operation over bulk OUT/IN.



    > Yes I have verified the reader is bus-powered!

    I pointed out REMOTE WAKEUP bit, not the self/bus-powered bit.
    As you set remote-wakeup bit to 1, host will send Set_Feature( DEVICE_REMOTE_WAKEUP ) and Clear_Feature( DEVICE_REMOTE_WAKEUP ) requests.
    When your device fails to handle these requests, the connection is cut off.

    If you don't use remote wakeup on your device, change bmAttributes field of the config descriptor from 0xA0 to 0x80

    #define WBVAL1(x) ((x >> 24) & 0xFF), ((x >> 16) & 0xFF), ((x >> 8) & 0xFF), (x & 0xFF) //DWORD to 4 bytes
    

    The endian is reversed. USB takes little endian - low-byte first
    Fix it, as follows,

    #define WBVAL1(x) (x & 0xFF), ((x >> 8) & 0xFF), ((x >> 16) & 0xFF), ((x >> 24) & 0xFF) //DWORD to 4 bytes
    

    The #defines for Smartcard Class Descriptor are messed up, anyway.
    As the start point, copy the values from the CCID example of ST micro.
    After realizing more about this class, modify it as you like.

    Tsuneo