IDTech Windows SDK Guide  1.1.81.0
API reference for SmartPIN L100
Sample Project Tutorial

Using Visual Studio 2015, we will create a C# sample project that will interface with the SmartPin L100 and will perform the following activities:

  • Get firmware version
  • Prompt for PIN Entry and return data
  • Display a secure message and prompt for entry
  • Display a non-secure message
  • Connect to either USB or Serial Versions of L100.
  • Show log of all data going to/from L100

Step 1: Create New Project

Create a new Blank App (Universal Windows) in Visual Studio. In our example, we use project name L100_Simple_Demo_UWP.

new_project_uwp.png

On the following popup, choose the target and minimum versions that your application will support. We have chosen the following for our demo application:

versions_uwp.png

Step 2: Import Libraries

Import the Necessary Libraries

Step 3: Add Device Details

Add Device Details to the Application's Manifest

Step 4: Design Interface

Use the Designer to layout buttons/fields
Open your designer and add items so it contains the following buttons/fields:

  • Radio buttons for USB and COM selection. For COM selection, add a text box to specify COM port. Add a drop-down for baud rate
  • Add buttons to execute the following functions:
    • Get Firmware
    • Get PIN Entry
    • Secure Message Prompt
    • Unsecure Message Prompt
  • Add a text box to communicate data from the L100.
  • Add a text box for the log of L100.
  • Add a text box to display the connection status.


L100_app_uwp.png


<Page
x:Class="L100_Simple_Demo_UWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:L100_Simple_Demo_UWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Grid Height="673" Margin="0,10,0,0" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Button x:Name="btnGetFirmwareVersion" Content="Firmware Version" HorizontalAlignment="Stretch" Margin="10,60,10,0" VerticalAlignment="Top" Click="btnGetFirmwareVersion_Click"/>
<Button x:Name="btnGetPINEntry" Content="Get PIN Entry" HorizontalAlignment="Stretch" Margin="10,97,10,0" VerticalAlignment="Top" Click="btnGetPINEntry_Click"/>
<Button x:Name="btnGetKeyInput" Content="Get Key Input" HorizontalAlignment="Stretch" Margin="10,134,10,0" VerticalAlignment="Top" Click="btnGetKeyInput_Click"/>
<Button x:Name="btnDisplayUnsecureMessage" Content="Display Unsecure Message" HorizontalAlignment="Stretch" Margin="10,171,10,0" VerticalAlignment="Top" Click="btnDisplayUnsecureMessage_Click"/>
<RadioButton x:Name="rbUSB" Content="USB" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Click="rbUSB_Click"/>
<RadioButton x:Name="rbSerial" Content="COM" HorizontalAlignment="Left" Margin="81,10,0,0" VerticalAlignment="Top" Click="rbSerial_Click"/>
<TextBox x:Name="tbCOMPort" HorizontalAlignment="Left" Margin="160,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" PlaceholderText="Port Number"/>
<TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="278,16,0,0" TextWrapping="Wrap" Text="Baud" VerticalAlignment="Top"/>
<ComboBox x:Name="comboBoxBaudRate" HorizontalAlignment="Left" Margin="315,10,0,0" VerticalAlignment="Top" Width="120" ItemsSource="{Binding}"/>
</Grid>
<Grid Grid.Row="1" Margin="0,0,0,40" MinHeight="200">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox x:Name="tbOutput" Margin="10" TextWrapping="Wrap" ScrollViewer.VerticalScrollMode="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" IsReadOnly="True" Grid.Row="0"/>
<TextBox x:Name="logOutput" Margin="10" TextWrapping="Wrap" ScrollViewer.VerticalScrollMode="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" IsReadOnly="True" Grid.Row="1"/>
</Grid>
</Grid>
</ScrollViewer>
<TextBox x:Name="connectionStatus" TextAlignment="Center" Background="Red" TextWrapping="Wrap" Text="SmartPIN L100 not connected." VerticalAlignment="Bottom" BorderThickness="0" IsHitTestVisible="False"/>
</Grid>
</Page>


Step 5: Configure the Project File

In the start of the class file, perform the following:

  • Add Using Statements to Utilize Library
  • Set callback method and initialize L100 singleton object in the class initializer. Reference: Initialize SmartPIN L100
  • Implement the radio button methods Click handlers to set the proper interface for SDK communications
    private void rbUSB_Click(object sender, RoutedEventArgs e)
    {
    Task.Run(() => IDT_L100.useUSB());
    }
    private void rbSerial_Click(object sender, RoutedEventArgs e)
    {
    Int32 portNumber = Convert.ToInt32(tbCOMPort.Text);
    if (comboBoxBaudRate.SelectedIndex == 0)
    {
    Task.Run(() => IDT_L100.useSerialPort(portNumber, false));
    }
    else
    {
    Int32 baudRate = Convert.ToInt32(comboBoxBaudRate.SelectedItem);
    Task.Run(() => IDT_L100.useSerialPort(portNumber, baudRate, false));
    }
    }

  • Implement the button methods Click handlers for button press code execution
    private void btnGetFirmwareVersion_Click(object sender, RoutedEventArgs e)
    {
    Task.Run(() =>
    {
    string firmwareVersion = "";
    RETURN_CODE rt = IDT_L100.SharedController.device_getFirmwareVersion(ref firmwareVersion);
    if (rt == RETURN_CODE.RETURN_CODE_DO_SUCCESS)
    {
    SetOutputText("Firmware Ver: " + firmwareVersion + "\r\n");
    System.Diagnostics.Debug.WriteLine("Firmware Ver: " + firmwareVersion);
    }
    else
    {
    SetOutputText("Get Firmware Fail Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt) + ": " + IDTechSDK.errorCode.getErrorString(rt) + "\r\n");
    System.Diagnostics.Debug.WriteLine("Get Firmware Fail Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt));
    }
    });
    }
    private void btnGetPINEntry_Click(object sender, RoutedEventArgs e)
    {
    Task.Run(() =>
    {
    RETURN_CODE rt = IDT_L100.SharedController.pin_getEncryptedPIN(1, "4111111111111111", "ENTER PIN", 45);
    if (rt == RETURN_CODE.RETURN_CODE_DO_SUCCESS)
    {
    SetOutputText("Enter Pin Executed Successful\r\n");
    System.Diagnostics.Debug.WriteLine("Enter Pin Executed Successful");
    }
    else
    {
    SetOutputText("Enter Pin Executed failed Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt) + ": " + IDTechSDK.errorCode.getErrorString(rt) + "\r\n");
    System.Diagnostics.Debug.WriteLine("Enter Pin Executed failed Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt));
    }
    });
    }
    private void btnGetKeyInput_Click(object sender, RoutedEventArgs e)
    {
    Task.Run(() =>
    {
    RETURN_CODE rt = IDT_L100.SharedController.pin_promptForKeyInput(Convert.ToInt32(tbMessageID.Text), Convert.ToInt32(tbLanguageID.Text), cbMaskInput.Checked, Convert.ToInt32(tbMinLength.Text), Convert.ToInt32(tbMaxLength.Text), Convert.ToInt32(tbPinTimout.Text));
    if (rt == RETURN_CODE.RETURN_CODE_DO_SUCCESS)
    {
    SetOutputText("Prompt for Key Entry Command Successful\r\n");
    System.Diagnostics.Debug.WriteLine("Prompt for Key Entry Command Successful");
    }
    else
    {
    SetOutputText("Prompt for Key Entry Command Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt) + ": " + IDTechSDK.errorCode.getErrorString(rt) + "\r\n");
    System.Diagnostics.Debug.WriteLine("Prompt for Key Entry Command Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt));
    }
    });
    }
    private void btnDisplayUnsecureMessage_Click(object sender, RoutedEventArgs e)
    {
    Task.Run(() =>
    {
    RETURN_CODE rt = IDT_Device.SharedController.lcd_displayMessage(1, "SmartPIN L100 Ready");
    if (rt == RETURN_CODE.RETURN_CODE_DO_SUCCESS)
    {
    SetOutputText("Display Message Successful\r\n");
    System.Diagnostics.Debug.WriteLine("Display Message Successful");
    }
    else
    {
    SetOutputText("Display Message failed Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt) + ": " + IDTechSDK.errorCode.getErrorString(rt) + "\r\n");
    System.Diagnostics.Debug.WriteLine("Display Message failed Error Code: " + "0x" + String.Format("{0:X}", (ushort)rt));
    }
    });
    }

    Note that all the the click handlers' code are ran asynchronously. At least the device command needs to be executed asynchronously or it will block the UI thread. The UWP API that is used by the IDTechSDK_UWP library for communication with HID devices is asynchronous.

Step 6: Configure Callback

The callback is used to receive important SDK data (messages, log info and transaction results). Reference: Implement the Callback Function

private void MessageCallBack(IDTechSDK.IDT_DEVICE_Types type, DeviceState state, byte[] data, IDTTransactionData cardData, EMV_Callback emvCallback, RETURN_CODE transactionResultCode)
{
switch (state)
{
case DeviceState.ToConnect:
SetOutputText("To connect\r\n");
break;
case DeviceState.DefaultDeviceTypeChange:
//The SDK is changing the default device to IDT_DEVICE_TYPES type
SetOutputText("Callback:DefaultDeviceTypeChange\n");
connectionStatus.Text = "SmartPIN L100 connected.";
connectionStatus.Background = new SolidColorBrush(Windows.UI.Colors.Green);
break;
case DeviceState.Connected:
//A connection has been made to IDT_DEVICE_TYPES type
SetOutputText("Callback:Connected\n");
connectionStatus.Text = "SmartPIN L100 connected.";
connectionStatus.Background = new SolidColorBrush(Windows.UI.Colors.Green);
break;
case DeviceState.Disconnected:
//A disconnection has occured with IDT_DEVICE_TYPES type
SetOutputText("Callback:Disconnected\n");
connectionStatus.Text = "SmartPIN L100 not connected.";
connectionStatus.Background = new SolidColorBrush(Windows.UI.Colors.Red);
break;
case DeviceState.ConnectionFailed:
SetOutputText("Connection Failed\r\n");
break;
case DeviceState.Notification:
SetOutputText("Notification\r\n");
break;
case DeviceState.TransactionData:
if (cardData == null) break;
//output parsed card data
SetOutputText("Return Code: " + transactionResultCode.ToString() + "\r\n");
if (cardData.Event == EVENT_TRANSACTION_DATA_Types.EVENT_TRANSACTION_PIN_DATA)
{
SetOutputText("PIN Data received:\r\nKSN: " + cardData.pin_KSN + "\r\nPINBLOCK: " + cardData.pin_pinblock + "\r\nKey Entry: " + cardData.pin_KeyEntry + "\r\n");
return;
}
break;
case DeviceState.DataReceived:
SetOutputTextLog(" IN: " + Common.getHexStringFromBytes(data) + "\r\n");
break;
case DeviceState.DataSent:
SetOutputTextLog(" OUT: " + Common.getHexStringFromBytes(data) + "\r\n");
break;
case DeviceState.CommandTimeout:
SetOutputText("Command Timeout\r\n");
break;
case DeviceState.ToSwipe:
SetOutputText("To Swipe\r\n");
break;
case DeviceState.MSRDecodeError:
SetOutputText("MSR Decode Error\r\n");
break;
case DeviceState.ToTap:
SetOutputText("To Tap\r\n");
break;
case DeviceState.SwipeTimeout:
SetOutputText("Swipe Timeout\r\n");
break;
case DeviceState.TransactionCancelled:
System.Diagnostics.Debug.WriteLine("TransactionCancelled\r\n");
break;
case DeviceState.DeviceTimeout:
SetOutputText("Device Timeout\r\n");
break;
case DeviceState.TransactionFailed:
SetOutputText("Transaction Failed: " + IDTechSDK.errorCode.getErrorString(transactionResultCode) + "\r\n");
break;
case DeviceState.EMVCallback:
SetOutputText("EMV Callback\r\n");
break;
case DeviceState.PINpadKeypress:
SetOutputText("PINPad Key was pressed\r\n");
break;
default:
break;
}
}
delegate void SetTextCallback(string text);
private async void SetOutputText(string text)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
tbOutput.Text = text + "\r\n" + tbOutput.Text;
});
}
private void SetOutputTextLog(string text)
{
logOutput.Text = text + "\r\n" + logOutput.Text;
}