PinPad
>w## Notice
> * please include the header file "bwsdk_api.h" when you need to input pinblock
`#include "bwsdk_api.h"`
>i## data structure
```
/**
* @brief Material of PINBLOCK
*/
typedef struct {
unsigned char KeyArch; ///< Refer to Key_Arch_Type
unsigned char KeyIdx; ///< key index
unsigned char Mode; ///< Pin_Block_Mode_Type
unsigned char PanLen; ///< Length of PAN
unsigned char TradeInfoLen; ///< Length of Trade information
unsigned char ListLen; ///< Length of PIN LEN list
unsigned long TimeoutMs; ///< Timeout
unsigned char Pan[20]; ///< PAN with check byte; Check byte should be set 0x00 if APP doesn't get it.
unsigned char TradeInfo[8]; ///< Trade information
unsigned char ExpPinLenList[12];///< Length of PIN permit.
} Pin_Block_Material_Type;
/**
* @brief Event data of PINBLOCK
* @see:: Pin_Block_Event
*/
typedef struct {
unsigned char ucPinLen; ///< when event is PIN_EVENT_LEN, indicate the PIN length inputted
unsigned char ucPinBlkLen; ///< when event is PIN_EVENT_PINBLOCK or PIN_EVENT_PINFREE, indicate the length of pinblock
unsigned char ucKsnLen; ///< when event is PIN_EVENT_PINBLOCK or PIN_EVENT_PINFREE and using DUKPT, indicate the length of KSN
int iErrCode; ///< when event is PIN_EVENT_ERR, indicate the error
unsigned char aucPinBlock[32]; ///< when event is PIN_EVENT_PINBLOCK or PIN_EVENT_PINFREE, is PINBLOCK
unsigned char aucKsn[10]; ///< when event is PIN_EVENT_PINBLOCK or PIN_EVENT_PINFREE and using DUKPT, is KSN
} Pin_Block_Data;
```
>i## PedGetPinBlockRev
### Prototype
`int PedGetPinBlockRev(Pin_Block_Material_Type *pstMaterial, PinBlockEventCB callback, Pin_Block_Data *pData);`
### Function
* Get PinBlock
### Parameter
|Name|Type|description|
|-|-|-|
|pstMaterial|Pin_Block_Material_Type *|PINBLOCK material|
|callback|PinBlockEventCB|PIN event callback function|
|pData|Pin_Block_Data *|PIN event data|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>s## Example
```
#define EMV_L2_DEFAULT_PIN_LIST_4 "\x00\x04\x06\x0C"
#define EMV_L2_DEFAULT_PIN_LIST_5 "\x00\x06\x08\x0C\x0C"
#define EMV_L2_DEFAULT_PIN_LIST_6 "\x00\x04\x06\x08\x0A\x0C"
#define EMV_L2_DEFAULT_PIN_LIST_8 "\x00\x04\x05\x06\x07\x08\x0A\x0C"
#define EMV_L2_DEFAULT_PIN_LIST_9 "\x00\x04\x05\x06\x07\x08\x09\x0A\x0C"
#define EMV_L2_DEFAULT_PIN_LIST_10 "\x00\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C"
/*Online pin callback*/
static int giPinEvent = PIN_EVENT_NONE;
static int giPinErr = SUCCESS;
static void Util_PinBlockEventCB(Pin_Block_Event event, Pin_Block_Data *data)
{
if (-1 == data->iErrCode) {
giPinErr = ERR_TIMEOUT;
}
giPinEvent = event;
}
///< online PIN input
int Utils_InputOnlinePIN(unsigned int dispLine, unsigned int column, const char* panData, unsigned char *pinBlock, unsigned int *pinBlockSize, unsigned short timeout)
{
int iRet = ERR_CANCEL;
char dispBuff[20];
unsigned char ucPinBlkLen;
Pin_Block_Material_Type pPinMaterial = { 0 };
Pin_Block_Data pOnlinePin = { 0 };
if (!pinBlock || !pinBlockSize) {
return ERR_PARAM;
}
ucPinBlkLen = *pinBlockSize;
*pinBlockSize = 0;
giPinErr = SUCCESS;
giPinEvent = PIN_EVENT_NONE;
pPinMaterial.KeyArch = KEY_ARCH_MKSK;
pPinMaterial.KeyIdx = 0x06;
pPinMaterial.Mode = PINBLOCK_MODE_ISO9564_FMT0; // Compute the pattern of pinblock
pPinMaterial.TimeoutMs = timeout*1000;
pPinMaterial.TradeInfoLen = 0x00;
///< exp
pPinMaterial.ListLen = 10;
if (pPinMaterial.ListLen > sizeof(pPinMaterial.ExpPinLenList)) {
return ERR_PARAM;
}
memcpy(pPinMaterial.ExpPinLenList, EMV_L2_DEFAULT_PIN_LIST_10, pPinMaterial.ListLen);
///< pan
if (panData) {
pPinMaterial.PanLen = strlen(panData);
if (pPinMaterial.PanLen > sizeof(pPinMaterial.Pan)) {
return ERR_PARAM;
}
memcpy(pPinMaterial.Pan, panData, pPinMaterial.PanLen);
}
memset(dispBuff, '*', sizeof(dispBuff));
if (PedGetPinBlockRev(&pPinMaterial, Util_PinBlockEventCB, &pOnlinePin) != 0){
// PIN input times exceed the limit, error code is -307, corresponding hexadecimal: FECD
KbFlush();
return ERR_DRV;
}
while (1)
{
if (!GetSysStatus()) {
PedInputCancelRev();
iRet = ERR_CANCEL;
break;
}
switch (giPinEvent)
{
case PIN_EVENT_NONE: ///< No input
Sleep(50);
continue;
case PIN_EVENT_LEN: ///< Have input
giPinEvent = PIN_EVENT_NONE;
mmi_clearLine(dispLine);
mmi_display((DISP_VAlign)dispLine, column, "%*.*s", 0, pOnlinePin.ucPinLen, dispBuff);
continue;
case PIN_EVENT_COMPLETE:///< Input to complete
iRet = SUCCESS;
break;
case PIN_EVENT_PINFREE: ///< Press ok
iRet = SUCCESS;
break;
case PIN_EVENT_INVALID:
giPinEvent = PIN_EVENT_NONE;
continue;
case PIN_EVENT_EXIT: ///< cancel
iRet = ERR_CANCEL;
break;
case PIN_EVENT_ERR:
iRet = ERR_END;
if (giPinErr != SUCCESS) {
iRet = giPinErr;
}
break;
default:
iRet = ERR_TIMEOUT;
break;
}
break;
}
if (SUCCESS == iRet) {
if (pOnlinePin.ucPinBlkLen > ucPinBlkLen) {
return ERR_PARAM;
}
if (PIN_EVENT_PINFREE != giPinEvent) {
*pinBlockSize = pOnlinePin.ucPinBlkLen;
memcpy(pinBlock, pOnlinePin.aucPinBlock, pOnlinePin.ucPinBlkLen);
}
}
else {
pOnlinePin.ucPinBlkLen = 0;
memset(pOnlinePin.aucPinBlock, 0, sizeof(pOnlinePin.aucPinBlock));
}
KbFlush();
return iRet;
}
///< On line PIN input
int InputOnlinePINDemo(void)
{
int iRet = SUCCESS;
unsigned int iLen;
unsigned int dispLine = DISP_Line1;
unsigned char PINData[16];
char *panData = "1234567890123456";
mmi_clearLine(DISP_ClearALL);
mmi_display((DISP_VAlign)(dispLine++), 0, "Input online password");
mmi_display((DISP_VAlign)(dispLine++), 0, "Input your password");
mmi_display((DISP_VAlign)(dispLine--), 0, "No password press[O]");
/*!< --------------------------------------------------------------------*/
memset(PINData, 0, sizeof(PINData));
iLen = sizeof(PINData);
iRet = Utils_InputOnlinePIN((DISP_VAlign)(dispLine), 0, panData, PINData, &iLen, 60);
return iRet;
}
```