1 #include "b_cas_card.h"
2 #include "b_cas_card_error_code.h"
14 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
28 B_CAS_INIT_STATUS stat
;
33 B_CAS_PWR_ON_CTRL_INFO pwc
;
36 } B_CAS_CARD_PRIVATE_DATA
;
38 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
41 static const uint8_t INITIAL_SETTING_CONDITIONS_CMD
[] = {
42 0x90, 0x30, 0x00, 0x00, 0x00,
45 static const uint8_t CARD_ID_INFORMATION_ACQUIRE_CMD
[] = {
46 0x90, 0x32, 0x00, 0x00, 0x00,
49 static const uint8_t POWER_ON_CONTROL_INFORMATION_REQUEST_CMD
[] = {
50 0x90, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
53 static const uint8_t ECM_RECEIVE_CMD_HEADER
[] = {
54 0x90, 0x34, 0x00, 0x00,
57 static const uint8_t EMM_RECEIVE_CMD_HEADER
[] = {
58 0x90, 0x36, 0x00, 0x00,
61 #define B_CAS_BUFFER_MAX (4*1024)
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
);
74 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
75 global function implementation
76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
77 B_CAS_CARD
*create_b_cas_card()
82 B_CAS_CARD_PRIVATE_DATA
*prv
;
84 n
= sizeof(B_CAS_CARD
) + sizeof(B_CAS_CARD_PRIVATE_DATA
);
85 prv
= (B_CAS_CARD_PRIVATE_DATA
*)calloc(1, n
);
90 r
= (B_CAS_CARD
*)(prv
+1);
92 r
->private_data
= prv
;
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
;
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
);
120 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
121 interface method implementation
122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
123 static void release_b_cas_card(void *bcas
)
125 B_CAS_CARD_PRIVATE_DATA
*prv
;
127 prv
= private_data(bcas
);
137 static int init_b_cas_card(void *bcas
)
143 B_CAS_CARD_PRIVATE_DATA
*prv
;
145 prv
= private_data(bcas
);
147 return B_CAS_CARD_ERROR_INVALID_PARAMETER
;
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
;
157 ret
= SCardListReaders(prv
->mng
, NULL
, NULL
, &len
);
158 if(ret
!= SCARD_S_SUCCESS
){
159 return B_CAS_CARD_ERROR_NO_SMART_CARD_READER
;
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
;
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
);
174 prv
->pwc
.data
= (B_CAS_PWR_ON_CTRL
*)(prv
->id
.data
+ prv
->id_max
);
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
;
182 while( prv
->reader
[0] != 0 ){
183 if(connect_card(prv
, prv
->reader
)){
186 prv
->reader
+= (strlen(prv
->reader
) + 1);
190 return B_CAS_CARD_ERROR_ALL_READERS_CONNECTION_FAILED
;
196 static int get_init_status_b_cas_card(void *bcas
, B_CAS_INIT_STATUS
*stat
)
198 B_CAS_CARD_PRIVATE_DATA
*prv
;
200 prv
= private_data(bcas
);
201 if( (prv
== NULL
) || (stat
== NULL
) ){
202 return B_CAS_CARD_ERROR_INVALID_PARAMETER
;
206 return B_CAS_CARD_ERROR_NOT_INITIALIZED
;
209 memcpy(stat
, &(prv
->stat
), sizeof(B_CAS_INIT_STATUS
));
214 static int get_id_b_cas_card(void *bcas
, B_CAS_ID
*dst
)
226 B_CAS_CARD_PRIVATE_DATA
*prv
;
227 SCARD_IO_REQUEST sir
;
229 prv
= private_data(bcas
);
230 if( (prv
== NULL
) || (dst
== NULL
) ){
231 return B_CAS_CARD_ERROR_INVALID_PARAMETER
;
235 return B_CAS_CARD_ERROR_NOT_INITIALIZED
;
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
;
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
;
249 tail
= prv
->rbuf
+ rlen
;
251 return B_CAS_CARD_ERROR_TRANSMIT_FAILED
;
255 if(num
> prv
->id_max
){
256 if(change_id_max(prv
, num
+4) < 0){
257 return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY
;
264 return B_CAS_CARD_ERROR_TRANSMIT_FAILED
;
274 prv
->id
.data
[i
] = load_be_uint48(p
+2);
275 check_code
= load_be_uint16(p
+8);
283 memcpy(dst
, &(prv
->id
), sizeof(B_CAS_ID
));
288 static int get_pwr_on_ctrl_b_cas_card(void *bcas
, B_CAS_PWR_ON_CTRL_INFO
*dst
)
297 B_CAS_CARD_PRIVATE_DATA
*prv
;
298 SCARD_IO_REQUEST sir
;
300 memset(dst
, 0, sizeof(B_CAS_PWR_ON_CTRL_INFO
));
302 prv
= private_data(bcas
);
303 if( (prv
== NULL
) || (dst
== NULL
) ){
304 return B_CAS_CARD_ERROR_INVALID_PARAMETER
;
308 return B_CAS_CARD_ERROR_NOT_INITIALIZED
;
311 slen
= sizeof(POWER_ON_CONTROL_INFORMATION_REQUEST_CMD
);
312 memcpy(prv
->sbuf
, POWER_ON_CONTROL_INFORMATION_REQUEST_CMD
, slen
);
314 memcpy(&sir
, SCARD_PCI_T1
, sizeof(sir
));
315 rlen
= B_CAS_BUFFER_MAX
;
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
;
322 code
= load_be_uint16(prv
->rbuf
+4);
326 }else if(code
!= 0x2100){
327 return B_CAS_CARD_ERROR_TRANSMIT_FAILED
;
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
;
337 extract_power_on_ctrl_response(prv
->pwc
.data
+0, prv
->rbuf
);
341 rlen
= B_CAS_BUFFER_MAX
;
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
;
348 extract_power_on_ctrl_response(prv
->pwc
.data
+i
, prv
->rbuf
);
351 prv
->pwc
.count
= num
;
353 memcpy(dst
, &(prv
->pwc
), sizeof(B_CAS_PWR_ON_CTRL_INFO
));
358 static int proc_ecm_b_cas_card(void *bcas
, B_CAS_ECM_RESULT
*dst
, uint8_t *src
, int len
)
366 B_CAS_CARD_PRIVATE_DATA
*prv
;
368 SCARD_IO_REQUEST sir
;
370 prv
= private_data(bcas
);
375 return B_CAS_CARD_ERROR_INVALID_PARAMETER
;
379 return B_CAS_CARD_ERROR_NOT_INITIALIZED
;
382 slen
= setup_ecm_receive_command(prv
->sbuf
, src
, len
);
383 memcpy(&sir
, SCARD_PCI_T1
, sizeof(sir
));
384 rlen
= B_CAS_BUFFER_MAX
;
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) ){
390 if(!connect_card(prv
, prv
->reader
)){
393 slen
= setup_ecm_receive_command(prv
->sbuf
, src
, len
);
394 memcpy(&sir
, SCARD_PCI_T1
, sizeof(sir
));
395 rlen
= B_CAS_BUFFER_MAX
;
397 ret
= SCardTransmit(prv
->card
, SCARD_PCI_T1
, prv
->sbuf
, slen
, &sir
, prv
->rbuf
, &rlen
);
400 if( (ret
!= SCARD_S_SUCCESS
) || (rlen
< 25) ){
401 return B_CAS_CARD_ERROR_TRANSMIT_FAILED
;
404 memcpy(dst
->scramble_key
, prv
->rbuf
+6, 16);
405 dst
->return_code
= load_be_uint16(prv
->rbuf
+4);
410 static int proc_emm_b_cas_card(void *bcas
, uint8_t *src
, int len
)
418 B_CAS_CARD_PRIVATE_DATA
*prv
;
420 SCARD_IO_REQUEST sir
;
422 prv
= private_data(bcas
);
426 return B_CAS_CARD_ERROR_INVALID_PARAMETER
;
430 return B_CAS_CARD_ERROR_NOT_INITIALIZED
;
433 slen
= setup_emm_receive_command(prv
->sbuf
, src
, len
);
434 memcpy(&sir
, SCARD_PCI_T1
, sizeof(sir
));
435 rlen
= B_CAS_BUFFER_MAX
;
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) ){
441 if(!connect_card(prv
, prv
->reader
)){
444 slen
= setup_emm_receive_command(prv
->sbuf
, src
, len
);
445 memcpy(&sir
, SCARD_PCI_T1
, sizeof(sir
));
446 rlen
= B_CAS_BUFFER_MAX
;
448 ret
= SCardTransmit(prv
->card
, SCARD_PCI_T1
, prv
->sbuf
, slen
, &sir
, prv
->rbuf
, &rlen
);
451 if( (ret
!= SCARD_S_SUCCESS
) || (rlen
< 6) ){
452 return B_CAS_CARD_ERROR_TRANSMIT_FAILED
;
458 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
459 private method implementation
460 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
461 static B_CAS_CARD_PRIVATE_DATA
*private_data(void *bcas
)
463 B_CAS_CARD_PRIVATE_DATA
*r
;
466 p
= (B_CAS_CARD
*)bcas
;
471 r
= (B_CAS_CARD_PRIVATE_DATA
*)(p
->private_data
);
472 if( ((void *)(r
+1)) != ((void *)p
) ){
479 static void teardown(B_CAS_CARD_PRIVATE_DATA
*prv
)
482 SCardDisconnect(prv
->card
, SCARD_LEAVE_CARD
);
487 SCardReleaseContext(prv
->mng
);
491 if(prv
->pool
!= NULL
){
503 static int change_id_max(B_CAS_CARD_PRIVATE_DATA
*prv
, int max
)
513 reader_size
= prv
->sbuf
- prv
->pool
;
514 pwctrl_size
= prv
->pwc
.count
* sizeof(B_CAS_PWR_ON_CTRL
);
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
);
522 return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY
;
525 old_reader
= (uint8_t *)(prv
->reader
);
526 old_pwctrl
= (uint8_t *)(prv
->pwc
.data
);
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
);
533 prv
->pwc
.data
= (B_CAS_PWR_ON_CTRL
*)(prv
->id
.data
+ prv
->id_max
);
535 memcpy(prv
->reader
, old_reader
, reader_size
);
536 memcpy(prv
->pwc
.data
, old_pwctrl
, pwctrl_size
);
544 static int change_pwc_max(B_CAS_CARD_PRIVATE_DATA
*prv
, int max
)
554 reader_size
= prv
->sbuf
- prv
->pool
;
555 cardid_size
= prv
->id
.count
* sizeof(int64_t);
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
);
563 return B_CAS_CARD_ERROR_NO_ENOUGH_MEMORY
;
566 old_reader
= (uint8_t *)(prv
->reader
);
567 old_cardid
= (uint8_t *)(prv
->id
.data
);
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
);
576 memcpy(prv
->reader
, old_reader
, reader_size
);
577 memcpy(prv
->id
.data
, old_cardid
, cardid_size
);
585 static int connect_card(B_CAS_CARD_PRIVATE_DATA
*prv
, const char *reader_name
)
594 SCARD_IO_REQUEST sir
;
597 SCardDisconnect(prv
->card
, SCARD_RESET_CARD
);
601 ret
= SCardConnect(prv
->mng
, reader_name
, SCARD_SHARE_SHARED
, SCARD_PROTOCOL_T1
, &(prv
->card
), &protocol
);
602 if(ret
!= SCARD_S_SUCCESS
){
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
){
621 n
= load_be_uint16(p
+4);
622 if(n
!= 0x2100){ // return code missmatch
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);
635 static void extract_power_on_ctrl_response(B_CAS_PWR_ON_CTRL
*dst
, uint8_t *src
)
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);
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
);
650 dst
->hold_time
= src
[13];
651 dst
->network_id
= (src
[14]<<8)|src
[15];
652 dst
->transport_id
= (src
[16]<<8)|src
[17];
656 static void extract_mjd(int *yy
, int *mm
, int *dd
, int mjd
)
666 mjd
-= 51604; // 2000,3/1
674 m2
= m1
- (a2
* 36524);
676 m3
= m2
- (a3
* 1461);
681 m4
= m3
- (a4
* 365);
683 mw
= (1071*m4
+450) >> 15;
684 dw
= m4
- ((979*mw
+16) >> 5);
686 yw
= a1
*400 + a2
*100 + a3
*4 + a4
+ 2000;
699 static int setup_ecm_receive_command(uint8_t *dst
, uint8_t *src
, int len
)
703 r
= sizeof(ECM_RECEIVE_CMD_HEADER
);
704 memcpy(dst
+0, ECM_RECEIVE_CMD_HEADER
, r
);
705 dst
[r
] = (uint8_t)(len
& 0xff);
707 memcpy(dst
+r
, src
, len
);
715 static int setup_emm_receive_command(uint8_t *dst
, uint8_t *src
, int len
)
719 r
= sizeof(EMM_RECEIVE_CMD_HEADER
);
720 memcpy(dst
+0, EMM_RECEIVE_CMD_HEADER
, r
);
721 dst
[r
] = (uint8_t)(len
& 0xff);
723 memcpy(dst
+r
, src
, len
);
731 static int32_t load_be_uint16(uint8_t *p
)
733 return ((p
[0]<<8)|p
[1]);
736 static int64_t load_be_uint48(uint8_t *p
)