173 lines
5.0 KiB
C
173 lines
5.0 KiB
C
|
|
#include"../globals.h"
|
||
|
|
|
||
|
|
#ifdef CARDREADER_INTERNAL_AZBOX
|
||
|
|
|
||
|
|
#include "../oscam-time.h"
|
||
|
|
|
||
|
|
#include "atr.h"
|
||
|
|
#include "../extapi/openxcas/openxcas_api.h"
|
||
|
|
#include "../extapi/openxcas/openxcas_smartcard.h"
|
||
|
|
#include "io_serial.h"
|
||
|
|
|
||
|
|
#define OK 0
|
||
|
|
#define ERROR 1
|
||
|
|
|
||
|
|
static int32_t sc_mode;
|
||
|
|
|
||
|
|
static int32_t _GetStatus(struct s_reader *reader)
|
||
|
|
{
|
||
|
|
unsigned char buf[64];
|
||
|
|
memset(buf, 0, sizeof(buf));
|
||
|
|
|
||
|
|
return ioctl(reader->handle, SCARD_IOC_CHECKCARD, &buf);
|
||
|
|
}
|
||
|
|
|
||
|
|
static int32_t Azbox_Reader_Init(struct s_reader *reader)
|
||
|
|
{
|
||
|
|
rdr_log_dbg(reader, D_DEVICE, "Init");
|
||
|
|
|
||
|
|
if((reader->handle = openxcas_get_smartcard_device(0)) < 0)
|
||
|
|
{
|
||
|
|
rdr_log_dbg(reader, D_DEVICE, "Init reader failed");
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
rdr_log_dbg(reader, D_DEVICE, "Init reader %d succeeded", reader->handle);
|
||
|
|
return OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int32_t Azbox_SetMode(struct s_reader *reader, int32_t mode)
|
||
|
|
{
|
||
|
|
sc_mode = mode;
|
||
|
|
|
||
|
|
rdr_log(reader, "sc_mode %d", sc_mode);
|
||
|
|
return OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int32_t Azbox_GetStatus(struct s_reader *reader, int32_t *status)
|
||
|
|
{
|
||
|
|
int32_t card_status = _GetStatus(reader);
|
||
|
|
|
||
|
|
if(card_status != 0x03 && card_status != 0x01)
|
||
|
|
{ *status = 0; }
|
||
|
|
else
|
||
|
|
{ *status = 1; }
|
||
|
|
|
||
|
|
//rdr_log_dbg(reader, D_IFD, "openxcas sc: status = %d", *status);
|
||
|
|
return OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int32_t Azbox_Reset(struct s_reader *reader, ATR *atr)
|
||
|
|
{
|
||
|
|
rdr_log_dbg(reader, D_IFD, "Azbox resetting card");
|
||
|
|
unsigned char buf[ATR_MAX_SIZE];
|
||
|
|
int32_t card_status;
|
||
|
|
|
||
|
|
buf[0] = 0x03;
|
||
|
|
buf[1] = 0x01;
|
||
|
|
card_status = ioctl(reader->handle, SCARD_IOC_WARMRESET, &buf);
|
||
|
|
|
||
|
|
while((card_status = _GetStatus(reader)) != 0x03)
|
||
|
|
{ cs_sleepms(50); }
|
||
|
|
|
||
|
|
buf[0] = 0x02;
|
||
|
|
buf[1] = sc_mode;
|
||
|
|
sc_mode = ioctl(reader->handle, SCARD_IOC_CHECKCARD, &buf);
|
||
|
|
|
||
|
|
int32_t frequency;
|
||
|
|
frequency = reader->cardmhz * 10000L;
|
||
|
|
|
||
|
|
rdr_log(reader, "Set reader mhz = %.2f", (float) frequency / 1000000L);
|
||
|
|
|
||
|
|
int32_t n = 0;
|
||
|
|
buf[0] = 0x01;
|
||
|
|
n = ioctl(reader->handle, SCARD_IOC_CHECKCARD, &buf);
|
||
|
|
//cs_sleepms(50);
|
||
|
|
|
||
|
|
rdr_log_dbg(reader, D_IFD, "Waiting for card ATR Response...");
|
||
|
|
|
||
|
|
int32_t FI = (buf[n] >> 4);
|
||
|
|
|
||
|
|
int32_t Fi = atr_f_table[FI];
|
||
|
|
float fmax = atr_fs_table[FI];
|
||
|
|
|
||
|
|
int32_t D = ATR_DEFAULT_D;
|
||
|
|
int32_t DI = (buf[n] & 0x0F);
|
||
|
|
D = atr_d_table[DI];
|
||
|
|
|
||
|
|
rdr_log_dbg(reader, D_ATR, "Advertised max cardfrequency is %.2f (Fmax), frequency divider is %d", fmax / 1000000L, Fi);
|
||
|
|
|
||
|
|
if(D == 0) { D = 1;}
|
||
|
|
rdr_log_dbg(reader, D_ATR, "Bitrate adjustment is %d (D)", D);
|
||
|
|
|
||
|
|
rdr_log_dbg(reader, D_ATR, "Work ETU = %.2f us assuming card runs at %.2f Mhz", (double)((double)(1 / (double)D) * ((double)Fi / (double)((double)frequency / 1000000))), (float) frequency / 1000000);
|
||
|
|
|
||
|
|
rdr_log_dbg(reader, D_ATR, "Initial ETU = %.2f us", (double)372 / (double)frequency * 1000000);
|
||
|
|
|
||
|
|
rdr_log_dbg(reader, D_IFD, "ATR Fsmax is %.2f MHz, Work ETU is %.2f us, clocking card to %.2f MHz",
|
||
|
|
fmax / 1000000, (double)((double)(1 / (double)D) * ((double)Fi / (double)((double)frequency / 1000000))), (float) frequency / 1000000);
|
||
|
|
|
||
|
|
if(ATR_InitFromArray(atr, buf, n) == ERROR)
|
||
|
|
{
|
||
|
|
rdr_log(reader, "WARNING: ATR is invalid!");
|
||
|
|
return ERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
rdr_log_dbg(reader, D_IFD, "Card activated");
|
||
|
|
return OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int32_t Azbox_Reader_Close(struct s_reader *reader)
|
||
|
|
{
|
||
|
|
rdr_log_dbg(reader, D_IFD, "Deactivating card");
|
||
|
|
|
||
|
|
if((reader->handle = openxcas_release_smartcard_device(0)) > 0)
|
||
|
|
{
|
||
|
|
rdr_log_dbg(reader, D_DEVICE, "Closing reader %d", reader->handle);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
return OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int32_t Azbox_do_reset(struct s_reader *reader, struct s_ATR *atr,
|
||
|
|
int32_t (*rdr_activate_card)(struct s_reader *, struct s_ATR *, uint16_t deprecated),
|
||
|
|
int32_t (*rdr_get_cardsystem)(struct s_reader *, struct s_ATR *))
|
||
|
|
{
|
||
|
|
int32_t ret = 0;
|
||
|
|
int32_t i;
|
||
|
|
if(reader->azbox_mode != -1)
|
||
|
|
{
|
||
|
|
Azbox_SetMode(reader, reader->azbox_mode);
|
||
|
|
if(!rdr_activate_card(reader, atr, 0))
|
||
|
|
{ return -1; }
|
||
|
|
ret = rdr_get_cardsystem(reader, atr);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
for(i = 0; i < AZBOX_MODES; i++)
|
||
|
|
{
|
||
|
|
Azbox_SetMode(reader, i);
|
||
|
|
if(!rdr_activate_card(reader, atr, 0))
|
||
|
|
{ return -1; }
|
||
|
|
ret = rdr_get_cardsystem(reader, atr);
|
||
|
|
if(ret)
|
||
|
|
{ break; }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
const struct s_cardreader cardreader_internal_azbox =
|
||
|
|
{
|
||
|
|
.desc = "internal",
|
||
|
|
.typ = R_INTERNAL,
|
||
|
|
.reader_init = Azbox_Reader_Init,
|
||
|
|
.get_status = Azbox_GetStatus,
|
||
|
|
.activate = Azbox_Reset,
|
||
|
|
.transmit = IO_Serial_Transmit,
|
||
|
|
.receive = IO_Serial_Receive,
|
||
|
|
.close = Azbox_Reader_Close,
|
||
|
|
.do_reset = Azbox_do_reset,
|
||
|
|
};
|
||
|
|
|
||
|
|
#endif
|