- simplify cak7 code (thanks to lpm11 and for all who tested)
[oscam.git] / csctapi / protocol_t1.c
blob9adf9615a066bf1b50578f82162120ba53649cdf
1 #include "../globals.h"
2 #include "../oscam-time.h"
3 #ifdef WITH_CARDREADER
4 #include "icc_async.h"
6 #define OK 0
7 #define ERROR 1
9 /* Buffer sizes */
10 #define T1_BLOCK_MAX_SIZE 259
12 /* Types of block */
13 #define T1_BLOCK_I 0x00
14 #define T1_BLOCK_R_OK 0x80
15 #define T1_BLOCK_R_EDC_ERR 0x81
16 #define T1_BLOCK_R_OTHER_ERR 0x82
17 #define T1_BLOCK_S_RESYNCH_REQ 0xC0
18 #define T1_BLOCK_S_RESYNCH_RES 0xE0
19 #define T1_BLOCK_S_IFS_REQ 0xC1
20 #define T1_BLOCK_S_IFS_RES 0xE1
21 #define T1_BLOCK_S_ABORT_REQ 0xC2
22 #define T1_BLOCK_S_ABORT_RES 0xE2
23 #define T1_BLOCK_S_WTX_REQ 0xC3
24 #define T1_BLOCK_S_WTX_RES 0xE3
25 #define T1_BLOCK_S_VPP_ERR 0xE4
27 #define T1_BLOCK_NAD 0x00
29 #define T1_Block_GetNS(a) ((a[1] >> 6) & 0x01)
30 #define T1_Block_GetMore(a) ((a[1] >> 5) & 0x01)
31 #define T1_Block_GetNR(a) ((a[1] >> 4) & 0x01)
32 #define T1_Block_GetLen(a) a[2]
35 static unsigned char T1_Block_LRC(unsigned char *data, uint32_t length)
37 unsigned char lrc = 0x00;
38 uint32_t i;
39 for(i = 0; i < length; i++)
41 lrc ^= data[i];
43 return lrc;
46 static int32_t T1_Block_SendIBlock(struct s_reader *reader, uint8_t *block_data, unsigned char len, unsigned char *inf, unsigned char ns, int32_t more, uint32_t timeout)
48 int length = len + 4;
50 block_data[0] = T1_BLOCK_NAD;
51 block_data[1] = T1_BLOCK_I | ((ns << 6) & 0x40);
52 if(more)
54 block_data[1] |= 0x20;
56 block_data[2] = len;
57 if(len != 0x00)
59 memcpy(block_data + 3, inf, len);
61 block_data[len + 3] = T1_Block_LRC(block_data, len + 3);
63 return ICC_Async_Transmit(reader, length, 0, block_data, 0, timeout);
66 static int32_t T1_Block_SendRBlock(struct s_reader *reader, uint8_t *block_data, unsigned char type, unsigned char nr, uint32_t timeout)
68 int length = 4;
70 block_data[0] = T1_BLOCK_NAD;
71 block_data[1] = type | ((nr << 4) & 0x10);
72 block_data[2] = 0x00;
73 block_data[3] = T1_Block_LRC(block_data, 3);
75 return ICC_Async_Transmit(reader, length, 0, block_data, 0, timeout);
78 static int32_t T1_Block_SendSBlock(struct s_reader *reader, uint8_t *block_data, unsigned char type, unsigned char len, unsigned char *inf, uint32_t timeout)
80 int length = 4 + len;
82 block_data[0] = T1_BLOCK_NAD;
83 block_data[1] = type;
84 block_data[2] = len;
85 if(len != 0x00)
87 memcpy(block_data + 3, inf, len);
90 block_data[len + 3] = T1_Block_LRC(block_data, len + 3);
92 return ICC_Async_Transmit(reader, length, 0, block_data, 0, timeout);
95 static int32_t Protocol_T1_ReceiveBlock(struct s_reader *reader, uint8_t *block_data, uint32_t *block_length, uint8_t *rsp_type, uint32_t timeout)
97 int32_t ret, length;
99 /* Receive four mandatory bytes */
100 if(ICC_Async_Receive(reader, 4, block_data, 0, timeout))
102 ret = ERROR;
104 else
106 length = block_data[2];
107 if(length != 0x00)
109 *block_length = (length + 4 > T1_BLOCK_MAX_SIZE) ? T1_BLOCK_MAX_SIZE : length + 4;
111 /* Receive remaining bytes */
112 if(ICC_Async_Receive(reader, *block_length - 4, block_data + 4, 0, timeout))
114 ret = ERROR;
116 else
118 ret = OK;
121 else
123 ret = OK;
124 *block_length = 4;
127 *rsp_type = ((block_data[1] & 0x80) == T1_BLOCK_I) ? T1_BLOCK_I : (block_data[1] & 0xEF);
129 return ret;
132 int32_t Protocol_T1_Command(struct s_reader *reader, unsigned char *command, uint16_t command_len, unsigned char *rsp, uint16_t *lr)
134 uint8_t block_data[T1_BLOCK_MAX_SIZE];
135 uint8_t rsp_type, bytes, nr, wtx;
136 uint16_t counter;
137 int32_t ret, timeout;
138 bool more;
139 uint32_t block_length = 0;
140 if(command[1] == T1_BLOCK_S_IFS_REQ)
142 uint8_t inf = command[3];
144 /* Create an IFS request S-Block */
145 timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout
146 //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time
147 ret = T1_Block_SendSBlock(reader, block_data, T1_BLOCK_S_IFS_REQ, 1, &inf, timeout);
148 if(ret == ERROR)
150 rdr_log_dbg(reader, D_IFD, "Protocol: Sending block S(IFS request, %d)", inf);
153 /* Receive a block */
154 timeout = ICC_Async_GetTimings(reader, reader->BWT); // we are going to receive so set Block Waiting Timeout!
155 //cs_sleepus(reader->block_delay); // we were sending, now receiving so wait BGT time
156 ret = Protocol_T1_ReceiveBlock(reader, block_data, &block_length, &rsp_type, timeout);
158 if(ret == OK)
160 /* Positive IFS Response S-Block received */
161 if(rsp_type == T1_BLOCK_S_IFS_RES)
163 rdr_log_dbg(reader, D_IFD, "Protocol: Received block S(IFS response, %d)", block_data[3]);
167 return ret;
169 else if(command[1] == T1_BLOCK_S_RESYNCH_REQ)
171 /* Create an Resynch request S-Block */
172 timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout
173 //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time
174 ret = T1_Block_SendSBlock(reader, block_data, T1_BLOCK_S_RESYNCH_REQ, 0, NULL, timeout);
175 if(ret == ERROR)
177 rdr_log_dbg(reader, D_IFD, "Protocol: Sending block S(RESYNCH request)");
180 /* Receive a block */
181 timeout = ICC_Async_GetTimings(reader, reader->BWT); // we are going to receive so set Block Waiting Timeout!
182 //cs_sleepus(reader->block_delay); // we were sending, now receiving so wait BGT time
183 ret = Protocol_T1_ReceiveBlock(reader, block_data, &block_length, &rsp_type, timeout);
185 if(ret == OK)
187 /* Positive IFS Response S-Block received */
188 if(rsp_type == T1_BLOCK_S_RESYNCH_RES)
190 rdr_log_dbg(reader, D_IFD, "Protocol: Received block S(RESYNCH response)");
191 reader->ns = 0;
194 return ret;
197 /* Calculate the number of bytes to send */
198 counter = 0;
199 bytes = MIN(command_len, reader->ifsc);
201 /* See if chaining is needed */
202 more = (command_len > reader->ifsc);
204 /* Increment ns */
205 reader->ns = (reader->ns == 1) ? 0 : 1; //toggle from 0 to 1 and back
207 /* Create an I-Block */
208 timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout
209 //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time
210 ret = T1_Block_SendIBlock(reader, block_data, bytes, command, reader->ns, more, timeout);
211 rdr_log_dbg(reader, D_IFD, "Sending block I(%d,%d)", reader->ns, more);
213 while((ret == OK) && more)
215 /* Receive a block */
217 timeout = ICC_Async_GetTimings(reader, reader->BWT); // we are going to receive so set Block Waiting Timeout!
218 //cs_sleepus(reader->block_delay); // we were sending, now receiving so wait BGT time
219 ret = Protocol_T1_ReceiveBlock(reader, block_data, &block_length, &rsp_type, timeout);
221 if(ret == OK)
223 /* Positive ACK R-Block received */
224 if(rsp_type == T1_BLOCK_R_OK)
226 rdr_log_dbg(reader, D_IFD, "Protocol: Received block R(%d)", T1_Block_GetNR(block_data));
228 /* Increment ns */
229 reader->ns = (reader->ns == 1) ? 0 : 1; //toggle from 0 to 1 and back
231 /* Calculate the number of bytes to send */
232 counter += bytes;
233 bytes = MIN(command_len - counter, reader->ifsc);
235 /* See if chaining is needed */
236 more = (command_len - counter > reader->ifsc);
238 /* Send an I-Block */
239 timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout
240 //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time
241 ret = T1_Block_SendIBlock(reader, block_data, bytes, command + counter, reader->ns, more, timeout);
242 rdr_log_dbg(reader, D_IFD, "Protocol: Sending block I(%d,%d)", reader->ns, more);
245 else
247 rdr_log_dbg(reader, D_TRACE, "ERROR: T1 Command %02X not implemented", rsp_type);
248 return ERROR;
251 else
253 rdr_log_dbg(reader, D_TRACE, "ERROR: T1 Command returned error");
254 return ERROR;
258 /* Reset counter */
259 counter = 0;
260 more = 1;
261 wtx = 1;
263 while((ret == OK) && more)
266 /* Receive a block */
267 timeout = ICC_Async_GetTimings(reader, wtx * reader->BWT); // we are going to receive so set Block Waiting Timeout!
268 //cs_sleepus(reader->block_delay); // we were sending, now receiving so wait BGT time
269 ret = Protocol_T1_ReceiveBlock(reader, block_data, &block_length, &rsp_type, timeout);
270 wtx = 1; // reset WTX value since its only valid for first received I block
272 if(ret == OK)
274 if(rsp_type == T1_BLOCK_I)
276 rdr_log_dbg(reader, D_IFD, "Protocol: Received block I(%d,%d)", T1_Block_GetNS(block_data), T1_Block_GetMore(block_data));
278 bytes = T1_Block_GetLen(block_data);
280 /* Calculate nr */
281 nr = (T1_Block_GetNS(block_data) + 1) % 2;
283 if(counter + bytes > T1_BLOCK_MAX_SIZE)
285 return ERROR;
288 memcpy(rsp + counter, block_data + 3, bytes);
289 counter += bytes;
291 /* See if chaining is requested */
292 more = T1_Block_GetMore(block_data);
294 if(more)
296 /* Send R-Block */
297 timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout
298 //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time
299 ret = T1_Block_SendRBlock(reader, block_data, T1_BLOCK_R_OK, nr, timeout);
300 rdr_log_dbg(reader, D_IFD, "Protocol: Sending block R(%d)", nr);
303 else if(rsp_type == T1_BLOCK_S_WTX_REQ) /* WTX Request S-Block received */
305 /* Get wtx multiplier */
306 wtx = block_data[3];
307 rdr_log_dbg(reader, D_IFD, "Protocol: Received block S(WTX request, %d)", wtx);
309 /* Send an WTX response S-Block */
310 timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout
311 //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time
312 ret = T1_Block_SendSBlock(reader, block_data, T1_BLOCK_S_WTX_RES, 1, &wtx, timeout);
313 rdr_log_dbg(reader, D_IFD, "Protocol: Sending block S(WTX response, %d)", wtx);
315 else
317 rdr_log_dbg(reader, D_TRACE, "ERROR: T1 Command %02X not implemented in Receive Block", rsp_type);
318 ret = ERROR; //not implemented
323 if(ret == OK)
325 *lr = counter;
328 return ret;
330 #endif