home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / usbd0906.zip / usb_20020906.zip / usbcalls / samples / Cardreader / ifdhandler.cpp < prev    next >
C/C++ Source or Header  |  2001-11-13  |  21KB  |  622 lines

  1. /*****************************************************************
  2. /
  3. / File   :   ifdhandler.c
  4. / Authors :   David Corcoran <corcoran@linuxnet.com>
  5. /             Jean-Luc Giraud <jl.giraud@free.fr>
  6. / Date   :   April 9, 2001
  7. / Purpose:   This provides reader specific low-level calls
  8. /            for the GemPC430 (USB) of Gemplus. The function
  9. /            stubs were written by D. Corcoran, the 430
  10. /            specific code was added by JL Giraud.
  11. /            This module implements the command level of GemCore
  12. /            See http://www.linuxnet.com for more information.
  13. / License:   See file LICENSE & COPYING
  14. /
  15. ******************************************************************/
  16.  
  17. #include <pcscdefines.h>
  18. #include <ifdhandler.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include "usbserial.h"
  22. #include "GemCore.h"
  23.  
  24. // Use this define to log the calls to the various functions
  25. //#define GEMPC430_DEBUG 1
  26.  
  27. #define log_function(x) fprintf(stderr,(x))
  28.  
  29. // Command descriptions
  30. // Reader mode without TLP support
  31. const UCHAR pcSetModeROSNOTLP[] = {0x01, 0x00, 0x01};
  32. // Slot specific (GemCore can manage 2 card slots)
  33. const UCHAR pcPowerUp[MAX_SLOT_NB]      = {0x12, 0x1A};
  34. const UCHAR pcPowerDown[MAX_SLOT_NB]    = {0x11, 0x19};
  35. const UCHAR pcISOOutput[MAX_SLOT_NB]    = {0x13, 0x1B};
  36. const UCHAR pcISOInput[MAX_SLOT_NB]     = {0x14, 0x1C};
  37. const UCHAR pcEchAPDU[MAX_SLOT_NB]      = {0x15, 0x1D};
  38. const UCHAR pcCardStatus[MAX_SLOT_NB]   = {0x17, 0x1F};
  39.  
  40. // Array of structures to hold the ATR of each slot
  41. static GCoreDesc pgSlots[MAX_SLOT_NB];
  42.  
  43. RESPONSECODE gempc430_status_processing(DWORD nlength, PDWORD RxLength,
  44.                                         PUCHAR pcbuffer, PUCHAR RxBuffer);
  45.  
  46.  
  47.  
  48. RESPONSECODE IFDHCreateChannel ( DWORD Lun, DWORD Channel ) {
  49.  
  50.   /* Lun - Logical Unit Number, use this for multiple card slots
  51.      or multiple readers. 0xXXXXYYYY -  XXXX multiple readers,
  52.      YYYY multiple slots. The resource manager will set these
  53.      automatically.  By default the resource manager loads a new
  54.      instance of the driver so if your reader does not have more than
  55.      one smartcard slot then ignore the Lun in all the functions.
  56.      Future versions of PC/SC might support loading multiple readers
  57.      through one instance of the driver in which XXXX would be important
  58.      to implement if you want this.
  59.   */
  60.  
  61.   /* Channel - Channel ID.  This is denoted by the following:
  62.      0x000001 - /dev/pcsc/1
  63.      0x000002 - /dev/pcsc/2
  64.      0x000003 - /dev/pcsc/3
  65.  
  66.      USB readers may choose to ignore this parameter and query
  67.      the bus for the particular reader.
  68.   */
  69.  
  70.   /* This function is required to open a communications channel to the
  71.      port listed by Channel.  For example, the first serial reader on COM1 would
  72.      link to /dev/pcsc/1 which would be a sym link to /dev/ttyS0 on some machines
  73.      This is used to help with intermachine independance.
  74.  
  75.      Once the channel is opened the reader must be in a state in which it is possible
  76.      to query IFDHICCPresence() for card status.
  77.  
  78.      returns:
  79.  
  80.      IFD_SUCCESS
  81.      IFD_COMMUNICATION_ERROR
  82.   */
  83.     DWORD nlength;
  84.     UCHAR pcbuffer[RESP_BUF_SIZE];
  85.  
  86.  #ifdef GEMPC430_DEBUG
  87.  printf("IFD_GemPC430 : entering IFDHCreateChannel\n");
  88.  #endif
  89.  
  90.  
  91.     // Reset ATR buffer
  92.     pgSlots[GCoreLunToSlotNb(Lun)].nATRLength = 0;
  93.  
  94.  
  95.     if (OpenUSB(Lun) != STATUS_SUCCESS)
  96.     {
  97.         log_function("IFD_GemPC430 : OpenUSB failed\n");
  98.         return IFD_COMMUNICATION_ERROR;
  99.     }
  100.  
  101.     // Set the mode to ROS but no TLP (ATR should then be fine)
  102.     nlength = sizeof(pcbuffer);
  103.     if ( GCSendCommand(Lun, sizeof(pcSetModeROSNOTLP),
  104.                        pcSetModeROSNOTLP,
  105.                        &nlength, pcbuffer) != STATUS_SUCCESS )
  106.     {
  107.         log_function("IFD_GemPC430 : Setmode failed\n");
  108.         goto error_exit;
  109.     }
  110.     // Check status returned by reader
  111.     if ( pcbuffer[STATUS_OFFSET] != GCORE_OK )
  112.     {
  113.         // Could not set reader mode
  114.         // For now, we consider this a "fatal" error
  115.         log_function("IFD_GemPC430 : Setmode failed\n");
  116.         goto error_exit;
  117.     }
  118.     return IFD_SUCCESS;
  119.  
  120. error_exit:
  121.     CloseUSB(Lun);
  122.     return IFD_COMMUNICATION_ERROR;
  123.  
  124. }
  125.  
  126. RESPONSECODE IFDHCloseChannel ( DWORD Lun ) {
  127.  
  128.   /* This function should close the reader communication channel
  129.      for the particular reader.  Prior to closing the communication channel
  130.      the reader should make sure the card is powered down and the terminal
  131.      is also powered down.
  132.  
  133.      returns:
  134.  
  135.      IFD_SUCCESS
  136.      IFD_COMMUNICATION_ERROR
  137.   */
  138.     UCHAR pcbuffer[RESP_BUF_SIZE];
  139.     DWORD nlength;
  140.  
  141.  #ifdef GEMPC430_DEBUG
  142.  printf("IFD_GemPC430 : entering IFDHCloseChannel\n");
  143.  #endif
  144.  
  145.     // PowerDown the card
  146.     nlength = sizeof(pcbuffer);
  147.     if ( GCSendCommand(Lun, sizeof(pcPowerDown[GCoreLunToSlotNb(Lun)]),
  148.                      &pcPowerDown[GCoreLunToSlotNb(Lun)],
  149.                      &nlength, pcbuffer) != STATUS_SUCCESS )
  150.     {
  151.         log_function("IFD GemPC430 : PowerDown failed\n");
  152.         CloseUSB(Lun);
  153.         return IFD_COMMUNICATION_ERROR;
  154.     }
  155.  
  156.     // No reader status check, if it failed, what can you do ? :)
  157.  
  158.     CloseUSB(Lun);
  159.     return IFD_SUCCESS;
  160. }
  161.  
  162. RESPONSECODE IFDHGetCapabilities ( DWORD Lun, DWORD Tag,
  163.            PDWORD Length, PUCHAR Value ) {
  164.  
  165.   /* This function should get the slot/card capabilities for a particular
  166.      slot/card specified by Lun.  Again, if you have only 1 card slot and don't mind
  167.      loading a new driver for each reader then ignore Lun.
  168.  
  169.      Tag - the tag for the information requested
  170.          example: TAG_IFD_ATR - return the Atr and it's size (required).
  171.          these tags are defined in ifdhandler.h
  172.  
  173.      Length - the length of the returned data
  174.      Value  - the value of the data
  175.  
  176.      returns:
  177.  
  178.      IFD_SUCCESS
  179.      IFD_ERROR_TAG
  180.   */
  181.  
  182.  #ifdef GEMPC430_DEBUG
  183.  printf("IFD_GemPC430 : entering IFDHGetCapabilities\n");
  184.  #endif
  185.  
  186.  
  187.     switch ( Tag )
  188.     {
  189.         case TAG_IFD_ATR:
  190.         {
  191.             // If Length is not zero, powerICC has been performed.
  192.             // Otherwise, return NULL pointer
  193.             // Buffer size is stored in *Length
  194.             *Length = ( *Length < pgSlots[GCoreLunToSlotNb(Lun)].nATRLength) ?
  195.                         *Length : pgSlots[GCoreLunToSlotNb(Lun)].nATRLength;
  196.             if ( *Length )
  197.             {
  198.                 memcpy(Value,  pgSlots[GCoreLunToSlotNb(Lun)].pcATRBuffer, *Length);
  199.             }
  200.             break;
  201.         }
  202.         default:
  203.         {
  204.             return IFD_ERROR_TAG;
  205.         }
  206.     }
  207.     return IFD_SUCCESS;
  208. }
  209.  
  210. RESPONSECODE IFDHSetCapabilities ( DWORD Lun, DWORD Tag,
  211.              DWORD Length, PUCHAR Value ) {
  212.  
  213.   /* This function should set the slot/card capabilities for a particular
  214.      slot/card specified by Lun.  Again, if you have only 1 card slot and don't mind
  215.      loading a new driver for each reader then ignore Lun.
  216.  
  217.      Tag - the tag for the information needing set
  218.  
  219.      Length - the length of the returned data
  220.      Value  - the value of the data
  221.  
  222.      returns:
  223.  
  224.      IFD_SUCCESS
  225.      IFD_ERROR_TAG
  226.      IFD_ERROR_SET_FAILURE
  227.      IFD_ERROR_VALUE_READ_ONLY
  228.   */
  229.     // By default, say it worked
  230. #ifdef GEMPC430_DEBUG
  231.  printf("IFD_GemPC430 : entering IFDHSetCapabilities\n");
  232. #endif
  233.     return IFD_SUCCESS;
  234. }
  235.  
  236. RESPONSECODE IFDHSetProtocolParameters ( DWORD Lun, DWORD Protocol,
  237.            UCHAR Flags, UCHAR PTS1,
  238.            UCHAR PTS2, UCHAR PTS3) {
  239.  
  240.   /* This function should set the PTS of a particular card/slot using
  241.      the three PTS parameters sent
  242.  
  243.      Protocol  - 0 .... 14  T=0 .... T=14
  244.      Flags     - Logical OR of possible values:
  245.      IFD_NEGOTIATE_PTS1 IFD_NEGOTIATE_PTS2 IFD_NEGOTIATE_PTS3
  246.      to determine which PTS values to negotiate.
  247.      PTS1,PTS2,PTS3 - PTS Values.
  248.  
  249.      returns:
  250.  
  251.      IFD_SUCCESS
  252.      IFD_ERROR_PTS_FAILURE
  253.      IFD_COMMUNICATION_ERROR
  254.      IFD_PROTOCOL_NOT_SUPPORTED
  255.   */
  256.  
  257. #ifdef GEMPC430_DEBUG
  258.  printf("IFD_GemPC430 : entering IFDHSetProtocolParameters\n");
  259. #endif
  260.     return IFD_SUCCESS;
  261. }
  262.  
  263.  
  264. RESPONSECODE IFDHPowerICC ( DWORD Lun, DWORD Action,
  265.           PUCHAR Atr, PDWORD AtrLength ) {
  266.  
  267.   /* This function controls the power and reset signals of the smartcard reader
  268.      at the particular reader/slot specified by Lun.
  269.  
  270.      Action - Action to be taken on the card.
  271.  
  272.      IFD_POWER_UP - Power and reset the card if not done so
  273.      (store the ATR and return it and it's length).
  274.  
  275.      IFD_POWER_DOWN - Power down the card if not done already
  276.      (Atr/AtrLength should
  277.      be zero'd)
  278.  
  279.     IFD_RESET - Perform a quick reset on the card.  If the card is not powered
  280.      power up the card.  (Store and return the Atr/Length)
  281.  
  282.      Atr - Answer to Reset of the card.  The driver is responsible for caching
  283.      this value in case IFDHGetCapabilities is called requesting the ATR and it's
  284.      length.  This should not exceed MAX_ATR_SIZE.
  285.  
  286.      AtrLength - Length of the Atr.  This should not exceed MAX_ATR_SIZE.
  287.  
  288.      Notes:
  289.  
  290.      Memory cards without an ATR should return IFD_SUCCESS on reset
  291.      but the Atr should be zero'd and the length should be zero
  292.  
  293.      Reset errors should return zero for the AtrLength and return
  294.      IFD_ERROR_POWER_ACTION.
  295.  
  296.      returns:
  297.  
  298.      IFD_SUCCESS
  299.      IFD_ERROR_POWER_ACTION
  300.      IFD_COMMUNICATION_ERROR
  301.      IFD_NOT_SUPPORTED
  302.   */
  303.     DWORD nlength;
  304.     UCHAR pcbuffer[RESP_BUF_SIZE];
  305.     UCHAR pccmd_buffer[CMD_BUF_SIZE];
  306.     DWORD ncommand_length = 1; // there is at least the command byte
  307.  #ifdef GEMPC430_DEBUG
  308.  printf("IFD_GemPC430 : entering IFDHPowerICC\n");
  309.  #endif
  310.      // By default, assume it won't work :)
  311.     *AtrLength = 0;
  312.  
  313.     switch (Action)
  314.     {
  315.         case IFD_POWER_UP:
  316.         case IFD_RESET:
  317.             // Build reset command
  318.             pccmd_buffer[OFFSET_CMD] = pcPowerUp[GCoreLunToSlotNb(Lun)];
  319. // PTS management should be added here
  320.            //send the command
  321.             nlength = sizeof(pcbuffer);
  322.             if ( GCSendCommand(Lun, ncommand_length, pccmd_buffer,
  323.                         &nlength, pcbuffer) != STATUS_SUCCESS )
  324.             {
  325.                 log_function("IFD_GemPC430 : PowerUp failed\n");
  326.                 return IFD_COMMUNICATION_ERROR;
  327.             }
  328.             // Response analysis
  329.             if ( nlength < 1)
  330.             {
  331.                 pgSlots[GCoreLunToSlotNb(Lun)].nATRLength
  332.                         = *AtrLength = 0;
  333.                 return IFD_COMMUNICATION_ERROR;
  334.             }
  335.             // Remove command byte count from length
  336.             nlength--;
  337.             switch ( pcbuffer[STATUS_OFFSET] )
  338.             {
  339.                 case GCORE_OK:
  340.                 case GCORE_WRONG_TCK:
  341.                     // Reset is returned, even if TCK is wrong
  342.                     pgSlots[GCoreLunToSlotNb(Lun)].nATRLength
  343.                         = *AtrLength = (nlength < MAX_ATR_SIZE)
  344.                                         ? nlength: MAX_ATR_SIZE;
  345.                     memcpy(Atr, pcbuffer+ATR_OFFSET, *AtrLength);
  346.                     memcpy(pgSlots[GCoreLunToSlotNb(Lun)].pcATRBuffer,
  347.                            pcbuffer+ATR_OFFSET,
  348.                            *AtrLength);
  349.                     break;
  350.                 default:
  351.                     // There is a problem in getting the reset
  352.                     return IFD_ERROR_POWER_ACTION;
  353.             }
  354.             break;
  355.         case IFD_POWER_DOWN:
  356.             //send the command
  357.             pccmd_buffer[OFFSET_CMD] = pcPowerDown[GCoreLunToSlotNb(Lun)];
  358.             nlength = sizeof(pcbuffer);
  359.             if ( GCSendCommand(Lun, ncommand_length, pccmd_buffer,
  360.                         &nlength, pcbuffer) != STATUS_SUCCESS )
  361.             {
  362.                 log_function("IFD_GemPC430 : PowerUp failed\n");
  363.                 return IFD_COMMUNICATION_ERROR;
  364.             }
  365.             if ( nlength<1 )
  366.                 return IFD_COMMUNICATION_ERROR;
  367.             if ( pcbuffer[STATUS_OFFSET] != GCORE_OK )
  368.             {
  369.                 // There is a problem in power down
  370.                 return IFD_ERROR_POWER_ACTION;
  371.             }
  372.             break;
  373.         default:
  374.             return IFD_NOT_SUPPORTED;
  375.     }
  376.     return IFD_SUCCESS;
  377. }
  378.  
  379. RESPONSECODE IFDHTransmitToICC ( DWORD Lun, SCARD_IO_HEADER SendPci,
  380.          PUCHAR TxBuffer, DWORD TxLength,
  381.          PUCHAR RxBuffer, PDWORD RxLength,
  382.          PSCARD_IO_HEADER RecvPci ) {
  383.  
  384.   /* This function performs an APDU exchange with the card/slot specified by
  385.      Lun.  The driver is responsible for performing any protocol specific exchanges
  386.      such as T=0/1 ... differences.  Calling this function will abstract all protocol
  387.      differences.
  388.  
  389.      SendPci
  390.      Protocol - 0, 1, .... 14
  391.      Length   - Not used.
  392.  
  393.      TxBuffer - Transmit APDU example (0x00 0xA4 0x00 0x00 0x02 0x3F 0x00)
  394.      TxLength - Length of this buffer.
  395.      RxBuffer - Receive APDU example (0x61 0x14)
  396.      RxLength - Length of the received APDU.  This function will be passed
  397.      the size of the buffer of RxBuffer and this function is responsible for
  398.      setting this to the length of the received APDU.  This should be ZERO
  399.      on all errors.  The resource manager will take responsibility of zeroing
  400.      out any temporary APDU buffers for security reasons.
  401.  
  402.      RecvPci
  403.      Protocol - 0, 1, .... 14
  404.      Length   - Not used.
  405.  
  406.      Notes:
  407.      The driver is responsible for knowing what type of card it has.  If the current
  408.      slot/card contains a memory card then this command should ignore the Protocol
  409.      and use the MCT style commands for support for these style cards and transmit
  410.      them appropriately.  If your reader does not support memory cards or you don't
  411.      want to then ignore this.
  412.  
  413.      RxLength should be set to zero on error.
  414.  
  415.      returns:
  416.  
  417.      IFD_SUCCESS
  418.      IFD_COMMUNICATION_ERROR
  419.      IFD_RESPONSE_TIMEOUT
  420.      IFD_ICC_NOT_PRESENT
  421.      IFD_PROTOCOL_NOT_SUPPORTED
  422.   */
  423.     UCHAR pccmd_buffer[CMD_BUF_SIZE];
  424.     UCHAR pcbuffer[RESP_BUF_SIZE];
  425.     DWORD nlength;
  426.     RESPONSECODE return_value = IFD_SUCCESS; // Assume it will work
  427.  
  428. #ifdef GEMPC430_DEBUG
  429.  printf("IFD_GemPC430 : entering IFDHTransmitToICC\n");
  430. #endif
  431.     switch ( SendPci.Protocol )
  432.     {
  433.         case T_0:
  434.             // Check if command is going to fit in buffer
  435.             if ( CMD_BUF_SIZE < (1 + TxLength) )
  436.             {
  437.                 // Buffer too small, send an error
  438.                 return_value =IFD_COMMUNICATION_ERROR;
  439.                 goto clean_up_and_return;
  440.             }
  441.  
  442.             // Check if this is an incoming or outgoing command
  443.             // Size should be APDU + one byte of length
  444.             if ( (TxLength == (APDU_SIZE+1)) && (TxBuffer[APDU_SIZE] !=0)  )
  445.             {
  446.                 // Buffer only holds an APDU (no Data) and L != 0,
  447.                 // output command
  448.                 pccmd_buffer[OFFSET_CMD] = pcISOOutput[GCoreLunToSlotNb(Lun)];
  449.                 memcpy(pccmd_buffer+OFFSET_APDU, TxBuffer, TxLength);
  450.             }
  451.             else if ( TxLength >= (APDU_SIZE+1) )
  452.             {
  453.                 // ">=" to catch the case CLA INS P1 P2 00
  454.                 pccmd_buffer[OFFSET_CMD] = pcISOInput[GCoreLunToSlotNb(Lun)];
  455.                 memcpy(pccmd_buffer+OFFSET_APDU, TxBuffer, TxLength);
  456.             }
  457.             else
  458.             {
  459.                 // RxBuffer  holds too little data to form an APDU+length
  460.                 return_value = IFD_COMMUNICATION_ERROR;
  461.                 goto clean_up_and_return;
  462.             }
  463.             // Send the command
  464.             nlength = sizeof(pcbuffer);
  465.             if ( GCSendCommand(Lun, TxLength+1,
  466.                                 pccmd_buffer,
  467.                                 &nlength, pcbuffer) != STATUS_SUCCESS )
  468.             {
  469.                 log_function("IFD_GemPC430 : ISO Output failed\n");
  470.                 return_value = IFD_COMMUNICATION_ERROR;
  471.                 goto clean_up_and_return;
  472.             }
  473.             return_value = gempc430_status_processing(nlength,
  474.                                                         RxLength,
  475.                                                         pcbuffer,
  476.                                                         RxBuffer);
  477.             break;
  478.         case T_1:
  479.             // Check if command is going to fit in buffer
  480.             // cmd byte + TxLength + Le
  481.             if ( CMD_BUF_SIZE < (1 + TxLength + 1) )
  482.             {
  483.                 // Buffer too small, send an error
  484.                 return_value =IFD_COMMUNICATION_ERROR;
  485.                 goto clean_up_and_return;
  486.             }
  487.  
  488.             // Build the commmand
  489.             pccmd_buffer[OFFSET_CMD] = pcEchAPDU[GCoreLunToSlotNb(Lun)];
  490.             memcpy(pccmd_buffer+OFFSET_APDU, TxBuffer, TxLength);
  491.             // Add length of expected data
  492.             pccmd_buffer[OFFSET_APDU+TxLength] = *RxLength;
  493.  
  494.             // Send the command
  495.             nlength = sizeof(pcbuffer);
  496.             if ( GCSendCommand(Lun, TxLength+1,
  497.                                 pccmd_buffer,
  498.                                 &nlength, pcbuffer) != STATUS_SUCCESS )
  499.             {
  500.                 log_function("IFD_GemPC430 : ISO Exchange failed\n");
  501.                 return_value = IFD_COMMUNICATION_ERROR;
  502.                 goto clean_up_and_return;
  503.             }
  504.             return_value = gempc430_status_processing(nlength,
  505.                                                         RxLength,
  506.                                                         pcbuffer,
  507.                                                         RxBuffer);
  508.  
  509.             break;
  510.         default:
  511.             return_value = IFD_PROTOCOL_NOT_SUPPORTED;
  512.     }
  513.  
  514. clean_up_and_return:
  515.     // Buffers clean-up
  516.     bzero(pccmd_buffer, sizeof(pccmd_buffer));
  517.     bzero(pcbuffer, sizeof(pcbuffer));
  518.     if ( return_value != IFD_SUCCESS )
  519.         *RxLength = 0;
  520.     return return_value;
  521.  
  522. }
  523.  
  524. RESPONSECODE IFDHControl ( DWORD Lun, PUCHAR TxBuffer,
  525.        DWORD TxLength, PUCHAR RxBuffer,
  526.        PDWORD RxLength ) {
  527.  
  528.   /* This function performs a data exchange with the reader (not the card)
  529.      specified by Lun.  Here XXXX will only be used.
  530.      It is responsible for abstracting functionality such as PIN pads,
  531.      biometrics, LCD panels, etc.  You should follow the MCT, CTBCS
  532.      specifications for a list of accepted commands to implement.
  533.  
  534.      TxBuffer - Transmit data
  535.      TxLength - Length of this buffer.
  536.      RxBuffer - Receive data
  537.      RxLength - Length of the received data.  This function will be passed
  538.      the length of the buffer RxBuffer and it must set this to the length
  539.      of the received data.
  540.  
  541.      Notes:
  542.      RxLength should be zero on error.
  543.   */
  544. #ifdef GEMPC430_DEBUG
  545.  printf("IFD_GemPC430 : entering IFDHControl\n");
  546. #endif
  547.  
  548.     return IFD_SUCCESS;
  549. }
  550.  
  551. RESPONSECODE IFDHICCPresence( DWORD Lun ) {
  552.  
  553.   /* This function returns the status of the card inserted in the
  554.      reader/slot specified by Lun.  It will return either:
  555.  
  556.      returns:
  557.      IFD_ICC_PRESENT
  558.      IFD_ICC_NOT_PRESENT
  559.      IFD_COMMUNICATION_ERROR
  560.   */
  561.  
  562.     UCHAR pcbuffer[RESP_BUF_SIZE];
  563.     DWORD nlength;
  564.  
  565. #ifdef GEMPC430_DEBUG
  566.  printf("IFD_GemPC430 : entering IFDHICCPresence\n");
  567. #endif
  568.  
  569.     // Send the command
  570.     nlength = sizeof(pcbuffer);
  571.     // Command is 1-byte long
  572.     if ( GCSendCommand(Lun, 1, &pcCardStatus[GCoreLunToSlotNb(Lun)],
  573.                      &nlength, pcbuffer) != STATUS_SUCCESS )
  574.     {
  575.         log_function("IFD_GemPC430 : CARD STATUS failed\n");
  576.         return IFD_COMMUNICATION_ERROR;
  577.     }
  578.  
  579.     if ( (nlength < (OFFSET_STAT_BYTE+1)) ||
  580.             pcbuffer[STATUS_OFFSET] != GCORE_OK )
  581.     {
  582.         // Length should at least be 2 (nlength + reader status)
  583.         return IFD_COMMUNICATION_ERROR;
  584.     }
  585.  
  586.     return (MASK_ICC_PRESENCE & pcbuffer[OFFSET_STAT_BYTE])
  587.                 ? IFD_ICC_PRESENT : IFD_ICC_NOT_PRESENT;
  588. }
  589.  
  590. RESPONSECODE gempc430_status_processing(DWORD nlength, PDWORD RxLength,
  591.                                         PUCHAR pcbuffer, PUCHAR RxBuffer)
  592. {
  593.     if (nlength < 1)
  594.     {
  595.         // Length should at least be 1 (reader status)
  596.         return IFD_COMMUNICATION_ERROR;
  597.     }
  598.     nlength -=1;
  599.     switch ( pcbuffer[STATUS_OFFSET] )
  600.     {
  601.         case GCORE_OK:
  602.         case GCORE_NOT_9000:
  603.         case GCORE_CARD_EXC_INT:   //SW=6700
  604.             // if ( nlength < pcbuffer[OFFSET_LNG] )
  605.             // WHAT SHOULD WE DO
  606.             *RxLength = ( *RxLength < nlength)
  607.                           ? (*RxLength) : nlength;
  608.             memcpy(RxBuffer, pcbuffer+OFFSET_DATA,
  609.                     *RxLength);
  610.             break;
  611.         case GCORE_CARD_MUTE:
  612.             return IFD_RESPONSE_TIMEOUT;
  613.         case GCORE_CARD_PROT_ERR:
  614.             return IFD_PROTOCOL_NOT_SUPPORTED;
  615.         default:
  616.             // There was a problem in sending the command
  617.             return IFD_COMMUNICATION_ERROR;
  618.     }
  619.     return IFD_SUCCESS;
  620. }
  621.  
  622.