initial commit
[arib_std_b25.git] / src / b_cas_card.c
blobad47435c7e194aa9b54d01827f2802aa63ab9f74
1 #include "b_cas_card.h"
2 #include "b_cas_card_error_code.h"
4 #include <stdlib.h>
5 #include <string.h>
7 #include <math.h>
9 #if defined(WIN32)
10 #include <windows.h>
11 #endif
12 #include <winscard.h>
14 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
15 inner structures
16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
17 typedef struct {
19 SCARDCONTEXT mng;
20 SCARDHANDLE card;
22 uint8_t *pool;
23 char *reader;
25 uint8_t *sbuf;
26 uint8_t *rbuf;
28 B_CAS_INIT_STATUS stat;
30 B_CAS_ID id;
31 int32_t id_max;
33 B_CAS_PWR_ON_CTRL_INFO pwc;
34 int32_t pwc_max;
36 } B_CAS_CARD_PRIVATE_DATA;
38 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
39 constant values
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()
79 int n;
81 B_CAS_CARD *r;
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);
86 if(prv == NULL){
87 return NULL;
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;
102 return r;
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);
128 if(prv == NULL){
129 /* do nothing */
130 return;
133 teardown(prv);
134 free(prv);
137 static int init_b_cas_card(void *bcas)
139 int m;
140 LONG ret;
141 DWORD len;
143 B_CAS_CARD_PRIVATE_DATA *prv;
145 prv = private_data(bcas);
146 if(prv == NULL){
147 return B_CAS_CARD_ERROR_INVALID_PARAMETER;
150 teardown(prv);
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;
161 len += 256;
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);
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;
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)){
184 break;
186 prv->reader += (strlen(prv->reader) + 1);
189 if(prv->card == 0){
190 return B_CAS_CARD_ERROR_ALL_READERS_CONNECTION_FAILED;
193 return 0;
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;
205 if(prv->card == 0){
206 return B_CAS_CARD_ERROR_NOT_INITIALIZED;
209 memcpy(stat, &(prv->stat), sizeof(B_CAS_INIT_STATUS));
211 return 0;
214 static int get_id_b_cas_card(void *bcas, B_CAS_ID *dst)
216 LONG ret;
218 DWORD slen;
219 DWORD rlen;
221 int i,num;
223 uint8_t *p;
224 uint8_t *tail;
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;
234 if(prv->card == 0){
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;
248 p = prv->rbuf + 6;
249 tail = prv->rbuf + rlen;
250 if( p+1 > tail ){
251 return B_CAS_CARD_ERROR_TRANSMIT_FAILED;
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;
261 p += 1;
262 for(i=0;i<num;i++){
263 if( p+10 > tail ){
264 return B_CAS_CARD_ERROR_TRANSMIT_FAILED;
266 #if 0
268 int maker_id;
269 int version;
270 int check_code;
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);
277 #endif
278 p += 10;
281 prv->id.count = num;
283 memcpy(dst, &(prv->id), sizeof(B_CAS_ID));
285 return 0;
288 static int get_pwr_on_ctrl_b_cas_card(void *bcas, B_CAS_PWR_ON_CTRL_INFO *dst)
290 LONG ret;
292 DWORD slen;
293 DWORD rlen;
295 int i,num,code;
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;
307 if(prv->card == 0){
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);
313 prv->sbuf[5] = 0;
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);
323 if(code == 0xa101){
324 /* no data */
325 return 0;
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);
339 for(i=1;i<num;i++){
340 prv->sbuf[5] = i;
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));
355 return 0;
358 static int proc_ecm_b_cas_card(void *bcas, B_CAS_ECM_RESULT *dst, uint8_t *src, int len)
360 int retry_count;
362 LONG ret;
363 DWORD slen;
364 DWORD rlen;
366 B_CAS_CARD_PRIVATE_DATA *prv;
368 SCARD_IO_REQUEST sir;
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;
378 if(prv->card == 0){
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;
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;
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);
407 return 0;
410 static int proc_emm_b_cas_card(void *bcas, uint8_t *src, int len)
412 int retry_count;
414 LONG ret;
415 DWORD slen;
416 DWORD rlen;
418 B_CAS_CARD_PRIVATE_DATA *prv;
420 SCARD_IO_REQUEST sir;
422 prv = private_data(bcas);
423 if( (prv == NULL) ||
424 (src == NULL) ||
425 (len < 1) ){
426 return B_CAS_CARD_ERROR_INVALID_PARAMETER;
429 if(prv->card == 0){
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;
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;
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;
455 return 0;
458 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
459 private method implementation
460 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
461 static B_CAS_CARD_PRIVATE_DATA *private_data(void *bcas)
463 B_CAS_CARD_PRIVATE_DATA *r;
464 B_CAS_CARD *p;
466 p = (B_CAS_CARD *)bcas;
467 if(p == NULL){
468 return NULL;
471 r = (B_CAS_CARD_PRIVATE_DATA *)(p->private_data);
472 if( ((void *)(r+1)) != ((void *)p) ){
473 return NULL;
476 return r;
479 static void teardown(B_CAS_CARD_PRIVATE_DATA *prv)
481 if(prv->card != 0){
482 SCardDisconnect(prv->card, SCARD_LEAVE_CARD);
483 prv->card = 0;
486 if(prv->mng != 0){
487 SCardReleaseContext(prv->mng);
488 prv->mng = 0;
491 if(prv->pool != NULL){
492 free(prv->pool);
493 prv->pool = NULL;
496 prv->reader = NULL;
497 prv->sbuf = NULL;
498 prv->rbuf = NULL;
499 prv->id.data = NULL;
500 prv->id_max = 0;
503 static int change_id_max(B_CAS_CARD_PRIVATE_DATA *prv, int max)
505 int m;
506 int reader_size;
507 int pwctrl_size;
509 uint8_t *p;
510 uint8_t *old_reader;
511 uint8_t *old_pwctrl;
513 reader_size = prv->sbuf - prv->pool;
514 pwctrl_size = prv->pwc.count * sizeof(B_CAS_PWR_ON_CTRL);
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;
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);
532 prv->id_max = 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);
538 free(prv->pool);
539 prv->pool = p;
541 return 0;
544 static int change_pwc_max(B_CAS_CARD_PRIVATE_DATA *prv, int max)
546 int m;
547 int reader_size;
548 int cardid_size;
550 uint8_t *p;
551 uint8_t *old_reader;
552 uint8_t *old_cardid;
554 reader_size = prv->sbuf - prv->pool;
555 cardid_size = prv->id.count * sizeof(int64_t);
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;
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);
574 prv->pwc_max = max;
576 memcpy(prv->reader, old_reader, reader_size);
577 memcpy(prv->id.data, old_cardid, cardid_size);
579 free(prv->pool);
580 prv->pool = p;
582 return 0;
585 static int connect_card(B_CAS_CARD_PRIVATE_DATA *prv, const char *reader_name)
587 int m,n;
589 LONG ret;
590 DWORD rlen,protocol;
592 uint8_t *p;
594 SCARD_IO_REQUEST sir;
596 if(prv->card != 0){
597 SCardDisconnect(prv->card, SCARD_RESET_CARD);
598 prv->card = 0;
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;
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;
615 if(rlen < 57){
616 return 0;
619 p = prv->rbuf;
621 n = load_be_uint16(p+4);
622 if(n != 0x2100){ // return code missmatch
623 return 0;
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);
632 return 1;
635 static void extract_power_on_ctrl_response(B_CAS_PWR_ON_CTRL *dst, uint8_t *src)
637 int referrence;
638 int start;
639 int limit;
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)
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;
666 mjd -= 51604; // 2000,3/1
667 if(mjd < 0){
668 mjd += 0x10000;
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;
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;
687 mw += 3;
688 if(mw > 12){
689 mw -= 12;
690 yw += 1;
692 dw += 1;
694 *yy = yw;
695 *mm = mw;
696 *dd = dw;
699 static int setup_ecm_receive_command(uint8_t *dst, uint8_t *src, int len)
701 int r;
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;
712 return r;
715 static int setup_emm_receive_command(uint8_t *dst, uint8_t *src, int len)
717 int r;
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;
728 return r;
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)
738 int i;
739 int64_t r;
741 r = p[0];
742 for(i=1;i<6;i++){
743 r <<= 8;
744 r |= p[i];
747 return r;