OSHW-DEIMOS/SOFTWARE/A64-TERES/linux-a64/drivers/char/sunxi-scr/smartcard.c
Dimitar Gamishev f9b0e7a283 linux
2017-10-13 14:07:04 +03:00

322 lines
4.9 KiB
C
Executable File

//code for iso7816 smart card
#include <linux/module.h>
#include "smartcard.h"
#include "sunxi-scr-common.h"
extern u32 scr_debug_mask;
uint32_t smartcard_params_init(pscatr_struct pscatr)
{
pscatr->TS = 0x3B;
pscatr->TK_NUM = 0x00;
pscatr->T = 0; //T=0 Protocol
pscatr->FMAX = 4; //4MHz
pscatr->F = 372;
pscatr->D = 1;
pscatr->I = 50; //50mA
pscatr->P = 5; //5V
pscatr->N = 2;
return 0;
}
uint32_t smartcard_atr_decode(pscr_struct pscr, pscatr_struct pscatr, uint8_t* pdata, ppps_struct pps, uint32_t with_ts)
{
uint32_t index=0;
uint8_t temp;
uint32_t i;
dprintk(DEBUG_INIT, "%s: enter!!\n", __func__);
pps->ppss = 0xff; //PPSS
pps->pps0 = 0;
if(with_ts)
{
pscatr->TS = pdata[0]; //TS
index ++;
}
temp = pdata[index]; //T0
index ++;
pscatr->TK_NUM = temp & 0xf;
if(temp & 0x10) //TA1
{
smartcard_ta1_decode(pscatr, pdata[index]);
pps->pps0 |= 0x1<<4;
pps->pps1 = pdata[index];
index ++;
}
if(temp & 0x20) //TB1
{
smartcard_tb1_decode(pscatr, pdata[index]);
index++;
}
if(temp & 0x40) //TC1
{
pscatr->N = pdata[index] & 0xff;
index ++;
}
if(temp & 0x80) //TD1
{
dprintk(DEBUG_INIT, "%s: TD1 parse 0x%x !!\n", __func__, pdata[index]);
temp = pdata[index];
pscatr->T = temp & 0xf;
pps->pps0 |= temp & 0xf;
if(pscatr->T == 1)
scr_set_t_protocol(pscr, 1);
else
scr_set_t_protocol(pscr, 0);
if(pscatr->N == 0xff) //Adjust Guard Time
{
if(pscatr->T == 1)
pscatr->N = 1;
else
pscatr->N = 2;
}
index ++;
}
else
{
if(pscatr->N == 0xff) pscatr->N = 2;
goto rx_tk;
}
if(temp & 0x10) //TA2
{
dprintk(DEBUG_INIT, "TA2 Exist!!\n");
index ++;
}
if(temp & 0x20) //TB2
{
dprintk(DEBUG_INIT, "TB2 Exist!!\n");
index ++;
}
if(temp & 0x40) //TC2
{
dprintk(DEBUG_INIT, "TC2 Exist!!\n");
index ++;
}
if(temp & 0x80) //TD2
{
dprintk(DEBUG_INIT, "TD2 Exist!!\n");
temp = pdata[index];
index ++;
}
else
{
goto rx_tk;
}
if(temp & 0x10) //TA3
{
dprintk(DEBUG_INIT, "TA3 Exist!!\n");
index ++;
}
if(temp & 0x20) //TB3
{
dprintk(DEBUG_INIT, "TB3 Exist!!\n");
index ++;
}
if(temp & 0x40) //TC3
{
dprintk(DEBUG_INIT, "TC3 Exist!!\n");
index ++;
}
if(temp & 0x80) //TD3
{
dprintk(DEBUG_INIT, "TD3 Exist!!\n");
temp = pdata[index];
index ++;
}
else
{
goto rx_tk;
}
if(temp & 0x10) //TA4
{
dprintk(DEBUG_INIT, "TA4 Exist!!\n");
index ++;
}
if(temp & 0x20) //TB4
{
dprintk(DEBUG_INIT, "TB4 Exist!!\n");
index ++;
}
if(temp & 0x40) //TC4
{
dprintk(DEBUG_INIT, "TC4 Exist!!\n");
index ++;
}
if(temp & 0x80) //TD4
{
dprintk(DEBUG_INIT, "TD4 Exist!!\n");
temp = pdata[index];
index ++;
}
else
{
goto rx_tk;
}
rx_tk:
for(i=0; i<(pscatr->TK_NUM); i++)
{
pscatr->TK[i] = pdata[index++];
}
pps->pck = pps->ppss;
pps->pck ^= pps->pps0;
if(pps->pps0&(0x1<<4))
{
pps->pck ^= pps->pps1;
}
if(pps->pps0&(0x1<<5))
{
pps->pck ^= pps->pps2;
}
if(pps->pps0&(0x1<<6))
{
pps->pck ^= pps->pps3;
}
return 0;
}
void smartcard_ta1_decode(pscatr_struct pscatr, uint8_t ta1)
{
uint8_t temp = ta1;
dprintk(DEBUG_INIT, "%s: enter!!\n", __func__);
switch((temp>>4)&0xf)
{
case 0x0:
pscatr->FMAX = 4;
pscatr->F = 372;
break;
case 0x1:
pscatr->FMAX = 5;
pscatr->F = 372;
break;
case 0x2:
pscatr->FMAX = 6;
pscatr->F = 558;
break;
case 0x3:
pscatr->FMAX = 8;
pscatr->F = 744;
break;
case 0x4:
pscatr->FMAX = 12;
pscatr->F = 1116;
break;
case 0x5:
pscatr->FMAX = 16;
pscatr->F = 1488;
break;
case 0x6:
pscatr->FMAX = 20;
pscatr->F = 1860;
break;
case 0x9:
pscatr->FMAX = 5;
pscatr->F = 512;
break;
case 0xA:
pscatr->FMAX = 7;
pscatr->F = 768;
break;
case 0xB:
pscatr->FMAX = 10;
pscatr->F = 1024;
break;
case 0xC:
pscatr->FMAX = 15;
pscatr->F = 1536;
break;
case 0xD:
pscatr->FMAX = 20;
pscatr->F = 2048;
break;
default: //0x7/0x8/0xE/0xF
pscatr->FMAX = 4;
pscatr->F = 372;
dprintk(DEBUG_INIT, "Unsupport ta1 = 0x%x\n", ta1);
break;
}
switch(temp&0xf)
{
case 0x1:
pscatr->D = 1;
break;
case 0x2:
pscatr->D = 2;
break;
case 0x3:
pscatr->D = 4;
break;
case 0x4:
pscatr->D = 8;
break;
case 0x5:
pscatr->D = 16;
break;
case 0x6:
pscatr->D = 32;
break;
case 0x8:
pscatr->D = 12;
break;
case 0x9:
pscatr->D = 20;
break;
default: //0x0/0x7/0xA/0xB/0xC/0xD/0xE/0xF
pscatr->D = 1;
dprintk(DEBUG_INIT, "Unsupport ta1 = 0x%x\n", ta1);
break;
}
}
void smartcard_tb1_decode(pscatr_struct pscatr, uint8_t tb1)
{
uint8_t temp = tb1;
dprintk(DEBUG_INIT, "%s: enter!!\n", __func__);
switch((temp>>5)&0x3)
{
case 0:
pscatr->I = 25;
break;
case 1:
pscatr->I = 50;
break;
case 2:
pscatr->I = 100;
break;
default:
pscatr->I = 50;
}
if(((temp&0x1f)>4)&&((temp&0x1f)<26))
{
pscatr->P = (temp&0x1f); //5~25 in Volts
}
else if((temp&0x1f)==0)
{
pscatr->P = 0; //NC
}
else
{
pscatr->P = 5; //NC
}
}