- simplify cak7 code (thanks to lpm11 and for all who tested)
[oscam.git] / csctapi / ifd_phoenix.c
blobf7b87c4453fb35e5301fe7bdd0fcfe08137f3d2e
1 /*
2 ifd_phoenix.c
3 This module provides IFD handling functions for Smartmouse/Phoenix reader.
4 */
6 #include "../globals.h"
8 #ifdef CARDREADER_PHOENIX
9 #include "../oscam-time.h"
10 #include "icc_async.h"
11 #include "ifd_db2com.h"
12 #include "ifd_phoenix.h"
13 #include "io_serial.h"
15 #define OK 0
16 #define ERROR 1
18 #define GPIO_PIN (1 << (reader->detect - 4))
20 static inline int reader_use_gpio(struct s_reader *reader)
22 return reader->use_gpio && reader->detect > 4;
25 static void set_gpio(struct s_reader *reader, int32_t level)
27 int ret = 0;
29 ret |= read(reader->gpio_outen, &reader->gpio, sizeof(reader->gpio));
30 reader->gpio |= GPIO_PIN;
31 ret |= write(reader->gpio_outen, &reader->gpio, sizeof(reader->gpio));
33 ret |= read(reader->gpio_out, &reader->gpio, sizeof(reader->gpio));
34 if(level > 0)
35 { reader->gpio |= GPIO_PIN; }
36 else
37 { reader->gpio &= ~GPIO_PIN; }
38 ret |= write(reader->gpio_out, &reader->gpio, sizeof(reader->gpio));
40 rdr_log_dbg(reader, D_IFD, "%s level: %d ret: %d", __func__, level, ret);
43 static void set_gpio_input(struct s_reader *reader)
45 int ret = 0;
46 ret |= read(reader->gpio_outen, &reader->gpio, sizeof(reader->gpio));
47 reader->gpio &= ~GPIO_PIN;
48 ret |= write(reader->gpio_outen, &reader->gpio, sizeof(reader->gpio));
49 rdr_log_dbg(reader, D_IFD, "%s ret:%d", __func__, ret);
52 static int32_t get_gpio(struct s_reader *reader)
54 int ret = 0;
55 set_gpio_input(reader);
56 ret = read(reader->gpio_in, &reader->gpio, sizeof(reader->gpio));
57 rdr_log_dbg(reader, D_IFD, "%s ok:%d ret:%d", __func__, reader->gpio & GPIO_PIN, ret);
58 if(reader->gpio & GPIO_PIN)
59 { return OK; }
60 else
61 { return ERROR; }
64 int32_t Phoenix_Init(struct s_reader *reader)
66 // First set card in reset state, to not change any parameters while communication ongoing
67 IO_Serial_RTS_Set(reader);
69 const struct s_cardreader *crdr_ops = reader->crdr;
70 if (!crdr_ops) return ERROR;
72 if(crdr_ops->flush) { IO_Serial_Flush(reader); }
74 // define reader->gpio number used for card detect and reset. ref to globals.h
75 if(reader_use_gpio(reader))
77 reader->gpio_outen = open("/dev/gpio/outen", O_RDWR);
78 reader->gpio_out = open("/dev/gpio/out", O_RDWR);
79 reader->gpio_in = open("/dev/gpio/in", O_RDWR);
80 rdr_log_dbg(reader, D_IFD, "init gpio_outen:%d gpio_out:%d gpio_in:%d",
81 reader->gpio_outen, reader->gpio_out, reader->gpio_in);
82 set_gpio_input(reader);
85 rdr_log_dbg(reader, D_IFD, "Initializing reader type=%d", reader->typ);
87 /* Default serial port settings */
88 if(reader->atr[0] == 0)
90 if(IO_Serial_SetParams(reader, DEFAULT_BAUDRATE, 8, PARITY_EVEN, 2, NULL, NULL)) { return ERROR; }
91 if(crdr_ops->flush) { IO_Serial_Flush(reader); }
93 return OK;
96 int32_t Phoenix_GetStatus(struct s_reader *reader, int32_t *status)
98 // detect card via defined reader->gpio
99 if(reader_use_gpio(reader))
101 *status = !get_gpio(reader);
102 return OK;
104 else
106 return IO_Serial_GetStatus(reader, status);
110 int32_t Phoenix_Reset(struct s_reader *reader, ATR *atr)
112 rdr_log_dbg(reader, D_IFD, "Resetting card");
113 int32_t ret;
114 int32_t i;
115 unsigned char buf[ATR_MAX_SIZE];
116 int32_t parity[3] = {PARITY_EVEN, PARITY_ODD, PARITY_NONE};
118 call(IO_Serial_SetBaudrate(reader, DEFAULT_BAUDRATE));
120 const struct s_cardreader *crdr_ops = reader->crdr;
121 if (!crdr_ops) return ERROR;
123 for(i = 0; i < 3; i++)
125 if(crdr_ops->flush) { IO_Serial_Flush(reader); }
126 if(crdr_ops->set_parity) { IO_Serial_SetParity(reader, parity[i]); }
128 ret = ERROR;
130 IO_Serial_Ioctl_Lock(reader, 1);
131 if(reader_use_gpio(reader))
132 { set_gpio(reader, 0); }
133 else
134 { IO_Serial_RTS_Set(reader); }
136 cs_sleepms(50);
138 // felix: set card reset hi (inactive)
139 if(reader_use_gpio(reader))
140 { set_gpio_input(reader); }
141 else
142 { IO_Serial_RTS_Clr(reader); }
143 cs_sleepms(50);
144 IO_Serial_Ioctl_Lock(reader, 0);
146 int32_t n = 0;
147 while(n < ATR_MAX_SIZE && !IO_Serial_Read(reader, 0, ATR_TIMEOUT, 1, buf + n))
148 { n++; }
149 if(n == 0)
150 { continue; }
151 if(ATR_InitFromArray(atr, buf, n) != ERROR)
152 { ret = OK; }
153 // Successfully retrieve ATR
154 if(ret == OK)
155 { break; }
158 return ret;
161 int32_t Phoenix_Close(struct s_reader *reader)
163 rdr_log_dbg(reader, D_IFD, "Closing phoenix device %s", reader->device);
164 if(reader_use_gpio(reader))
166 if(reader->gpio_outen > -1)
167 { close(reader->gpio_outen); }
168 if(reader->gpio_out > -1)
169 { close(reader->gpio_out); }
170 if(reader->gpio_in > -1)
171 { close(reader->gpio_in); }
173 IO_Serial_Close(reader);
174 return OK;
178 int32_t Phoenix_FastReset (struct s_reader * reader, int32_t delay)
180 IO_Serial_Ioctl_Lock(reader, 1);
181 if (reader_use_gpio(reader))
182 set_gpio(reader, 0);
183 else
184 IO_Serial_RTS_Set(reader);
186 cs_sleepms(delay);
188 // set card reset hi (inactive)
189 if (reader_use_gpio(reader))
190 set_gpio_input(reader);
191 else
192 IO_Serial_RTS_Clr(reader);
194 IO_Serial_Ioctl_Lock(reader, 0);
196 cs_sleepms(50);
198 IO_Serial_Flush(reader);
199 return 0;
203 static int32_t mouse_init(struct s_reader *reader)
205 const struct s_cardreader *crdr_ops = reader->crdr;
206 if (!crdr_ops) return ERROR;
208 if(detect_db2com_reader(reader))
210 reader->crdr = crdr_ops = &cardreader_db2com;
211 return crdr_ops->reader_init(reader);
214 reader->handle = open(reader->device, O_RDWR | O_NOCTTY | O_NONBLOCK);
215 if(reader->handle < 0)
217 rdr_log(reader, "ERROR: Opening device %s (errno=%d %s)",
218 reader->device, errno, strerror(errno));
219 return ERROR;
221 if(Phoenix_Init(reader))
223 rdr_log(reader, "ERROR: Phoenix_Init returns error");
224 Phoenix_Close(reader);
225 return ERROR;
227 return OK;
230 const struct s_cardreader cardreader_mouse =
232 .desc = "mouse",
233 .typ = R_MOUSE,
234 .flush = 1,
235 .read_written = 1,
236 .need_inverse = 1,
237 .reader_init = mouse_init,
238 .get_status = Phoenix_GetStatus,
239 .activate = Phoenix_Reset,
240 .transmit = IO_Serial_Transmit,
241 .receive = IO_Serial_Receive,
242 .close = Phoenix_Close,
243 .set_parity = IO_Serial_SetParity,
244 .set_baudrate = IO_Serial_SetBaudrate,
247 #endif