- simplify cak7 code (thanks to lpm11 and for all who tested)
[oscam.git] / csctapi / ifd_cool.c
blob74860f215e83f1935b1005c18a4c34d276c5f6c6
1 /*
2 This module provides IFD handling functions for Coolstream internal reader.
3 */
5 #include"../globals.h"
7 #if defined(CARDREADER_INTERNAL_COOLAPI) || defined(CARDREADER_INTERNAL_COOLAPI2)
8 #include "../extapi/coolapi.h"
9 #include "../oscam-string.h"
10 #include "../oscam-time.h"
11 #include "atr.h"
13 #define OK 0
14 #define ERROR 1
16 extern int32_t cool_kal_opened;
18 struct cool_data
20 void *handle; //device handle for coolstream
21 uint8_t cardbuffer[512];
22 uint32_t cardbuflen;
23 int8_t pps;
26 static int32_t Cool_Init(struct s_reader *reader)
28 char *device = reader->device;
29 int32_t reader_nb = 0;
30 // this is to stay compatible with older config.
31 if(cs_strlen(device))
32 { reader_nb = atoi((const char *)device); }
33 if(reader_nb > 1)
35 // there are only 2 readers in the coolstream : 0 or 1
36 rdr_log(reader, "Coolstream reader device can only be 0 or 1");
37 return 0;
39 if(!cs_malloc(&reader->crdr_data, sizeof(struct cool_data)))
40 { return ERROR; }
41 struct cool_data *crdr_data = reader->crdr_data;
42 if(cnxt_smc_open(&crdr_data->handle, &reader_nb, NULL, NULL))
43 { return 0; }
45 int32_t ret = cnxt_smc_enable_flow_control(crdr_data->handle, 0);
46 coolapi_check_error("cnxt_smc_enable_flow_control", ret);
48 crdr_data->cardbuflen = 0;
49 crdr_data->pps = 0;
50 return OK;
53 static int32_t Cool_FastReset(struct s_reader *reader)
55 struct cool_data *crdr_data = reader->crdr_data;
56 int32_t n = ATR_MAX_SIZE, ret;
57 unsigned char buf[ATR_MAX_SIZE];
59 //reset card
60 ret = cnxt_smc_reset_card(crdr_data->handle, ATR_TIMEOUT, NULL, NULL);
61 coolapi_check_error("cnxt_smc_reset_card", ret);
62 cs_sleepms(50);
63 ret = cnxt_smc_get_atr(crdr_data->handle, buf, &n);
64 coolapi_check_error("cnxt_smc_get_atr", ret);
66 return OK;
69 static int32_t Cool_SetClockrate(struct s_reader *reader, int32_t mhz)
71 struct cool_data *crdr_data = reader->crdr_data;
72 uint32_t clk;
73 clk = mhz * 10000;
74 int32_t ret = cnxt_smc_set_clock_freq(crdr_data->handle, clk);
75 coolapi_check_error("cnxt_smc_set_clock_freq", ret);
76 call(Cool_FastReset(reader));
77 rdr_log_dbg(reader, D_DEVICE, "COOL: clock successfully set to %i", clk);
78 return OK;
81 static int32_t Cool_GetStatus(struct s_reader *reader, int32_t *in)
83 struct cool_data *crdr_data = reader->crdr_data;
84 if(cool_kal_opened)
86 int32_t state;
87 int32_t ret = cnxt_smc_get_state(crdr_data->handle, &state);
88 if(ret)
90 coolapi_check_error("cnxt_smc_get_state", ret);
91 return ERROR;
93 //state = 0 no card, 1 = not ready, 2 = ready
94 if(state)
95 { *in = 1; } //CARD, even if not ready report card is in, or it will never get activated
96 else
97 { *in = 0; } //NOCARD
99 else
101 *in = 0;
103 return OK;
106 static int32_t Cool_Reset(struct s_reader *reader, ATR *atr)
108 struct cool_data *crdr_data = reader->crdr_data;
109 int32_t ret;
111 if(!reader->ins7e11_fast_reset)
113 //set freq to reader->cardmhz if necessary
114 uint32_t clk;
116 ret = cnxt_smc_get_clock_freq(crdr_data->handle, &clk);
117 coolapi_check_error("cnxt_smc_get_clock_freq", ret);
118 if(clk / 10000 != (uint32_t)reader->cardmhz)
120 rdr_log_dbg(reader, D_DEVICE, "COOL: clock freq: %i, scheduling change to %i for card reset",
121 clk, reader->cardmhz * 10000);
122 call(Cool_SetClockrate(reader, reader->cardmhz));
125 else
127 rdr_log(reader, "Doing fast reset");
130 //reset card
131 ret = cnxt_smc_reset_card(crdr_data->handle, ATR_TIMEOUT, NULL, NULL);
132 coolapi_check_error("cnxt_smc_reset_card", ret);
133 cs_sleepms(50);
134 int32_t n = ATR_MAX_SIZE;
135 unsigned char buf[ATR_MAX_SIZE];
136 ret = cnxt_smc_get_atr(crdr_data->handle, buf, &n);
137 coolapi_check_error("cnxt_smc_get_atr", ret);
139 call(!(ATR_InitFromArray(atr, buf, n) != ERROR));
141 cs_sleepms(50);
142 return OK;
146 static int32_t Cool_Transmit(struct s_reader *reader, unsigned char *sent, uint32_t size, uint32_t expectedlen, uint32_t UNUSED(delay), uint32_t UNUSED(timeout))
148 struct cool_data *crdr_data = reader->crdr_data;
149 int32_t ret;
150 memset(crdr_data->cardbuffer, 0, 512);
152 if(reader->protocol_type == ATR_PROTOCOL_TYPE_T0)
154 crdr_data->cardbuflen = expectedlen;
155 ret = cnxt_smc_read_write(crdr_data->handle, 0, sent, size, crdr_data->cardbuffer, &crdr_data->cardbuflen, 0, NULL);
157 else
159 crdr_data->cardbuflen = 512;
160 ret = cnxt_smc_read_write(crdr_data->handle, 0, sent, size, crdr_data->cardbuffer, &crdr_data->cardbuflen, 4000, NULL);
163 coolapi_check_error("cnxt_smc_read_write", ret);
165 rdr_log_dump_dbg(reader, D_DEVICE, sent, size, "COOL Transmit:");
167 if(ret)
168 { return ERROR; }
169 return OK;
172 static int32_t Cool_Receive(struct s_reader *reader, unsigned char *data, uint32_t size, uint32_t UNUSED(delay), uint32_t UNUSED(timeout))
174 struct cool_data *crdr_data = reader->crdr_data;
175 if(size > crdr_data->cardbuflen)
176 { size = crdr_data->cardbuflen; } //never read past end of buffer
177 memcpy(data, crdr_data->cardbuffer, size);
178 crdr_data->cardbuflen -= size;
179 memmove(crdr_data->cardbuffer, crdr_data->cardbuffer + size, crdr_data->cardbuflen);
180 rdr_log_dump_dbg(reader, D_DEVICE, data, size, "COOL Receive:");
181 return OK;
184 static void Cool_Print_Comm_Parameters(struct s_reader *reader)
186 struct cool_data *crdr_data = reader->crdr_data;
187 uint16_t F;
188 uint8_t D;
189 int32_t ret = cnxt_smc_get_F_D_factors(crdr_data->handle, &F, &D);
190 coolapi_check_error("cnxt_smc_get_F_D_factors", ret);
192 char *protocol;
193 CNXT_SMC_COMM comm;
194 ret = cnxt_smc_get_comm_parameters(crdr_data->handle, &comm);
195 coolapi_check_error("cnxt_smc_get_comm_parameters", ret);
196 if(comm.protocol == 0x01)
197 { protocol = "T0"; }
198 else if(comm.protocol == 0x02)
199 { protocol = "T1"; }
200 else if(comm.protocol == 0x04)
201 { protocol = "T14"; }
202 else
203 { protocol = "unknown"; }
205 rdr_log(reader, "Driver Settings: Convention=%s, Protocol=%s, FI=%i, F=%i, N=%i, DI=%i, D=%i, PI1=%i, PI2=%i, II=%i, TXRetries=%i, RXRetries=%i, FilterProtocolBytes=%i", comm.convention ? "Inverse" : "Direct", protocol, comm.FI, F, comm.N, comm.DI, D, comm.PI1, comm.PI2, comm.II, comm.retries.TXRetries, comm.retries.RXRetries, comm.filterprotocolbytes);
207 CNXT_SMC_TIMEOUT timeout;
208 ret = cnxt_smc_get_config_timeout(crdr_data->handle, &timeout);
209 coolapi_check_error("cnxt_smc_get_config_timeout", ret);
211 rdr_log(reader, "Driver Timeouts: CardActTime=%i, CardDeactTime=%i, ATRSTime=%i, ATRDTime=%i, BLKTime=%i, CHTime=%i, CHGuardTime=%i, BKGuardTime=%i", timeout.CardActTime, timeout.CardDeactTime, timeout.ATRSTime, timeout.ATRDTime, timeout.BLKTime, timeout.CHTime, timeout.CHGuardTime, timeout.BKGuardTime);
215 static int32_t Cool_WriteSettings(struct s_reader *reader, struct s_cardreader_settings *s)
217 struct cool_data *crdr_data = reader->crdr_data;
218 //first set freq back to reader->mhz if necessary
219 uint32_t clk;
220 int32_t ret = cnxt_smc_get_clock_freq(crdr_data->handle, &clk);
221 coolapi_check_error("cnxt_smc_get_clock_freq", ret);
222 if(clk / 10000 != (uint32_t)reader->mhz)
224 rdr_log_dbg(reader, D_DEVICE, "COOL: clock freq: %i, scheduling change to %i", clk, reader->mhz * 10000);
225 call(Cool_SetClockrate(reader, reader->mhz));
228 uint32_t BLKTime = 0, CHTime = 0;
229 uint8_t BKGuardTime = 0;
230 switch(reader->protocol_type)
232 case ATR_PROTOCOL_TYPE_T1:
233 if(reader->BWT > 11)
234 { BLKTime = (reader->BWT - 11); }
235 if(reader->CWT > 11)
236 { CHTime = (reader->CWT - 11); }
237 if(s->BGT > 11)
238 { BKGuardTime = (s->BGT - 11); }
239 else
240 { BKGuardTime = 11; } //For T1, the BGT minimum time shall be 22 work etus. BGT is effectively offset by 11 etus internally.
241 if(!crdr_data->pps)
243 ret = cnxt_smc_set_F_D_factors(crdr_data->handle, s->F, s->D);
244 coolapi_check_error("cnxt_smc_set_F_D_factors", ret);
246 break;
247 case ATR_PROTOCOL_TYPE_T0:
248 case ATR_PROTOCOL_TYPE_T14:
249 default:
250 BLKTime = 0;
251 if(s->WWT > 12)
252 { CHTime = (s->WWT - 12); }
253 if(s->BGT > 12)
254 { BKGuardTime = (s->BGT - 12); }
255 if(BKGuardTime < 4)
256 { BKGuardTime = 4; } //For T0, the BGT minimum time shall be 16 work etus. BGT is effectively offset by 12 etus internally.
257 if(!crdr_data->pps)
259 if(reader->protocol_type == ATR_PROTOCOL_TYPE_T14)
261 ret = cnxt_smc_set_F_D_factors(crdr_data->handle, 620, 1);
263 else
265 ret = cnxt_smc_set_F_D_factors(crdr_data->handle, s->F, s->D);
267 coolapi_check_error("cnxt_smc_set_F_D_factors", ret);
269 break;
271 ret = cnxt_smc_set_convention(crdr_data->handle, reader->convention);
272 coolapi_check_error("cnxt_smc_set_convention", ret);
274 CNXT_SMC_TIMEOUT timeout;
275 ret = cnxt_smc_get_config_timeout(crdr_data->handle, &timeout);
276 coolapi_check_error("cnxt_smc_get_config_timeout", ret);
277 timeout.BLKTime = BLKTime;
278 timeout.CHTime = CHTime;
279 timeout.CHGuardTime = s->EGT;
280 timeout.BKGuardTime = BKGuardTime;
281 ret = cnxt_smc_set_config_timeout(crdr_data->handle, timeout);
282 coolapi_check_error("cnxt_smc_set_config_timeout", ret);
284 Cool_Print_Comm_Parameters(reader);
286 return OK;
289 static int32_t Cool_Close(struct s_reader *reader)
291 struct cool_data *crdr_data = reader->crdr_data;
292 if(cool_kal_opened)
294 int32_t ret = cnxt_smc_close(crdr_data->handle);
295 coolapi_check_error("cnxt_smc_close", ret);
297 return OK;
300 static int32_t Cool_SetProtocol(struct s_reader *reader, unsigned char *params, uint32_t *UNUSED(length), uint32_t UNUSED(len_request))
302 struct cool_data *crdr_data = reader->crdr_data;
303 unsigned char pps[4], response[6];
304 uint8_t len = 0;
306 //Driver sets PTSS and PCK on its own
307 pps[0] = params[1]; //PPS0
308 pps[1] = params[2]; //PPS1
310 int32_t ret = cnxt_smc_start_pps(crdr_data->handle, pps, response, &len, 1);
311 coolapi_check_error("cnxt_smc_start_pps", ret);
312 if(ret)
313 { return ERROR; }
314 crdr_data->pps = 1;
315 return OK;
318 const struct s_cardreader cardreader_internal_cool =
320 .desc = "internal",
321 .typ = R_INTERNAL,
322 .max_clock_speed = 1,
323 .reader_init = Cool_Init,
324 .get_status = Cool_GetStatus,
325 .activate = Cool_Reset,
326 .transmit = Cool_Transmit,
327 .receive = Cool_Receive,
328 .close = Cool_Close,
329 .write_settings = Cool_WriteSettings,
330 .set_protocol = Cool_SetProtocol,
333 #endif