0
|
1 #include "b_cas_card.h"
|
|
2 #include "b_cas_card_error_code.h"
|
|
3
|
|
4 #include <stdlib.h>
|
|
5 #include <string.h>
|
|
6
|
|
7 #include <math.h>
|
|
8
|
|
9 #if defined(WIN32)
|
|
10 #include <windows.h>
|
|
11 #endif
|
|
12 #include <winscard.h>
|
|
13
|
|
14 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
15 inner structures
|
|
16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
17 typedef struct {
|
|
18
|
|
19 SCARDCONTEXT mng;
|
|
20 SCARDHANDLE card;
|
|
21
|
|
22 uint8_t *pool;
|
|
23 char *reader;
|
|
24
|
|
25 uint8_t *sbuf;
|
|
26 uint8_t *rbuf;
|
|
27
|
|
28 B_CAS_INIT_STATUS stat;
|
|
29
|
|
30 B_CAS_ID id;
|
|
31 int32_t id_max;
|
|
32
|
|
33 B_CAS_PWR_ON_CTRL_INFO pwc;
|
|
34 int32_t pwc_max;
|
|
35
|
|
36 } B_CAS_CARD_PRIVATE_DATA;
|
|
37
|
|
38 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
39 constant values
|
|
40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
41 static const uint8_t INITIAL_SETTING_CONDITIONS_CMD[] = {
|
|
42 0x90, 0x30, 0x00, 0x00, 0x00,
|
|
43 };
|
|
44
|
|
45 static const uint8_t CARD_ID_INFORMATION_ACQUIRE_CMD[] = {
|
|
46 0x90, 0x32, 0x00, 0x00, 0x00,
|
|
47 };
|
|
48
|
|
49 static const uint8_t POWER_ON_CONTROL_INFORMATION_REQUEST_CMD[] = {
|
|
50 0x90, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
|
|
51 };
|
|
52
|
|
53 static const uint8_t ECM_RECEIVE_CMD_HEADER[] = {
|
|
54 0x90, 0x34, 0x00, 0x00,
|
|
55 };
|
|
56
|
|
57 static const uint8_t EMM_RECEIVE_CMD_HEADER[] = {
|
|
58 0x90, 0x36, 0x00, 0x00,
|
|
59 };
|
|
60
|
|
61 #define B_CAS_BUFFER_MAX (4*1024)
|
|
62
|
|
63 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
64 function prottypes (interface method)
|
|
65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
66 static void release_b_cas_card(void *bcas);
|
|
67 static int init_b_cas_card(void *bcas);
|
|
68 static int get_init_status_b_cas_card(void *bcas, B_CAS_INIT_STATUS *stat);
|
|
69 static int get_id_b_cas_card(void *bcas, B_CAS_ID *dst);
|
|
70 static int get_pwr_on_ctrl_b_cas_card(void *bcas, B_CAS_PWR_ON_CTRL_INFO *dst);
|
|
71 static int proc_ecm_b_cas_card(void *bcas, B_CAS_ECM_RESULT *dst, uint8_t *src, int len);
|
|
72 static int proc_emm_b_cas_card(void *bcas, uint8_t *src, int len);
|
|
73
|
|
74 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
75 global function implementation
|
|
76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
77 B_CAS_CARD *create_b_cas_card()
|
|
78 {
|
|
79 int n;
|
|
80
|
|
81 B_CAS_CARD *r;
|
|
82 B_CAS_CARD_PRIVATE_DATA *prv;
|
|
83
|
|
84 n = sizeof(B_CAS_CARD) + sizeof(B_CAS_CARD_PRIVATE_DATA);
|
|
85 prv = (B_CAS_CARD_PRIVATE_DATA *)calloc(1, n);
|
|
86 if(prv == NULL){
|
|
87 return NULL;
|
|
88 }
|
|
89
|
|
90 r = (B_CAS_CARD *)(prv+1);
|
|
91
|
|
92 r->private_data = prv;
|
|
93
|
|
94 r->release = release_b_cas_card;
|
|
95 r->init = init_b_cas_card;
|
|
96 r->get_init_status = get_init_status_b_cas_card;
|
|
97 r->get_id = get_id_b_cas_card;
|
|
98 r->get_pwr_on_ctrl = get_pwr_on_ctrl_b_cas_card;
|
|
99 r->proc_ecm = proc_ecm_b_cas_card;
|
|
100 r->proc_emm = proc_emm_b_cas_card;
|
|
101
|
|
102 return r;
|
|
103 }
|
|
104
|
|
105 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
106 function prottypes (private method)
|
|
107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
108 static B_CAS_CARD_PRIVATE_DATA *private_data(void *bcas);
|
|
109 static void teardown(B_CAS_CARD_PRIVATE_DATA *prv);
|
|
110 static int change_id_max(B_CAS_CARD_PRIVATE_DATA *prv, int max);
|
|
111 static int change_pwc_max(B_CAS_CARD_PRIVATE_DATA *prv, int max);
|
|
112 static int connect_card(B_CAS_CARD_PRIVATE_DATA *prv, const char *reader_name);
|
|
113 static void extract_power_on_ctrl_response(B_CAS_PWR_ON_CTRL *dst, uint8_t *src);
|
|
114 static void extract_mjd(int *yy, int *mm, int *dd, int mjd);
|
|
115 static int setup_ecm_receive_command(uint8_t *dst, uint8_t *src, int len);
|
|
116 static int setup_emm_receive_command(uint8_t *dst, uint8_t *src, int len);
|
|
117 static int32_t load_be_uint16(uint8_t *p);
|
|
118 static int64_t load_be_uint48(uint8_t *p);
|
|
119
|
|
120 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
121 interface method implementation
|
|
122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
123 static void release_b_cas_card(void *bcas)
|
|
124 {
|
|
125 B_CAS_CARD_PRIVATE_DATA *prv;
|
|
126
|
|
127 prv = private_data(bcas);
|
|
128 if(prv == NULL){
|
|
129 /* do nothing */
|
|
130 return;
|
|
131 }
|
|
132
|
|
133 teardown(prv);
|
|
134 free(prv);
|
|
135 }
|
|
136
|
|
137 static int init_b_cas_card(void *bcas)
|
|
138 {
|
|
139 int m;
|
|
140 LONG ret;
|
|
141 DWORD len;
|
|
142
|
|
143 B_CAS_CARD_PRIVATE_DATA *prv;
|
|
144
|
|
145 prv = private_data(bcas);
|
|
146 if(prv == NULL){
|
|
147 return B_CAS_CARD_ERROR_INVALID_PARAMETER;
|
|
148 }
|
|
149
|
|
150 teardown(prv);
|
|
151
|
|
152 ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &(prv->mng));
|
|
153 if(ret != SCARD_S_SUCCESS){
|
|
154 return B_CAS_CARD_ERROR_NO_SMART_CARD_READER;
|
|
155 }
|
|
156
|
|
157 ret = SCardListReaders(prv->mng, NULL, NULL, &len);
|
|
158 if(ret != SCARD_S_SUCCESS){
|
|
159 return B_CAS_CARD_ERROR_NO_SMART_CARD_READER;
|
|
160 }
|
|
161 len += 256;
|
|
162
|
|
163 m = len + (2*B_CAS_BUFFER_MAX) + (sizeof(int64_t)*16) + (sizeof(B_CAS_PWR_ON_CTRL)*16);
|
|
164 prv->pool = (uint8_t *)malloc(m);
|
|
165 if(prv->pool == NULL){
|
|
166 return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY;
|
|
167 }
|
|
168
|
|
169 prv->reader = (char *)(prv->pool);
|
|
170 prv->sbuf = prv->pool + len;
|
|
171 prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX;
|
|
172 prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX);
|
|
173 prv->id_max = 16;
|
|
174 prv->pwc.data = (B_CAS_PWR_ON_CTRL *)(prv->id.data + prv->id_max);
|
|
175 prv->pwc_max = 16;
|
|
176
|
|
177 ret = SCardListReaders(prv->mng, NULL, prv->reader, &len);
|
|
178 if(ret != SCARD_S_SUCCESS){
|
|
179 return B_CAS_CARD_ERROR_NO_SMART_CARD_READER;
|
|
180 }
|
|
181
|
|
182 while( prv->reader[0] != 0 ){
|
|
183 if(connect_card(prv, prv->reader)){
|
|
184 break;
|
|
185 }
|
|
186 prv->reader += (strlen(prv->reader) + 1);
|
|
187 }
|
|
188
|
|
189 if(prv->card == 0){
|
|
190 return B_CAS_CARD_ERROR_ALL_READERS_CONNECTION_FAILED;
|
|
191 }
|
|
192
|
|
193 return 0;
|
|
194 }
|
|
195
|
|
196 static int get_init_status_b_cas_card(void *bcas, B_CAS_INIT_STATUS *stat)
|
|
197 {
|
|
198 B_CAS_CARD_PRIVATE_DATA *prv;
|
|
199
|
|
200 prv = private_data(bcas);
|
|
201 if( (prv == NULL) || (stat == NULL) ){
|
|
202 return B_CAS_CARD_ERROR_INVALID_PARAMETER;
|
|
203 }
|
|
204
|
|
205 if(prv->card == 0){
|
|
206 return B_CAS_CARD_ERROR_NOT_INITIALIZED;
|
|
207 }
|
|
208
|
|
209 memcpy(stat, &(prv->stat), sizeof(B_CAS_INIT_STATUS));
|
|
210
|
|
211 return 0;
|
|
212 }
|
|
213
|
|
214 static int get_id_b_cas_card(void *bcas, B_CAS_ID *dst)
|
|
215 {
|
|
216 LONG ret;
|
|
217
|
|
218 DWORD slen;
|
|
219 DWORD rlen;
|
|
220
|
|
221 int i,num;
|
|
222
|
|
223 uint8_t *p;
|
|
224 uint8_t *tail;
|
|
225
|
|
226 B_CAS_CARD_PRIVATE_DATA *prv;
|
|
227 SCARD_IO_REQUEST sir;
|
|
228
|
|
229 prv = private_data(bcas);
|
|
230 if( (prv == NULL) || (dst == NULL) ){
|
|
231 return B_CAS_CARD_ERROR_INVALID_PARAMETER;
|
|
232 }
|
|
233
|
|
234 if(prv->card == 0){
|
|
235 return B_CAS_CARD_ERROR_NOT_INITIALIZED;
|
|
236 }
|
|
237
|
|
238 slen = sizeof(CARD_ID_INFORMATION_ACQUIRE_CMD);
|
|
239 memcpy(prv->sbuf, CARD_ID_INFORMATION_ACQUIRE_CMD, slen);
|
|
240 memcpy(&sir, SCARD_PCI_T1, sizeof(sir));
|
|
241 rlen = B_CAS_BUFFER_MAX;
|
|
242
|
|
243 ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen);
|
|
244 if( (ret != SCARD_S_SUCCESS) || (rlen < 19) ){
|
|
245 return B_CAS_CARD_ERROR_TRANSMIT_FAILED;
|
|
246 }
|
|
247
|
|
248 p = prv->rbuf + 6;
|
|
249 tail = prv->rbuf + rlen;
|
|
250 if( p+1 > tail ){
|
|
251 return B_CAS_CARD_ERROR_TRANSMIT_FAILED;
|
|
252 }
|
|
253
|
|
254 num = p[0];
|
|
255 if(num > prv->id_max){
|
|
256 if(change_id_max(prv, num+4) < 0){
|
|
257 return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY;
|
|
258 }
|
|
259 }
|
|
260
|
|
261 p += 1;
|
|
262 for(i=0;i<num;i++){
|
|
263 if( p+10 > tail ){
|
|
264 return B_CAS_CARD_ERROR_TRANSMIT_FAILED;
|
|
265 }
|
|
266
|
|
267 {
|
|
268 int maker_id;
|
|
269 int version;
|
|
270 int check_code;
|
|
271
|
|
272 maker_id = p[0];
|
|
273 version = p[1];
|
|
274 prv->id.data[i] = load_be_uint48(p+2);
|
|
275 check_code = load_be_uint16(p+8);
|
|
276 }
|
|
277
|
|
278 p += 10;
|
|
279 }
|
|
280
|
|
281 prv->id.count = num;
|
|
282
|
|
283 memcpy(dst, &(prv->id), sizeof(B_CAS_ID));
|
|
284
|
|
285 return 0;
|
|
286 }
|
|
287
|
|
288 static int get_pwr_on_ctrl_b_cas_card(void *bcas, B_CAS_PWR_ON_CTRL_INFO *dst)
|
|
289 {
|
|
290 LONG ret;
|
|
291
|
|
292 DWORD slen;
|
|
293 DWORD rlen;
|
|
294
|
|
295 int i,num,code;
|
|
296
|
|
297 B_CAS_CARD_PRIVATE_DATA *prv;
|
|
298 SCARD_IO_REQUEST sir;
|
|
299
|
|
300 memset(dst, 0, sizeof(B_CAS_PWR_ON_CTRL_INFO));
|
|
301
|
|
302 prv = private_data(bcas);
|
|
303 if( (prv == NULL) || (dst == NULL) ){
|
|
304 return B_CAS_CARD_ERROR_INVALID_PARAMETER;
|
|
305 }
|
|
306
|
|
307 if(prv->card == 0){
|
|
308 return B_CAS_CARD_ERROR_NOT_INITIALIZED;
|
|
309 }
|
|
310
|
|
311 slen = sizeof(POWER_ON_CONTROL_INFORMATION_REQUEST_CMD);
|
|
312 memcpy(prv->sbuf, POWER_ON_CONTROL_INFORMATION_REQUEST_CMD, slen);
|
|
313 prv->sbuf[5] = 0;
|
|
314 memcpy(&sir, SCARD_PCI_T1, sizeof(sir));
|
|
315 rlen = B_CAS_BUFFER_MAX;
|
|
316
|
|
317 ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen);
|
|
318 if( (ret != SCARD_S_SUCCESS) || (rlen < 18) || (prv->rbuf[6] != 0) ){
|
|
319 return B_CAS_CARD_ERROR_TRANSMIT_FAILED;
|
|
320 }
|
|
321
|
|
322 code = load_be_uint16(prv->rbuf+4);
|
|
323 if(code == 0xa101){
|
|
324 /* no data */
|
|
325 return 0;
|
|
326 }else if(code != 0x2100){
|
|
327 return B_CAS_CARD_ERROR_TRANSMIT_FAILED;
|
|
328 }
|
|
329
|
|
330 num = (prv->rbuf[7] + 1);
|
|
331 if(prv->pwc_max < num){
|
|
332 if(change_pwc_max(prv, num+4) < 0){
|
|
333 return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY;
|
|
334 }
|
|
335 }
|
|
336
|
|
337 extract_power_on_ctrl_response(prv->pwc.data+0, prv->rbuf);
|
|
338
|
|
339 for(i=1;i<num;i++){
|
|
340 prv->sbuf[5] = i;
|
|
341 rlen = B_CAS_BUFFER_MAX;
|
|
342
|
|
343 ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen);
|
|
344 if( (ret != SCARD_S_SUCCESS) || (rlen < 18) || (prv->rbuf[6] != i) ){
|
|
345 return B_CAS_CARD_ERROR_TRANSMIT_FAILED;
|
|
346 }
|
|
347
|
|
348 extract_power_on_ctrl_response(prv->pwc.data+i, prv->rbuf);
|
|
349 }
|
|
350
|
|
351 prv->pwc.count = num;
|
|
352
|
|
353 memcpy(dst, &(prv->pwc), sizeof(B_CAS_PWR_ON_CTRL_INFO));
|
|
354
|
|
355 return 0;
|
|
356 }
|
|
357
|
|
358 static int proc_ecm_b_cas_card(void *bcas, B_CAS_ECM_RESULT *dst, uint8_t *src, int len)
|
|
359 {
|
|
360 int retry_count;
|
|
361
|
|
362 LONG ret;
|
|
363 DWORD slen;
|
|
364 DWORD rlen;
|
|
365
|
|
366 B_CAS_CARD_PRIVATE_DATA *prv;
|
|
367
|
|
368 SCARD_IO_REQUEST sir;
|
|
369
|
|
370 prv = private_data(bcas);
|
|
371 if( (prv == NULL) ||
|
|
372 (dst == NULL) ||
|
|
373 (src == NULL) ||
|
|
374 (len < 1) ){
|
|
375 return B_CAS_CARD_ERROR_INVALID_PARAMETER;
|
|
376 }
|
|
377
|
|
378 if(prv->card == 0){
|
|
379 return B_CAS_CARD_ERROR_NOT_INITIALIZED;
|
|
380 }
|
|
381
|
|
382 slen = setup_ecm_receive_command(prv->sbuf, src, len);
|
|
383 memcpy(&sir, SCARD_PCI_T1, sizeof(sir));
|
|
384 rlen = B_CAS_BUFFER_MAX;
|
|
385
|
|
386 retry_count = 0;
|
|
387 ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen);
|
|
388 while( ((ret != SCARD_S_SUCCESS) || (rlen < 25)) && (retry_count < 10) ){
|
|
389 retry_count += 1;
|
|
390 if(!connect_card(prv, prv->reader)){
|
|
391 continue;
|
|
392 }
|
|
393 slen = setup_ecm_receive_command(prv->sbuf, src, len);
|
|
394 memcpy(&sir, SCARD_PCI_T1, sizeof(sir));
|
|
395 rlen = B_CAS_BUFFER_MAX;
|
|
396
|
|
397 ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen);
|
|
398 }
|
|
399
|
|
400 if( (ret != SCARD_S_SUCCESS) || (rlen < 25) ){
|
|
401 return B_CAS_CARD_ERROR_TRANSMIT_FAILED;
|
|
402 }
|
|
403
|
|
404 memcpy(dst->scramble_key, prv->rbuf+6, 16);
|
|
405 dst->return_code = load_be_uint16(prv->rbuf+4);
|
|
406
|
|
407 return 0;
|
|
408 }
|
|
409
|
|
410 static int proc_emm_b_cas_card(void *bcas, uint8_t *src, int len)
|
|
411 {
|
|
412 int retry_count;
|
|
413
|
|
414 LONG ret;
|
|
415 DWORD slen;
|
|
416 DWORD rlen;
|
|
417
|
|
418 B_CAS_CARD_PRIVATE_DATA *prv;
|
|
419
|
|
420 SCARD_IO_REQUEST sir;
|
|
421
|
|
422 prv = private_data(bcas);
|
|
423 if( (prv == NULL) ||
|
|
424 (src == NULL) ||
|
|
425 (len < 1) ){
|
|
426 return B_CAS_CARD_ERROR_INVALID_PARAMETER;
|
|
427 }
|
|
428
|
|
429 if(prv->card == 0){
|
|
430 return B_CAS_CARD_ERROR_NOT_INITIALIZED;
|
|
431 }
|
|
432
|
|
433 slen = setup_emm_receive_command(prv->sbuf, src, len);
|
|
434 memcpy(&sir, SCARD_PCI_T1, sizeof(sir));
|
|
435 rlen = B_CAS_BUFFER_MAX;
|
|
436
|
|
437 retry_count = 0;
|
|
438 ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen);
|
|
439 while( ((ret != SCARD_S_SUCCESS) || (rlen < 6)) && (retry_count < 2) ){
|
|
440 retry_count += 1;
|
|
441 if(!connect_card(prv, prv->reader)){
|
|
442 continue;
|
|
443 }
|
|
444 slen = setup_emm_receive_command(prv->sbuf, src, len);
|
|
445 memcpy(&sir, SCARD_PCI_T1, sizeof(sir));
|
|
446 rlen = B_CAS_BUFFER_MAX;
|
|
447
|
|
448 ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, slen, &sir, prv->rbuf, &rlen);
|
|
449 }
|
|
450
|
|
451 if( (ret != SCARD_S_SUCCESS) || (rlen < 6) ){
|
|
452 return B_CAS_CARD_ERROR_TRANSMIT_FAILED;
|
|
453 }
|
|
454
|
|
455 return 0;
|
|
456 }
|
|
457
|
|
458 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
459 private method implementation
|
|
460 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
461 static B_CAS_CARD_PRIVATE_DATA *private_data(void *bcas)
|
|
462 {
|
|
463 B_CAS_CARD_PRIVATE_DATA *r;
|
|
464 B_CAS_CARD *p;
|
|
465
|
|
466 p = (B_CAS_CARD *)bcas;
|
|
467 if(p == NULL){
|
|
468 return NULL;
|
|
469 }
|
|
470
|
|
471 r = (B_CAS_CARD_PRIVATE_DATA *)(p->private_data);
|
|
472 if( ((void *)(r+1)) != ((void *)p) ){
|
|
473 return NULL;
|
|
474 }
|
|
475
|
|
476 return r;
|
|
477 }
|
|
478
|
|
479 static void teardown(B_CAS_CARD_PRIVATE_DATA *prv)
|
|
480 {
|
|
481 if(prv->card != 0){
|
|
482 SCardDisconnect(prv->card, SCARD_LEAVE_CARD);
|
|
483 prv->card = 0;
|
|
484 }
|
|
485
|
|
486 if(prv->mng != 0){
|
|
487 SCardReleaseContext(prv->mng);
|
|
488 prv->mng = 0;
|
|
489 }
|
|
490
|
|
491 if(prv->pool != NULL){
|
|
492 free(prv->pool);
|
|
493 prv->pool = NULL;
|
|
494 }
|
|
495
|
|
496 prv->reader = NULL;
|
|
497 prv->sbuf = NULL;
|
|
498 prv->rbuf = NULL;
|
|
499 prv->id.data = NULL;
|
|
500 prv->id_max = 0;
|
|
501 }
|
|
502
|
|
503 static int change_id_max(B_CAS_CARD_PRIVATE_DATA *prv, int max)
|
|
504 {
|
|
505 int m;
|
|
506 int reader_size;
|
|
507 int pwctrl_size;
|
|
508
|
|
509 uint8_t *p;
|
|
510 uint8_t *old_reader;
|
|
511 uint8_t *old_pwctrl;
|
|
512
|
|
513 reader_size = prv->sbuf - prv->pool;
|
|
514 pwctrl_size = prv->pwc.count * sizeof(B_CAS_PWR_ON_CTRL);
|
|
515
|
|
516 m = reader_size;
|
|
517 m += (2*B_CAS_BUFFER_MAX);
|
|
518 m += (max*sizeof(int64_t));
|
|
519 m += (prv->pwc_max*sizeof(B_CAS_PWR_ON_CTRL));
|
|
520 p = (uint8_t *)malloc(m);
|
|
521 if(p == NULL){
|
|
522 return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY;
|
|
523 }
|
|
524
|
|
525 old_reader = (uint8_t *)(prv->reader);
|
|
526 old_pwctrl = (uint8_t *)(prv->pwc.data);
|
|
527
|
|
528 prv->reader = (char *)p;
|
|
529 prv->sbuf = prv->pool + reader_size;
|
|
530 prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX;
|
|
531 prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX);
|
|
532 prv->id_max = max;
|
|
533 prv->pwc.data = (B_CAS_PWR_ON_CTRL *)(prv->id.data + prv->id_max);
|
|
534
|
|
535 memcpy(prv->reader, old_reader, reader_size);
|
|
536 memcpy(prv->pwc.data, old_pwctrl, pwctrl_size);
|
|
537
|
|
538 free(prv->pool);
|
|
539 prv->pool = p;
|
|
540
|
|
541 return 0;
|
|
542 }
|
|
543
|
|
544 static int change_pwc_max(B_CAS_CARD_PRIVATE_DATA *prv, int max)
|
|
545 {
|
|
546 int m;
|
|
547 int reader_size;
|
|
548 int cardid_size;
|
|
549
|
|
550 uint8_t *p;
|
|
551 uint8_t *old_reader;
|
|
552 uint8_t *old_cardid;
|
|
553
|
|
554 reader_size = prv->sbuf - prv->pool;
|
|
555 cardid_size = prv->id.count * sizeof(int64_t);
|
|
556
|
|
557 m = reader_size;
|
|
558 m += (2*B_CAS_BUFFER_MAX);
|
|
559 m += (prv->id_max*sizeof(int64_t));
|
|
560 m += (max*sizeof(B_CAS_PWR_ON_CTRL));
|
|
561 p = (uint8_t *)malloc(m);
|
|
562 if(p == NULL){
|
|
563 return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY;
|
|
564 }
|
|
565
|
|
566 old_reader = (uint8_t *)(prv->reader);
|
|
567 old_cardid = (uint8_t *)(prv->id.data);
|
|
568
|
|
569 prv->reader = (char *)p;
|
|
570 prv->sbuf = prv->pool + reader_size;
|
|
571 prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX;
|
|
572 prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX);
|
|
573 prv->pwc.data = (B_CAS_PWR_ON_CTRL *)(prv->id.data + prv->id_max);
|
|
574 prv->pwc_max = max;
|
|
575
|
|
576 memcpy(prv->reader, old_reader, reader_size);
|
|
577 memcpy(prv->id.data, old_cardid, cardid_size);
|
|
578
|
|
579 free(prv->pool);
|
|
580 prv->pool = p;
|
|
581
|
|
582 return 0;
|
|
583 }
|
|
584
|
|
585 static int connect_card(B_CAS_CARD_PRIVATE_DATA *prv, const char *reader_name)
|
|
586 {
|
|
587 int m,n;
|
|
588
|
|
589 LONG ret;
|
|
590 DWORD rlen,protocol;
|
|
591
|
|
592 uint8_t *p;
|
|
593
|
|
594 SCARD_IO_REQUEST sir;
|
|
595
|
|
596 if(prv->card != 0){
|
|
597 SCardDisconnect(prv->card, SCARD_RESET_CARD);
|
|
598 prv->card = 0;
|
|
599 }
|
|
600
|
|
601 ret = SCardConnect(prv->mng, reader_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &(prv->card), &protocol);
|
|
602 if(ret != SCARD_S_SUCCESS){
|
|
603 return 0;
|
|
604 }
|
|
605
|
|
606 m = sizeof(INITIAL_SETTING_CONDITIONS_CMD);
|
|
607 memcpy(prv->sbuf, INITIAL_SETTING_CONDITIONS_CMD, m);
|
|
608 memcpy(&sir, SCARD_PCI_T1, sizeof(sir));
|
|
609 rlen = B_CAS_BUFFER_MAX;
|
|
610 ret = SCardTransmit(prv->card, SCARD_PCI_T1, prv->sbuf, m, &sir, prv->rbuf, &rlen);
|
|
611 if(ret != SCARD_S_SUCCESS){
|
|
612 return 0;
|
|
613 }
|
|
614
|
|
615 if(rlen < 57){
|
|
616 return 0;
|
|
617 }
|
|
618
|
|
619 p = prv->rbuf;
|
|
620
|
|
621 n = load_be_uint16(p+4);
|
|
622 if(n != 0x2100){ // return code missmatch
|
|
623 return 0;
|
|
624 }
|
|
625
|
|
626 memcpy(prv->stat.system_key, p+16, 32);
|
|
627 memcpy(prv->stat.init_cbc, p+48, 8);
|
|
628 prv->stat.bcas_card_id = load_be_uint48(p+8);
|
|
629 prv->stat.card_status = load_be_uint16(p+2);
|
|
630
|
|
631 return 1;
|
|
632 }
|
|
633
|
|
634 static void extract_power_on_ctrl_response(B_CAS_PWR_ON_CTRL *dst, uint8_t *src)
|
|
635 {
|
|
636 int referrence;
|
|
637 int start;
|
|
638 int limit;
|
|
639
|
|
640
|
|
641 dst->broadcaster_group_id = src[8];
|
|
642 referrence = (src[9]<<8)|src[10];
|
|
643 start = referrence - src[11];
|
|
644 limit = start + (src[12]-1);
|
|
645
|
|
646 extract_mjd(&(dst->s_yy), &(dst->s_mm), &(dst->s_dd), start);
|
|
647 extract_mjd(&(dst->l_yy), &(dst->l_mm), &(dst->l_dd), limit);
|
|
648
|
|
649 dst->hold_time = src[13];
|
|
650 dst->network_id = (src[14]<<8)|src[15];
|
|
651 dst->transport_id = (src[16]<<8)|src[17];
|
|
652
|
|
653 }
|
|
654
|
|
655 static void extract_mjd(int *yy, int *mm, int *dd, int mjd)
|
|
656 {
|
|
657 int yd;
|
|
658 int md;
|
|
659 int d;
|
|
660
|
|
661 yd = (int)floor( (mjd-15078.2) / 365.25 );
|
|
662 md = (int)floor( ((mjd-14956.1) - (yd*365.25)) / 30.6001 );
|
|
663 d = mjd - 14956 - (int)floor(yd*365.25) - (int)floor(md*30.6001);
|
|
664 if( md > 13 ){
|
|
665 *dd = d;
|
|
666 *mm = md-13;
|
|
667 *yy = 1900+yd+1;
|
|
668 }else{
|
|
669 *dd = d;
|
|
670 *mm = md-1;
|
|
671 *yy = 1900+yd;
|
|
672 }
|
|
673
|
|
674 if(*yy < 2000){ /* mjd bit overflow - retry */
|
|
675 extract_mjd(yy, mm, dd, mjd+0x10000);
|
|
676 }
|
|
677 }
|
|
678
|
|
679 static int setup_ecm_receive_command(uint8_t *dst, uint8_t *src, int len)
|
|
680 {
|
|
681 int r;
|
|
682
|
|
683 r = sizeof(ECM_RECEIVE_CMD_HEADER);
|
|
684 memcpy(dst+0, ECM_RECEIVE_CMD_HEADER, r);
|
|
685 dst[r] = (uint8_t)(len & 0xff);
|
|
686 r += 1;
|
|
687 memcpy(dst+r, src, len);
|
|
688 r += len;
|
|
689 dst[r] = 0;
|
|
690 r += 1;
|
|
691
|
|
692 return r;
|
|
693 }
|
|
694
|
|
695 static int setup_emm_receive_command(uint8_t *dst, uint8_t *src, int len)
|
|
696 {
|
|
697 int r;
|
|
698
|
|
699 r = sizeof(EMM_RECEIVE_CMD_HEADER);
|
|
700 memcpy(dst+0, EMM_RECEIVE_CMD_HEADER, r);
|
|
701 dst[r] = (uint8_t)(len & 0xff);
|
|
702 r += 1;
|
|
703 memcpy(dst+r, src, len);
|
|
704 r += len;
|
|
705 dst[r] = 0;
|
|
706 r += 1;
|
|
707
|
|
708 return r;
|
|
709 }
|
|
710
|
|
711 static int32_t load_be_uint16(uint8_t *p)
|
|
712 {
|
|
713 return ((p[0]<<8)|p[1]);
|
|
714 }
|
|
715
|
|
716 static int64_t load_be_uint48(uint8_t *p)
|
|
717 {
|
|
718 int i;
|
|
719 int64_t r;
|
|
720
|
|
721 r = p[0];
|
|
722 for(i=1;i<6;i++){
|
|
723 r <<= 8;
|
|
724 r |= p[i];
|
|
725 }
|
|
726
|
|
727 return r;
|
|
728 }
|
|
729
|