comparison arib25v021/arib25/src/b_cas_card.c @ 0:67e8eca28a80

initial import
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 16 Feb 2009 15:41:49 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:67e8eca28a80
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