Click here to Skip to main content
15,867,453 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
I am new to smart reader tech. I am developing a simple application to read data from smart card using .NET and c#. The phone is MC75A with biometric attachment and sdk is BSCR sdk version 2.2. I am using the WinSCard provided by the sdk which is a wrapper for winscard.dll.

In the code posted below, I am connecting to the card and trying to get the id from the smart card. I got the apdu command to retrieve UID from card from the Cardman_5x21-CL_Reader_Developers_Guide. It is mentioned that this works with every ISO 14443 A/B or ISO 15693 compliant card. The card I am using is PIV-Interoperable. I have tried various things but I am stuck at the point where it goes to WinSCard.Transmit command and gives error code: 80100069. I am not able to figure it out. Anyone please direct me what I am doing wrong? The code is pasted below. Thanks in advance.

private void ConnectCard()
        {
             try
              {
                  IntPtr hContext = IntPtr.Zero;
                  uint scardError = 0;
                  UpdateSCStatus("Establishing Context ...");
                  scardError = WinSCard.EstablishContext((uint)WinSCard.SCOPE.USER, IntPtr.Zero, IntPtr.Zero, out saved_hContext);
                  if (scardError != (uint)WinSCard.STATUS_RESULT.S_SUCCESS)
                  {
                      UpdateSCStatus("failed: 0x" + scardError.ToString("X8"));
                      return;
                  }
                  saved_Reader = (string)scComboBox2.SelectedItem;
                  UpdateSCStatus("Connecting ...");
                  MessageBox.Show(saved_Reader);
                  scardError = WinSCard.Connect(saved_hContext, saved_Reader, (uint)WinSCard.SHARE.EXCLUSIVE, (uint)WinSCard.PROTOCOL.T0, out saved_card, out saved_protocol);
                  if (scardError != 0)
                  {
                      saved_Reader = null;
                      saved_card = IntPtr.Zero;
                      saved_protocol = 0;
                      UpdateSCStatus("failed: 0x" + scardError.ToString("X8"));
                  }
                  else
                  {
                      UpdateSCStatus("Connected to Card.");
                      MessageBox.Show("Before calling submitIC(), saved_card: " + saved_card);
                      MessageBox.Show("Before calling submitIC(), saved_protocol: " + saved_protocol);
                      scardError = WinSCard.BeginTransaction(saved_card);
                      if (scardError == 0)
                      {
                          MessageBox.Show("Transaction started.");
                          SubmitIC();
                          UpdateSCStatus("Disconnecting Card....");
                          WinSCard.EndTransaction(saved_card, 0);
                          WinSCard.Disconnect(saved_card, (uint)WinSCard.CLOSE.UNPOWER_CARD);
                      }
                      else
                      {
                          UpdateSCStatus("failed: 0x" + scardError.ToString("X8"));
                      }
                  }
                  return;
              }
              catch (Exception ex)
              {
                  UpdateSCStatus(string.Format("Exception:\r\n" + ex.Message));
                  return;
              }
        }
         
    public int SubmitIC()
    {
        MessageBox.Show("in submitIC");
      int nResult = 1;
      try
      {
          byte[] defaultIssuerCode = { 0x5C, 0x03, 0x5F, 0xC1, 0x09, 0x00 };
          nResult = ExecuteCommand_Class2(0xFF, 0xCA, 0x00, 0x00, 0x00, defaultIssuerCode);
      }
      catch (Exception generalException)
      {
          LogError(1, generalException.Message);
      }
      return nResult;
    }
    private int ExecuteCommand_Class2(byte CLA, byte INS, byte P1, byte P2, byte Lc, byte[] Data)
    {
        MessageBox.Show("ExecuteCommand_Class2");
      int nResult = 0;
      if (saved_card != IntPtr.Zero)
      {
        byte[] bCommand = new byte[0x05 + Lc];
        byte[] bResponse = new byte[512];
        uint dwResponseLength = 512;
        WinSCard.IO_REQUEST cardIORequest = new WinSCard.IO_REQUEST();
        WinSCard.IO_REQUEST receiveIORequest = new WinSCard.IO_REQUEST();
    
        bCommand[0] = CLA;
        bCommand[1] = INS;
        bCommand[2] = P1;
        bCommand[3] = P2;
        bCommand[4] = Lc;
        uint blnCommand = 5;
        for (byte i = 0x00; i < Lc; i++)
          bCommand[i + 0x05] = Data[i];
        cardIORequest.dwProtocol = saved_protocol;
        cardIORequest.cbPciLength = (uint)(0x05 + Lc);
        receiveIORequest.dwProtocol = saved_protocol;
        receiveIORequest.cbPciLength = 512;
          nResult = (int)WinSCard.Transmit(saved_card, ref cardIORequest, bCommand, blnCommand, ref receiveIORequest, bResponse, ref dwResponseLength);
          UpdateSCStatus("result after Transmit: " + nResult.ToString("X8"));
          if (nResult == 0)
        {
            MessageBox.Show("in nResult block");
          if (bResponse[dwResponseLength - 2] == 0x90 && bResponse[dwResponseLength - 1] == 0x00)
          {
          }
          else if (bResponse[dwResponseLength - 2] == 0x61)
          {
          }
          else if (bResponse[dwResponseLength - 2] == 0x91)
          {
            // User Data File has been selected
          }
          else if (bResponse[dwResponseLength - 2] == 0x63)
          {
            nResult = 1;
          }
          else if (bResponse[dwResponseLength - 2] == 0x67)
          {
            nResult = 1;
          }
          else if (bResponse[dwResponseLength - 2] == 0x69 && bResponse[dwResponseLength - 1] == 0x66)
          {
            nResult = 1;
          }
          else if (bResponse[dwResponseLength - 2] == 0x69 && bResponse[dwResponseLength - 1] == 0x81)
          {
            nResult = 1;
          }
        }
        else
          LogError((uint)nResult, "Transmit");
      }
      return nResult;
    }
Posted
Updated 14-Apr-11 6:17am
v3
Comments
HimanshuJoshi 14-Apr-11 12:17pm    
Edited to add pre tags.

1 solution

Have you looked here? http://www.codeguru.com/forum/showthread.php?t=450642 (Though it's in VB. )

They talk about the SCARD_W_REMOVED_CARD error and how it might be because of the value types used in calling the functions are not correct.
 
Share this answer
 
Comments
Member 7804943 18-Apr-11 12:10pm    
Thanks for your response. I looked at the link you mentioned. I am not sure what code 22 stands for. The error code I am getting is -2146434967 equivalent to 80100069 in my sdk which translate to SCARD_W_REMOVED_CARD.
GenJerDan 18-Apr-11 12:31pm    
Yes. But one of the posters mentions that the results are different when called from .NET and "regular" programming. Like the DLL isn't returning the datatypes expected, so the actual error may not be card removed, but something else entirely...
Member 7804943 18-Apr-11 14:31pm    
How do I know what is the real issue? Thanks.
GenJerDan 18-Apr-11 14:37pm    
I'd try a tiny test program in another language (C, C++, VB) that does nothing but the function you're having problems with and see if you get the same or a different error. But even before that, I'd put breakpoints in your existing code where you're connecting to the card...see if it really is getting connected.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900