Mercurial > pt1.oyama
comparison arib25/src/b_cas_card.c @ 53:41a5481db56f
rearrange arib25 directory
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Sun, 13 Sep 2009 02:11:33 +0900 |
parents | arib25v023/arib25/src/b_cas_card.c@6801fe7e04ff |
children |
comparison
equal
deleted
inserted
replaced
52:db7af62da709 | 53:41a5481db56f |
---|---|
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 prv->stat.ca_system_id = load_be_uint16(p+6); | |
631 | |
632 return 1; | |
633 } | |
634 | |
635 static void extract_power_on_ctrl_response(B_CAS_PWR_ON_CTRL *dst, uint8_t *src) | |
636 { | |
637 int referrence; | |
638 int start; | |
639 int limit; | |
640 | |
641 | |
642 dst->broadcaster_group_id = src[8]; | |
643 referrence = (src[9]<<8)|src[10]; | |
644 start = referrence - src[11]; | |
645 limit = start + (src[12]-1); | |
646 | |
647 extract_mjd(&(dst->s_yy), &(dst->s_mm), &(dst->s_dd), start); | |
648 extract_mjd(&(dst->l_yy), &(dst->l_mm), &(dst->l_dd), limit); | |
649 | |
650 dst->hold_time = src[13]; | |
651 dst->network_id = (src[14]<<8)|src[15]; | |
652 dst->transport_id = (src[16]<<8)|src[17]; | |
653 | |
654 } | |
655 | |
656 static void extract_mjd(int *yy, int *mm, int *dd, int mjd) | |
657 { | |
658 int a1,m1; | |
659 int a2,m2; | |
660 int a3,m3; | |
661 int a4,m4; | |
662 int mw; | |
663 int dw; | |
664 int yw; | |
665 | |
666 mjd -= 51604; // 2000,3/1 | |
667 if(mjd < 0){ | |
668 mjd += 0x10000; | |
669 } | |
670 | |
671 a1 = mjd / 146097; | |
672 m1 = mjd % 146097; | |
673 a2 = m1 / 36524; | |
674 m2 = m1 - (a2 * 36524); | |
675 a3 = m2 / 1461; | |
676 m3 = m2 - (a3 * 1461); | |
677 a4 = m3 / 365; | |
678 if(a4 > 3){ | |
679 a4 = 3; | |
680 } | |
681 m4 = m3 - (a4 * 365); | |
682 | |
683 mw = (1071*m4+450) >> 15; | |
684 dw = m4 - ((979*mw+16) >> 5); | |
685 | |
686 yw = a1*400 + a2*100 + a3*4 + a4 + 2000; | |
687 mw += 3; | |
688 if(mw > 12){ | |
689 mw -= 12; | |
690 yw += 1; | |
691 } | |
692 dw += 1; | |
693 | |
694 *yy = yw; | |
695 *mm = mw; | |
696 *dd = dw; | |
697 } | |
698 | |
699 static int setup_ecm_receive_command(uint8_t *dst, uint8_t *src, int len) | |
700 { | |
701 int r; | |
702 | |
703 r = sizeof(ECM_RECEIVE_CMD_HEADER); | |
704 memcpy(dst+0, ECM_RECEIVE_CMD_HEADER, r); | |
705 dst[r] = (uint8_t)(len & 0xff); | |
706 r += 1; | |
707 memcpy(dst+r, src, len); | |
708 r += len; | |
709 dst[r] = 0; | |
710 r += 1; | |
711 | |
712 return r; | |
713 } | |
714 | |
715 static int setup_emm_receive_command(uint8_t *dst, uint8_t *src, int len) | |
716 { | |
717 int r; | |
718 | |
719 r = sizeof(EMM_RECEIVE_CMD_HEADER); | |
720 memcpy(dst+0, EMM_RECEIVE_CMD_HEADER, r); | |
721 dst[r] = (uint8_t)(len & 0xff); | |
722 r += 1; | |
723 memcpy(dst+r, src, len); | |
724 r += len; | |
725 dst[r] = 0; | |
726 r += 1; | |
727 | |
728 return r; | |
729 } | |
730 | |
731 static int32_t load_be_uint16(uint8_t *p) | |
732 { | |
733 return ((p[0]<<8)|p[1]); | |
734 } | |
735 | |
736 static int64_t load_be_uint48(uint8_t *p) | |
737 { | |
738 int i; | |
739 int64_t r; | |
740 | |
741 r = p[0]; | |
742 for(i=1;i<6;i++){ | |
743 r <<= 8; | |
744 r |= p[i]; | |
745 } | |
746 | |
747 return r; | |
748 } | |
749 |