How to develop a card service.
Developing a Card Service
Best starting point for a card service to use a BasicCard is to extend the AbstractBasicCardService class. This class gives easy access to all predefined BasicCard commands by use of the Cmd... functions. Furthermore you can call custom BasicCard commands by use of DoCommandAndResponse. Calling custom commands is the typical need for a custom card service, so within following description we will focus on this.
The DoCommandAndResponse function expects a BasicCardCommand object as parameter. The BasicCardCommand reflects the command declaration within your BasicCard. Lets assume you have a BasicCard which implements the following command:
BasicCard Basic
![]() | |
---|---|
Command &H48 &H12 MyOwnCommand(MyNumber as Integer, MyString as String) EepromMyNumber=MyNumber EepromMyString=MyString MyNumber=42 MyString="Hello World" End Command |
Obviously this command is just storing the command parameters within matching global EEPROM variables and return some constant values within these parameters on return. Within this command we see the following:
48h is assigned to this command as CLA
12h is assigned to this command as INS
There are two parameters MyNumber which is a BasicCard Integer and MyString which is a BasicCard String.
The command does return some information within these parameters, so we should use the default LE to receive this data..
Following code will setup a BasicCardCommand object for this command:
Visual Basic | ![]() |
---|---|
' Create BasicCardCommand with CLA=48h and INS=12h Dim cmd as BasicCardCommand cmd = new BasicCardCommand(&H48, &H12) ' setup first parameter as BasicCard Integer cmd.AppendBasicInteger(42) ' setup second parameter to "Hello World" using ASCII encoding cmd.AppendBasicString(new BasicCardString("Hello World", BasicCardString.CharsetIdAscii) ' set default LE so we get our result parameters cmd.SetDefaultLE() |
C# | ![]() |
---|---|
// Create BasicCardCommand with CLA=48h and INS=12h BasicCardCommand cmd=new BasicCardCommand(0x48, 0x12); // setup first parameter as BasicCard Integer cmd.AppendBasicInteger(42); // setup second parameter to "Hello World" using ASCII encoding cmd.AppendBasicString(new BasicCardString("Hello World", BasicCardString.CharsetIdAscii); // set default LE so we get our result parameters cmd.SetDefaultLE(); |
As you can see above for creating the BasicCardCommand you have to fulfil the following steps:
Create a BasicCardCommand object with matching CLA and INS.
If desired set P1 and/or P2 as required. Initially these bytes will be set to zero.
Add your BasicCard command parameters as implemented within your BasicCard to this BasicCardCommand by use of a matching ; AppendBasic... method call. You must append the command parameters in same order as they appear within your BasicCard command implementations, starting with leftmost parameter. Depending on your card implementation it may not be required to provide input to your card command or it may not be required to provide all specified parameters as input to your card command. In this case you may provide only the required parameters, but you still must keep the order and you must not dismiss parameters to the left of a required/transmitted parameter. Note Your BasicCard command may not accept to receive a reduced amount of parameters. So in cases where you receive a swLcLeError you should try to transmit none or all parameters instead.
Additionally to your command data the smart card expects the LE (Length Expected) byte. This byte will notify the card regarding your requested amount of response data. The library tries to figure out a proper value for LE if none is specified, but it is recommended to specify it manually.
If you have added all command parameters and you expect the card to return the same parameters on return you do not need to specify LE. This is equal to calling SetDefaultLE.
If you want the card to return no parameter data on response, you must disable the LE byte transmission by use of DisableLE.
If you want the card to return as much data as available as response you must set LE to zero by using the LE property.
If you want the card to return a certain amount of bytes you can specify this byte count as LE again by using the LE property.
Note In general your BasicCard command may not accept all LE values. So in cases where you receive a swLcLeError error you should try a different value for LE.
Once you have created a BasicCardCommand you can pass it to DoCommandAndResponse. E.g. like this:
Visual Basic | ![]() |
---|---|
Dim rsp as BasicCardResponse rsp=DoCommandAndResponse(cmd) |
C# | ![]() |
---|---|
BasicCardResponse rsp=DoCommandAndResponse(cmd); |
This will cause the command to be transmitted to your BasicCard and your matching BASIC command code within your BasicCard is executed. Once execution within card is finshed the DoCommandAndResponse method will return. As return value you will receive a BasicCardResponse object.
The BasicCardResponse object is much like a BasicCardCommand object. It will encapsulate the result including the SW1SW2 status word which in general all smart cards return and the response parameter. For MyOwnCommand as described above our source code may look as follows:
Visual Basic | ![]() |
---|---|
Dim MyNumber as Short Dim MyString as String rsp.CheckSW1SW2() // retrieve first parameter MyNumber = rsp.FetchBasicInteger() // retrieve second parameter MyString = rsp.FetchBasicString().ToString(BasicCardString.CharsetIdAscii) |
C# | ![]() |
---|---|
rsp.CheckSW1SW2(); // retrieve first parameter short MyNumber=rsp.FetchBasicInteger(); // retrieve second parameter string MyString=rsp.FetchBasicString().ToString(BasicCardString.CharsetIdAscii); |
So to validate the response and get your resulting parameters you must implement the following steps:
Check the response in general for error conditions within SW1SW2 by calling CheckSW1SW2.
Retrieve the required response parameters by use of matching FetchBasic... method. Here the same rule as for the BasicCardCommand applies, you must fetch the response parameters in correct order beginning with leftmost parameter.