1 #include "../globals.h"
2 #include "../oscam-time.h"
10 #define T1_BLOCK_MAX_SIZE 259
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;
39 for(i
= 0; i
< length
; i
++)
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
)
50 block_data
[0] = T1_BLOCK_NAD
;
51 block_data
[1] = T1_BLOCK_I
| ((ns
<< 6) & 0x40);
54 block_data
[1] |= 0x20;
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
)
70 block_data
[0] = T1_BLOCK_NAD
;
71 block_data
[1] = type
| ((nr
<< 4) & 0x10);
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
)
82 block_data
[0] = T1_BLOCK_NAD
;
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
)
99 /* Receive four mandatory bytes */
100 if(ICC_Async_Receive(reader
, 4, block_data
, 0, timeout
))
106 length
= block_data
[2];
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
))
127 *rsp_type
= ((block_data
[1] & 0x80) == T1_BLOCK_I
) ? T1_BLOCK_I
: (block_data
[1] & 0xEF);
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
;
137 int32_t ret
, timeout
;
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
);
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
);
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]);
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
);
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
);
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)");
197 /* Calculate the number of bytes to send */
199 bytes
= MIN(command_len
, reader
->ifsc
);
201 /* See if chaining is needed */
202 more
= (command_len
> reader
->ifsc
);
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
);
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
));
229 reader
->ns
= (reader
->ns
== 1) ? 0 : 1; //toggle from 0 to 1 and back
231 /* Calculate the number of bytes to send */
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
);
247 rdr_log_dbg(reader
, D_TRACE
, "ERROR: T1 Command %02X not implemented", rsp_type
);
253 rdr_log_dbg(reader
, D_TRACE
, "ERROR: T1 Command returned error");
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
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
);
281 nr
= (T1_Block_GetNS(block_data
) + 1) % 2;
283 if(counter
+ bytes
> T1_BLOCK_MAX_SIZE
)
288 memcpy(rsp
+ counter
, block_data
+ 3, bytes
);
291 /* See if chaining is requested */
292 more
= T1_Block_GetMore(block_data
);
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 */
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
);
317 rdr_log_dbg(reader
, D_TRACE
, "ERROR: T1 Command %02X not implemented in Receive Block", rsp_type
);
318 ret
= ERROR
; //not implemented