oscam-2.26.01-11942-802-wit.../csctapi/ifd_phoenix.c

248 lines
6.0 KiB
C
Raw Normal View History

/*
ifd_phoenix.c
This module provides IFD handling functions for Smartmouse/Phoenix reader.
*/
#include "../globals.h"
#ifdef CARDREADER_PHOENIX
#include "../oscam-time.h"
#include "icc_async.h"
#include "ifd_db2com.h"
#include "ifd_phoenix.h"
#include "io_serial.h"
#define OK 0
#define ERROR 1
#define GPIO_PIN (1 << (reader->detect - 4))
static inline int reader_use_gpio(struct s_reader *reader)
{
return reader->use_gpio && reader->detect > 4;
}
static void set_gpio(struct s_reader *reader, int32_t level)
{
int ret = 0;
ret |= read(reader->gpio_outen, &reader->gpio, sizeof(reader->gpio));
reader->gpio |= GPIO_PIN;
ret |= write(reader->gpio_outen, &reader->gpio, sizeof(reader->gpio));
ret |= read(reader->gpio_out, &reader->gpio, sizeof(reader->gpio));
if(level > 0)
{ reader->gpio |= GPIO_PIN; }
else
{ reader->gpio &= ~GPIO_PIN; }
ret |= write(reader->gpio_out, &reader->gpio, sizeof(reader->gpio));
rdr_log_dbg(reader, D_IFD, "%s level: %d ret: %d", __func__, level, ret);
}
static void set_gpio_input(struct s_reader *reader)
{
int ret = 0;
ret |= read(reader->gpio_outen, &reader->gpio, sizeof(reader->gpio));
reader->gpio &= ~GPIO_PIN;
ret |= write(reader->gpio_outen, &reader->gpio, sizeof(reader->gpio));
rdr_log_dbg(reader, D_IFD, "%s ret:%d", __func__, ret);
}
static int32_t get_gpio(struct s_reader *reader)
{
int ret = 0;
set_gpio_input(reader);
ret = read(reader->gpio_in, &reader->gpio, sizeof(reader->gpio));
rdr_log_dbg(reader, D_IFD, "%s ok:%d ret:%d", __func__, reader->gpio & GPIO_PIN, ret);
if(reader->gpio & GPIO_PIN)
{ return OK; }
else
{ return ERROR; }
}
int32_t Phoenix_Init(struct s_reader *reader)
{
// First set card in reset state, to not change any parameters while communication ongoing
IO_Serial_RTS_Set(reader);
const struct s_cardreader *crdr_ops = reader->crdr;
if (!crdr_ops) return ERROR;
if(crdr_ops->flush) { IO_Serial_Flush(reader); }
// define reader->gpio number used for card detect and reset. ref to globals.h
if(reader_use_gpio(reader))
{
reader->gpio_outen = open("/dev/gpio/outen", O_RDWR);
reader->gpio_out = open("/dev/gpio/out", O_RDWR);
reader->gpio_in = open("/dev/gpio/in", O_RDWR);
rdr_log_dbg(reader, D_IFD, "init gpio_outen:%d gpio_out:%d gpio_in:%d",
reader->gpio_outen, reader->gpio_out, reader->gpio_in);
set_gpio_input(reader);
}
rdr_log_dbg(reader, D_IFD, "Initializing reader type=%d", reader->typ);
/* Default serial port settings */
if(reader->atr[0] == 0)
{
if(IO_Serial_SetParams(reader, DEFAULT_BAUDRATE, 8, PARITY_EVEN, 2, NULL, NULL)) { return ERROR; }
if(crdr_ops->flush) { IO_Serial_Flush(reader); }
}
return OK;
}
int32_t Phoenix_GetStatus(struct s_reader *reader, int32_t *status)
{
// detect card via defined reader->gpio
if(reader_use_gpio(reader))
{
*status = !get_gpio(reader);
return OK;
}
else
{
return IO_Serial_GetStatus(reader, status);
}
}
int32_t Phoenix_Reset(struct s_reader *reader, ATR *atr)
{
rdr_log_dbg(reader, D_IFD, "Resetting card");
int32_t ret;
int32_t i;
unsigned char buf[ATR_MAX_SIZE];
int32_t parity[3] = {PARITY_EVEN, PARITY_ODD, PARITY_NONE};
call(IO_Serial_SetBaudrate(reader, DEFAULT_BAUDRATE));
const struct s_cardreader *crdr_ops = reader->crdr;
if (!crdr_ops) return ERROR;
for(i = 0; i < 3; i++)
{
if(crdr_ops->flush) { IO_Serial_Flush(reader); }
if(crdr_ops->set_parity) { IO_Serial_SetParity(reader, parity[i]); }
ret = ERROR;
IO_Serial_Ioctl_Lock(reader, 1);
if(reader_use_gpio(reader))
{ set_gpio(reader, 0); }
else
{ IO_Serial_RTS_Set(reader); }
cs_sleepms(50);
// felix: set card reset hi (inactive)
if(reader_use_gpio(reader))
{ set_gpio_input(reader); }
else
{ IO_Serial_RTS_Clr(reader); }
cs_sleepms(50);
IO_Serial_Ioctl_Lock(reader, 0);
int32_t n = 0;
while(n < ATR_MAX_SIZE && !IO_Serial_Read(reader, 0, ATR_TIMEOUT, 1, buf + n))
{ n++; }
if(n == 0)
{ continue; }
if(ATR_InitFromArray(atr, buf, n) != ERROR)
{ ret = OK; }
// Successfully retrieve ATR
if(ret == OK)
{ break; }
}
return ret;
}
int32_t Phoenix_Close(struct s_reader *reader)
{
rdr_log_dbg(reader, D_IFD, "Closing phoenix device %s", reader->device);
if(reader_use_gpio(reader))
{
if(reader->gpio_outen > -1)
{ close(reader->gpio_outen); }
if(reader->gpio_out > -1)
{ close(reader->gpio_out); }
if(reader->gpio_in > -1)
{ close(reader->gpio_in); }
}
IO_Serial_Close(reader);
return OK;
}
/*
int32_t Phoenix_FastReset (struct s_reader * reader, int32_t delay)
{
IO_Serial_Ioctl_Lock(reader, 1);
if (reader_use_gpio(reader))
set_gpio(reader, 0);
else
IO_Serial_RTS_Set(reader);
cs_sleepms(delay);
// set card reset hi (inactive)
if (reader_use_gpio(reader))
set_gpio_input(reader);
else
IO_Serial_RTS_Clr(reader);
IO_Serial_Ioctl_Lock(reader, 0);
cs_sleepms(50);
IO_Serial_Flush(reader);
return 0;
}
*/
static int32_t mouse_init(struct s_reader *reader)
{
const struct s_cardreader *crdr_ops = reader->crdr;
if (!crdr_ops) return ERROR;
if(detect_db2com_reader(reader))
{
reader->crdr = crdr_ops = &cardreader_db2com;
return crdr_ops->reader_init(reader);
}
reader->handle = open(reader->device, O_RDWR | O_NOCTTY | O_NONBLOCK);
if(reader->handle < 0)
{
rdr_log(reader, "ERROR: Opening device %s (errno=%d %s)",
reader->device, errno, strerror(errno));
return ERROR;
}
if(Phoenix_Init(reader))
{
rdr_log(reader, "ERROR: Phoenix_Init returns error");
Phoenix_Close(reader);
return ERROR;
}
return OK;
}
const struct s_cardreader cardreader_mouse =
{
.desc = "mouse",
.typ = R_MOUSE,
.flush = 1,
.read_written = 1,
.need_inverse = 1,
.reader_init = mouse_init,
.get_status = Phoenix_GetStatus,
.activate = Phoenix_Reset,
.transmit = IO_Serial_Transmit,
.receive = IO_Serial_Receive,
.close = Phoenix_Close,
.set_parity = IO_Serial_SetParity,
.set_baudrate = IO_Serial_SetBaudrate,
};
#endif