source: titan/titan/ca.h @ 37777

Last change on this file since 37777 was 37777, checked in by gost, 8 years ago

next test ci*

File size: 52.0 KB
Line 
1#ifndef CA_H
2#define CA_H
3
4//wait for a module inserted
5void cawait(struct stimerthread* self, struct dvbdev* dvbnode, int tout)
6{
7        unsigned int i = 0;
8        ca_slot_info_t info;
9
10        if(dvbnode == NULL || self == NULL) return;
11        info.num = dvbnode->devnr;
12
13        while(self->aktion == START)
14        {
15                if(cagetslotinfo(dvbnode, &info) == 0)
16                {
17                        if(info.flags & CA_CI_MODULE_READY)
18                                break;
19                }
20                sleep(1);
21                i++;
22                if(i >= tout) break;
23
24                if(dvbnode->caslot != NULL && dvbnode->caslot->status == 100) break;
25        }
26}
27
28//flag 0: don't flash buffer
29//flag 1: flush buffer
30void careseting(struct stimerthread* self, struct dvbdev* dvbnode, int flag)
31{
32        if(dvbnode != NULL)
33        {
34                struct queue* qe = NULL;
35                unsigned char buf[256];
36
37                ciclose(dvbnode, -1);
38                usleep(300000);
39                ciopen(dvbnode);
40
41                //flush buffer
42                if(flag == 1)
43                        while(dvbreadfd(dvbnode->fd, buf, 0, 256, -1, 0) > 0);
44
45                //flush queue
46                qe = getqueue(dvbnode->devnr);
47                while(qe != NULL)
48                {
49                        delqueue(qe, 0);
50                        qe = getqueue(dvbnode->devnr);
51                }
52
53                careset(dvbnode, dvbnode->devnr);
54                cawait(self, dvbnode, 10);
55        }
56}
57
58//wait for a while for some data und read it if some
59int caread(struct dvbdev* dvbnode, unsigned char* buf, int* len)
60{
61        int ret = 0, c = 0;
62        struct pollfd fds;
63
64        if(dvbnode == NULL || dvbnode->fd < 0) return -1;
65
66        fds.fd = dvbnode->fd;
67        fds.events = POLLOUT | POLLPRI | POLLIN;
68
69        ret = TEMP_FAILURE_RETRY(poll(&fds, 1, 300));
70
71        if(ret < 0)
72        {
73                err("poll data");
74                return -1; //error
75        }
76        else if(ret == 0)
77                return -2; //timeout
78        else if(ret > 0)
79        {
80                if(fds.revents & POLLIN)
81                {
82                        int readret = 0;
83retry:
84                        readret = TEMP_FAILURE_RETRY(read(dvbnode->fd, buf, *len));
85
86                        if(readret > 0)
87                        {
88                                if(debug_level == 620)
89                                {
90                                        int i = 0;
91                                        printf("CA Read (fd %d): > ", dvbnode->fd);
92                                        for(i = 0; i < readret; i++)
93                                                printf("%02x ", buf[i]);
94                                        printf("\n");
95                                }
96
97                                *len = readret;
98                                return 0; //ready
99                        }
100                        if(readret < 0 && errno == EAGAIN && c < 10)
101                        {
102                                c++;
103                                usleep(300000);
104                                goto retry;
105                        }
106                        *len = 0;
107                        if(fds.revents & POLLOUT && c == 10 && getqueue(dvbnode->devnr) != NULL)
108                        {
109                                perr("caread but queue not empty, so test a write, ret = %d", readret);
110                                return 1;
111                        }
112                        perr("caread ret = %d", readret);
113                        return -1; //error
114                }
115                else if(fds.revents & POLLOUT)
116                        return 1; //write
117                else if(fds.revents & POLLPRI)
118                        return 2; //change
119        }
120
121        perr("capoll ret = %d", ret);
122        return -1; //error
123}
124
125int cawrite(struct dvbdev* dvbnode, int fd, unsigned char* buf, int count, int flag, int tout)
126{
127        int ret = 0;
128
129        if(dvbnode != NULL)
130        {
131                if(debug_level == 620)
132                {
133                        int i = 0;
134                        printf("CA Write (slot %d fd %d): > ", dvbnode->devnr, dvbnode->fd);
135                        for(i = 0; i < count; i++)
136                                printf("%02x ", buf[i]);
137                        printf("\n");
138                }
139
140                if(dvbnode->caslot != NULL && flag == 0) dvbnode->caslot->fastrun = getconfigint("camwait", NULL);
141        }
142
143        ret = dvbwrite(fd, buf, count, tout);
144        if(checkbox("DM7020HD") == 1 || checkbox("DM7020HDV2") == 1)
145                usleep(150000);
146        if(ret >= 0 && ret == count && dvbnode != NULL && dvbnode->caslot != NULL) dvbnode->caslot->poll = 0;
147
148        return ret;
149}
150
151//send some data on an fd, for a special slot and connid
152int casend(struct dvbdev* dvbnode, unsigned char* buf, int len)
153{
154        unsigned char *tmpbuf = NULL;
155        int flag = 0;
156
157        if(dvbnode == NULL || dvbnode->caslot == NULL) return 1;
158        tmpbuf = (unsigned char*) malloc(len + 10);
159        if(tmpbuf == NULL)
160        {
161                err("no mem");
162                return 1;
163        }
164       
165#ifdef MIPSEL
166        memcpy(tmpbuf, buf, len);
167#else
168        // should we send a data last ?
169        if(buf != NULL)
170        {
171                if((buf[2] >= T_SB) && (buf[2] <= T_NEW_T_C))
172                        memcpy(tmpbuf, buf, len);
173                else
174                {
175                        //send data_last and data
176                        int lenfield = 0;
177
178                        tmpbuf[0] = dvbnode->devnr;
179                        tmpbuf[1] = dvbnode->caslot->connid;
180                        tmpbuf[2] = T_DATA_LAST;
181                        lenfield = writelengthfield(tmpbuf + 3, len + 1); //len
182                        tmpbuf[3 + lenfield] = dvbnode->caslot->connid; //transport connection identifier
183                       
184                        memcpy(tmpbuf + (4 + lenfield), buf, len);
185                        len += (4 + lenfield);
186                }
187        }
188        else
189        {
190                //send a data last only
191                tmpbuf[0] = dvbnode->devnr;
192                tmpbuf[1] = dvbnode->caslot->connid;
193                tmpbuf[2] = T_DATA_LAST;
194                tmpbuf[3] = 1; //len
195                tmpbuf[4] = dvbnode->caslot->connid; //transport connection identifier
196                len = 5;
197                flag = 1;
198        }
199#endif
200
201        if(debug_level == 620)
202        {
203                int i = 0;
204                printf("CA casend to queue (slot %d fd %d): > ", dvbnode->devnr, dvbnode->fd);
205                for(i = 0; i < len; i++)
206                        printf("%02x ", tmpbuf[i]);
207                printf("\n");
208        }
209       
210#ifdef MIPSEL
211        int ret = cawrite(dvbnode, dvbnode->fd, tmpbuf, len, flag, -1);
212        if(ret < 0 || ret != len)
213        {
214                err("writing data to queue, slot %d", dvbnode->devnr);
215                return 1; //error
216        }
217#else
218        struct queue* qe = addqueue(dvbnode->devnr, tmpbuf, len, NULL, 0, flag, NULL);
219        free(tmpbuf); tmpbuf = NULL;
220        if(qe == NULL)
221        {
222                err("writing data to queue, slot %d", dvbnode->devnr);
223                return 1; //error
224        }
225#endif
226
227        return 0; //ready
228}
229
230void sendSPDU(struct dvbdev* dvbnode, unsigned char tag, void *data, int len, int sessionnr, void *apdu, int alen)
231{
232        unsigned char* buf = NULL;
233        unsigned char *tmpbuf = NULL;
234
235        buf = calloc(1, MINMALLOC);
236        if(buf == NULL)
237        {
238                err("no mem");
239                return;
240        }
241
242        debug(620, "send SPDU, nr %d", sessionnr);
243
244        tmpbuf = buf;
245
246        *tmpbuf++ = tag;
247        tmpbuf += writelengthfield(tmpbuf, len + 2);
248
249        if(data != NULL) memcpy(tmpbuf, data, len);
250        tmpbuf += len;
251        *tmpbuf++ = sessionnr >> 8;
252        *tmpbuf++ = sessionnr;
253
254        if(apdu != NULL) memcpy(tmpbuf, apdu, alen);
255        tmpbuf += alen;
256
257        casend(dvbnode, buf, tmpbuf - buf);
258        free(buf); buf = NULL;
259}
260
261void sendAPDU(struct dvbdev* dvbnode, int sessionnr, unsigned char *tag, void *data, int len)
262{
263        debug(620, "send APDU, nr %d", sessionnr);
264
265        unsigned char buf[len + 3 + 4];
266        int lenfield = 0;
267
268        memcpy(buf, tag, 3);
269        lenfield = writelengthfield(buf + 3, len);
270
271        if(data != NULL) memcpy(buf + 3 + lenfield, data, len);
272        sendSPDU(dvbnode, 0x90, NULL, 0, sessionnr, buf, len + 3 + lenfield);
273}
274
275int parselenfield(unsigned char *buf, int* len)
276{
277        int i;
278
279        *len = 0;
280
281        if(!(*buf & 0x80))
282        {
283                *len = *buf;
284                return 1;
285        }
286
287        for(i = 0; i < (buf[0] & 0x7F); ++i)
288        {
289                *len <<= 8;
290                *len |= buf[i + 1];
291        }
292
293        return (buf[0] & 0x7F) + 1;
294}
295
296int asn1decode(uint16_t* lenret, unsigned char* asn1array, uint32_t asn1arraylen)
297{
298        uint8_t len;
299
300        if(asn1arraylen < 1 || asn1array == NULL) return -1;
301        len = asn1array[0];
302
303        if(len < 0x80)
304        {
305                //there is only one word
306                *lenret = len & 0x7f;
307                return 1;
308        }
309        else if(len == 0x81)
310        {
311                if(asn1arraylen < 2) return -1;
312                *lenret = asn1array[1];
313                return 2;
314        }
315        else if(len == 0x82)
316        {
317                if(asn1arraylen < 3) return -1;
318                *lenret = (asn1array[1] << 8) | asn1array[2];
319                return 3;
320        }
321
322        return -1;
323}
324
325//mmi functions
326
327int cammistop(struct dvbdev* dvbnode, int sessionnr)
328{
329        debug(620, "cammistop");
330
331        unsigned char tag[] = {0x9f, 0x88, 0x00};
332        unsigned char data[] = {0x00};
333        sendAPDU(dvbnode, sessionnr, tag, data, 1);
334
335        return 0;
336}
337
338int cammianswer(struct dvbdev* dvbnode, int sessionnr, int answer)
339{
340        debug(620, "cammianswer: %d", answer);
341
342        unsigned char tag[] = {0x9f, 0x88, 0x0B};
343        unsigned char data[] = {0x00};
344        data[0] = answer & 0xff;
345        sendAPDU(dvbnode, sessionnr, tag, data, 1);
346
347        return 0;
348}
349
350int cammianswerenq(struct dvbdev* dvbnode, int sessionnr, char *answer, int len)
351{
352        debug(620, "cammianswerenq (%d): %s", len, answer);
353
354        unsigned char data[len + 1];
355        data[0] = 0x01; //answer ok
356        memcpy(data + 1, answer, len);
357
358        unsigned char tag[] = {0x9f, 0x88, 0x08};
359        sendAPDU(dvbnode, sessionnr, tag, data, len + 1);
360
361        return 0;
362}
363
364int cammicancelenq(struct dvbdev* dvbnode, int sessionnr)
365{
366        debug(620, "cammicancelenq");
367
368        unsigned char tag[] = {0x9f, 0x88, 0x08};
369        unsigned char data[] = {0x00}; // canceled
370        sendAPDU(dvbnode, sessionnr, tag, data, 1);
371
372        return 0;
373}
374
375int cammiaction(struct dvbdev* dvbnode, int sessionnr)
376{
377        struct casession* casession = NULL;
378
379        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
380        casession = dvbnode->caslot->casession;
381
382        debug(620, "cammiaction nr %d, stat %d", sessionnr, casession[sessionnr].state);
383
384        switch(casession[sessionnr].state)
385        {
386                case CASESSIONSTART:
387                        debug(620, "state mmi sessionstart");
388                        casession[sessionnr].state = CAMMIIDLE;
389                        break;
390                case CAMMIDISPLAYREPLAY:
391                {
392                        debug(620, "state cammidisplayreplay");
393                        unsigned char tag[] = {0x9f, 0x88, 0x02};
394                        unsigned char data[] = {0x01, 0x01};
395                        sendAPDU(dvbnode, sessionnr, tag, data, 2);
396                        casession[sessionnr].state = CAMMIIDLE;
397                        //casession[sessionnr].state = CAMMIFAKEOK;
398                        //return 1;
399                        break;
400                }
401                case CAMMIFAKEOK:
402                {
403                        debug(620, "state cammifakeok");
404                        unsigned char tag[] = {0x9f, 0x88, 0x0b};
405                        unsigned char data[] = {5};
406                        sendAPDU(dvbnode, sessionnr, tag, data, 1);
407                        casession[sessionnr].state = CAMMIIDLE;
408                        break;
409                }
410                case CAMMIIDLE:
411                        debug(620, "state cammiidle");
412                        break;
413                default:
414                        break;
415        }
416        return 0;
417}
418
419int cammiAPDU(struct dvbdev* dvbnode, int sessionnr, unsigned char *tag, void *data, int len)
420{
421        char* tmpstr = NULL, *tmpstr1 = NULL;
422        struct casession* casession = NULL;
423        struct menulist* mlist = NULL, *mbox = NULL;
424
425        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
426        casession = dvbnode->caslot->casession;
427
428        debug(620, "mmi manager %02x %02x %02x", tag[0], tag[1], tag[2]);
429
430        if(debug_level == 620)
431        {
432                int i = 0;
433                printf("CA manager data (len %d): > ", len);
434                for(i = 0; i < len; i++)
435                        printf("%02x ", ((unsigned char*)data)[i]);
436                printf("\n");
437        }
438
439        if(tag[0] == 0x9f && tag[1] == 0x88)
440        {
441                switch(tag[2])
442                {
443                        case 0x00: //close
444                                cammistop(dvbnode, sessionnr);
445                                break;
446                        case 0x01: //display control
447                                casession[sessionnr].state = CAMMIDISPLAYREPLAY;
448                                return 1;
449                                break;
450                        case 0x07: //menu enq
451                        {
452                                unsigned char *tmpdata = data;
453                                unsigned char *max = tmpdata + len;
454                                int textlen = len - 2;
455
456                                if(tmpdata + 2 > max) break;
457                                int blind = *tmpdata++ & 1;
458                                int alen = *tmpdata++;
459
460                                debug(620, "mmi manager text len: %d, blind: %d", textlen, blind);
461
462                                if(tmpdata + textlen > max) break;
463
464                                char* str = malloc(textlen + 1);
465                                if(str == NULL)
466                                {
467                                        cammicancelenq(dvbnode, sessionnr);
468                                        break;
469                                }
470
471                                memcpy(str, tmpdata, textlen);
472                                str[textlen] = '\0';
473                                str = string_newline(str);
474
475                                debug(620, "mmi manager text: %s", str);
476
477                                int i = 0;
478                                for(i = 0; i < alen; i++) tmpstr1 = ostrcat(tmpstr1, "0", 1, 0);
479                                tmpstr = textinput(str, tmpstr1);
480                                if(tmpstr == NULL)
481                                        cammicancelenq(dvbnode, sessionnr);
482                                else
483                                {
484                                        if(strlen(tmpstr) > alen) tmpstr[alen] = '\0';
485                                        cammianswerenq(dvbnode, sessionnr, tmpstr, strlen(tmpstr));
486                                }
487                                free(tmpstr); tmpstr = NULL;
488                                free(tmpstr1); tmpstr1 = NULL;
489
490                        }
491                        break;
492                        case 0x09: //menu last
493                        case 0x0c: //list last
494                        {
495                                unsigned char *tmpdata = data;
496                                unsigned char *max= tmpdata + len;
497                                int pos = 0;
498
499                                if(tag[2] == 0x09)
500                                {
501                                        debug(620, "mmi manager menu last");
502                                }
503                                else
504                                {
505                                        debug(620, "mmi manager list last");
506                                }
507
508                                if(tmpdata > max) break;
509
510                                int n = *tmpdata++;
511
512                                if(n == 0xFF)
513                                        n = 0;
514                                else
515                                        n++;
516
517                                int i = 0;
518                                for(i = 0; i < (n + 3); ++i)
519                                {
520                                        int textlen = 0;
521                                        if(tmpdata + 3 > max) break;
522
523                                        debug(620, "mmi text tag: %02x %02x %02x", tmpdata[0], tmpdata[1], tmpdata[2]);
524                                        tmpdata += 3;
525                                        tmpdata += parselenfield(tmpdata, &textlen);
526
527                                        debug(620, "mmi manager text len: %d", textlen);
528                                        if(tmpdata + textlen > max) break;
529
530                                        char* str = malloc(textlen + 1);
531                                        if(str == NULL) break;
532                                        memcpy(str, tmpdata, textlen);
533                                        str[textlen] = '\0';
534                                        str = string_newline(str);
535
536                                        int type = pos++;
537
538                                        if(type == 0) // title
539                                                casession->mmititle = ostrcat(casession->mmititle, str, 1, 0);
540                                        else if(type == 1) // subtitle
541                                                casession->mmisubtitle = ostrcat(casession->mmisubtitle, str, 1, 0);
542                                        else if(type == 2) // bottom
543                                                casession->mmibottom = ostrcat(casession->mmibottom, str, 1, 0);
544                                        else // text
545                                        {
546                                                casession->mmitext = ostrcat(casession->mmitext, str, 1, 0);
547                                                casession->mmitext = ostrcat(casession->mmitext, "\n", 1, 0);
548                                        }
549
550                                        if(debug_level == 620)
551                                        {
552                                                printf("MMI Text: > ");
553                                                while(textlen--)
554                                                        printf("%c", *tmpdata++);
555                                                printf("\n");
556                                        }
557                                        else
558                                        {
559                                                while(textlen--)
560                                                        tmpdata++;
561                                        }
562
563                                }
564
565                                if(tag[2] == 0x09) //MENU
566                                {
567                                        tmpstr = ostrcat(tmpstr, casession->mmititle, 1, 0);
568                                        tmpstr = ostrcat(tmpstr, " - ", 1, 0);
569                                        tmpstr = ostrcat(tmpstr, casession->mmisubtitle, 1, 0);
570                                        tmpstr1 = ostrcat(tmpstr1, casession->mmitext, 1, 0);
571                                       
572                                        addmenulistall(&mlist, tmpstr1, NULL, 0, NULL);
573                                        mbox = menulistbox(mlist, "menulist", tmpstr, NULL, NULL, NULL, 1, 0);
574                                        if(mbox == NULL) //exit
575                                                cammistop(dvbnode, sessionnr);
576                                        else //got selnr
577                                        {
578                                                int i = 0, len = 0, slen = 0, selnr = 0, cmp = 1;
579
580                                                if(casession->mmitext != NULL)
581                                                        len = strlen(casession->mmitext);
582                                                slen = strlen(mbox->name);
583                                                for(i = 0; i < len; i++)
584                                                {
585                                                        if(cmp == 1)
586                                                        {
587                                                                cmp = 0;
588                                                                if(ostrncmp(mbox->name, &casession->mmitext[i], slen) == 0)
589                                                                        break;
590                                                        }
591
592                                                        if(casession->mmitext[i] == '\n')
593                                                        {
594                                                                selnr++;
595                                                                cmp = 1;
596                                                        }
597                                                }
598
599                                                cammianswer(dvbnode, sessionnr, selnr + 1);
600                                        }
601                                        freemenulist(mlist, 1); mlist = NULL;
602                                        free(tmpstr); tmpstr = NULL;
603                                        free(tmpstr1); tmpstr1 = NULL;
604                                        free(casession->mmititle); casession->mmititle = NULL;
605                                        free(casession->mmisubtitle); casession->mmisubtitle = NULL;
606                                        free(casession->mmitext); casession->mmitext = NULL;
607                                        free(casession->mmibottom); casession->mmibottom = NULL;
608                                }
609                                else //LIST
610                                {
611                                        tmpstr = ostrcat(tmpstr, casession->mmititle, 1, 0);
612                                        if(casession->mmisubtitle != NULL)
613                                        {
614                                                tmpstr1 = ostrcat(tmpstr1, casession->mmisubtitle, 1, 0);
615                                                tmpstr1 = ostrcat(tmpstr1, "\n\n", 1, 0);
616                                        }
617                                        if(casession->mmitext != NULL)
618                                        {
619                                                tmpstr1 = ostrcat(tmpstr1, casession->mmitext, 1, 0);
620                                                tmpstr1 = ostrcat(tmpstr1, "\n\n", 1, 0);
621                                        }
622                                        tmpstr1 = ostrcat(tmpstr1, casession->mmibottom, 1, 0);
623                                        if(getconfigint("nocamsg", NULL) == 0)
624                                                textbox(_(tmpstr), _(tmpstr1), NULL, getrcconfigint("rcok", NULL), NULL, getrcconfigint("rcexit", NULL), NULL, 0, NULL, 0, 600, 300, 7, 0);
625                                        free(tmpstr); tmpstr = NULL;
626                                        free(tmpstr1); tmpstr1 = NULL;
627                                        free(casession->mmititle); casession->mmititle = NULL;
628                                        free(casession->mmisubtitle); casession->mmisubtitle = NULL;
629                                        free(casession->mmitext); casession->mmitext = NULL;
630                                        free(casession->mmibottom); casession->mmibottom = NULL;
631                                        cammistop(dvbnode, sessionnr);
632                                }
633
634                        }
635                        break;
636                }
637        }
638        return 0;
639}
640
641//ca functions
642
643int cacaaction(struct dvbdev* dvbnode, int sessionnr)
644{
645        struct casession* casession = NULL;
646
647        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
648        casession = dvbnode->caslot->casession;
649
650        debug(620, "cacaaction nr %d, stat %d", sessionnr, casession[sessionnr].state);
651
652        switch(casession[sessionnr].state)
653        {
654                case CASESSIONSTART:
655                {
656                        debug(620, "state ca sessionstart");
657                        unsigned char tag[3] = {0x9F, 0x80, 0x30}; //ca info enq
658                        sendAPDU(dvbnode, sessionnr, tag, NULL, 0);
659                        casession[sessionnr].state = CASESSIONFINAL;
660                        return 0;
661                }
662                case CASESSIONFINAL:
663                        debug(620, "state cacafinal and action is not ok");
664                default:
665                        return 0;
666        }
667}
668
669int cacaAPDU(struct dvbdev* dvbnode, int sessionnr, unsigned char *tag, void *data, int len)
670{
671        int i = 0;
672        struct casession* casession = NULL;
673
674        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
675        casession = dvbnode->caslot->casession;
676
677        debug(620, "ca manager %02x %02x %02x", tag[0], tag[1], tag[2]);
678
679        if(debug_level == 620)
680        {
681                i = 0;
682                printf("CA manager data (len %d): > ", len);
683                for(i = 0; i < len; i++)
684                        printf("%02x ", ((unsigned char*)data)[i]);
685                printf("\n");
686        }
687
688        if(tag[0] == 0x9f && tag[1] == 0x80)
689        {
690                switch(tag[2])
691                {
692                        case 0x31: //ca info
693                                if(debug_level == 620)
694                                {
695                                        i = 0;
696                                        printf("Ca info (len %d): > ", len);
697                                        for(i = 0; i < len; i += 2)
698                                        {
699                                                printf("%04x ", (((unsigned char*)data)[i] << 8) | (((unsigned char*)data)[i + 1]));
700                                        }
701                                        printf("\n");
702                                }
703
704                                free(dvbnode->caslot->caids);
705                                dvbnode->caslot->caids = NULL;
706                                i = 0;
707                                for(i = 0; i < len; i += 2)
708                                {
709                                        dvbnode->caslot->caids = ostrcat(dvbnode->caslot->caids, "#", 1, 0);
710                                        dvbnode->caslot->caids = ostrcat(dvbnode->caslot->caids, oitoa((((unsigned char*)data)[i] << 8) | ((unsigned char*)data)[i + 1]), 1, 1);
711                                        dvbnode->caslot->caids = ostrcat(dvbnode->caslot->caids, "#", 1, 0);
712printf("dvbnode->caslot->caids %d: %s\n", i, dvbnode->caslot->caids);
713                                }
714/*
715neutrino work for hdpluss
716if (!caids.empty())
717        if ((caids[0] & 0xFF00) == 0x1800)
718        {
719                caids.push_back(0x186A);
720                printf("%04x", 0x186A);
721        }
722
723                                if ((dvbnode->caslot->caids[0] & 0xFF00) == 0x1800)
724                                {
725                                        printf("%04x", 0x186A);
726                                        dvbnode->caslot->caids = ostrcat(dvbnode->caslot->caids, "#", 1, 0);
727                                        dvbnode->caslot->caids = ostrcat(dvbnode->caslot->caids, oitoa(0x186A), 1, 1);
728                                        dvbnode->caslot->caids = ostrcat(dvbnode->caslot->caids, "#", 1, 0);
729printf("dvbnode->caslot->caids last: %s\n", dvbnode->caslot->caids);
730
731                                }
732*/                             
733                                break;
734                        case 0x33: //ca pmt reply
735                                if(len > 3)
736                                {
737                                        if(((unsigned char*)data)[3] == 0x81) //can descrambling
738                                        {
739                                                status.checkcamdecrypt = -1;
740                                                debug(620, "cam say's he can handel decrypt");
741                                        }
742                                        else
743                                        {
744                                                status.checkcamdecrypt = -2;
745                                                debug(620, "cam say's he can not handel decrypt");
746                                        }
747                                }
748                                break;
749                        default:
750                                debug(620, "unknown APDU tag 9F 80 %02x\n", tag[2]);
751                                break;
752                }
753        }
754        return 0;
755}
756
757//cc functions
758int caccaction(struct dvbdev* dvbnode, int sessionnr)
759{
760        struct casession* casession = NULL;
761        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
762                casession = dvbnode->caslot->casession;
763
764        debug(620, "caccaction nr %d, stat %d", sessionnr, casession[sessionnr].state);
765
766        switch (casession[sessionnr].state)
767        {
768                case CASESSIONSTART:
769                {
770                        casession[sessionnr].state = CASESSIONFINAL;
771                        return 0;
772                }
773                case CASESSIONFINAL:
774                        printf("stateFinal und action! kann doch garnicht sein ;)\n");
775                default:
776                        return 0;
777        }
778}
779
780int caccAPDU(struct dvbdev* dvbnode, int sessionnr, unsigned char *tag, void *data, int len)
781{
782        debug(620, "cc manager caccAPDU start");
783
784        int i = 0;
785        struct casession* casession = NULL;
786
787        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
788        casession = dvbnode->caslot->casession;
789
790        debug(620, "cc manager %02x %02x %02x", tag[0], tag[1], tag[2]);
791
792        if(debug_level == 620)
793        {
794                i = 0;
795                printf("CC manager data (len %d): > ", len);
796                for(i = 0; i < len; i++)
797                        printf("%02x ", ((unsigned char*)data)[i]);
798                printf("\n");
799        }
800
801        if(tag[0] == 0x9f && tag[1] == 0x90)
802        {
803                switch(tag[2])
804                {
805                        case 0x01: ci_ccmgr_cc_open_cnf(dvbnode, sessionnr); break;
806                        case 0x03: ci_ccmgr_cc_data_req(dvbnode, sessionnr, (uint8_t*)data, len); break;
807                        case 0x05: ci_ccmgr_cc_sync_req(dvbnode, sessionnr); break;
808                        case 0x07: ci_ccmgr_cc_sac_data_req(dvbnode, sessionnr, (uint8_t*)data, len); break;
809                        case 0x09: ci_ccmgr_cc_sac_sync_req(dvbnode, sessionnr, (uint8_t*)data, len); break;
810                        default:
811                                debug(620, "unknown APDU tag 9F 80 %02x\n", tag[2]);
812                                break;
813                }
814        }
815        return 0;
816}
817
818//datetime functions
819
820int cadatetimeaction(struct dvbdev* dvbnode, int sessionnr)
821{
822        struct casession* casession = NULL;
823
824        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
825        casession = dvbnode->caslot->casession;
826
827        debug(620, "cadatetimeaction nr %d, stat %d", sessionnr, casession[sessionnr].state);
828
829        switch(casession[sessionnr].state)
830        {
831                case CASESSIONSTART:
832                        debug(620, "state cadatetime sessionstart");
833                        return 0;
834                case CADATETIMESEND:
835                {
836                        debug(620, "state cadatetimesend");
837                        unsigned char tag[3] = {0x9f, 0x84, 0x41}; //datetime response
838                        unsigned char msg[7] = {0, 0, 0, 0, 0, 0, 0};
839                        sendAPDU(dvbnode, sessionnr, tag, msg, 7);
840                        return 0;
841                }
842                case CASESSIONFINAL:
843                        debug(620, "state cadatetimefinal and action is not ok");
844                default:
845                        return 0;
846        }
847}
848
849int cadatetimeAPDU(struct dvbdev* dvbnode, int sessionnr, unsigned char *tag, void *data, int len)
850{
851        struct casession* casession = NULL;
852
853        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
854        casession = dvbnode->caslot->casession;
855
856        debug(620, "datetime manager %02x %02x %02x", tag[0], tag[1], tag[2]);
857
858        if(debug_level == 620)
859        {
860                int i = 0;
861                printf("Datetime manager data (len %d): > ", len);
862                for(i = 0; i < len; i++)
863                        printf("%02x ", ((unsigned char*)data)[i]);
864                printf("\n");
865        }
866
867        if(tag[0] == 0x9f && tag[1] == 0x84)
868        {
869                switch(tag[2])
870                {
871                        case 0x40:
872                                casession[sessionnr].state = CADATETIMESEND;
873                                return 1;
874                                break;
875                        default:
876                                debug(620, "unknown APDU tag 9F 84 %02x\n", tag[2]);
877                                break;
878                }
879        }
880
881        return 0;
882}
883
884//res function
885
886int caresaction(struct dvbdev* dvbnode, int sessionnr)
887{
888        struct casession* casession = NULL;
889
890        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
891        casession = dvbnode->caslot->casession;
892
893        debug(620, "caresaction nr %d, stat %d", sessionnr, casession[sessionnr].state);
894
895        switch(casession[sessionnr].state)
896        {
897                case CASESSIONSTART:
898                {
899                        debug(620, "state cares sessionstart");
900                        unsigned char tag[3] = {0x9F, 0x80, 0x10}; //profile enquiry
901                        checkcerts();
902                        sendAPDU(dvbnode, sessionnr, tag, NULL, 0);
903                        casession[sessionnr].state = CARESFIRSTENQUIRY;
904                        return 0;
905                }
906                case CARESFIRSTENQUIRY:
907                {
908                        debug(620, "state caresfirstenquiry");
909                        unsigned char tag[3] = {0x9F, 0x80, 0x12}; //profile change
910                        sendAPDU(dvbnode, sessionnr, tag, NULL, 0);
911                        casession[sessionnr].state = CARESCHANGE;
912                        return 0;
913                }
914                case CARESCHANGE:
915                {
916                        debug(620, "state careschange not ok");
917                        break;
918                }
919                case CARESENQUIRY:
920                {
921                        debug(620, "state caresenquiry");
922                        unsigned char tag[3] = {0x9F, 0x80, 0x11};
923
924                        if(checkcerts() == 1)
925                        {
926                                unsigned char data[][4]=
927                                {
928                                        {0x00, 0x01, 0x00, 0x41},       // resource
929                                        {0x00, 0x02, 0x00, 0x41},       // application V1
930                                        {0x00, 0x02, 0x00, 0x43},       // application V3
931                                        {0x00, 0x03, 0x00, 0x41},       // conditional access
932//                                      {0x00, 0x20, 0x00, 0x41},       // host control
933                                        {0x00, 0x40, 0x00, 0x41},       // mmi
934                                        {0x00, 0x24, 0x00, 0x41},       // date-time
935                                        {0x00, 0x8c, 0x10, 0x01}        // content control
936//                                      {0x00, 0x10, 0x00, 0x41}        // auth.
937                                };
938                                sendAPDU(dvbnode, sessionnr, tag, data, sizeof(data));
939                        }
940                        else
941                        {                       
942                                unsigned char data[][4]=
943                                {
944                                        {0x00, 0x01, 0x00, 0x41},
945                                        {0x00, 0x02, 0x00, 0x41},
946                                        {0x00, 0x03, 0x00, 0x41},
947                                        //{0x00, 0x20, 0x00, 0x41}, //host control
948                                        {0x00, 0x24, 0x00, 0x41},
949                                        {0x00, 0x40, 0x00, 0x41}
950                                        //{0x00, 0x10, 0x00, 0x41} //auth.
951                                };
952                                sendAPDU(dvbnode, sessionnr, tag, data, sizeof(data));
953                        };
954                        casession[sessionnr].state = CASESSIONFINAL;
955                        return 0;
956                }
957                case CASESSIONFINAL:
958                        debug(620, "state caresfinal and action is not ok");
959                default:
960                        break;
961        }
962
963        return 0;
964}
965
966int caresAPDU(struct dvbdev* dvbnode, int sessionnr, unsigned char *tag, void *data, int len)
967{
968        struct casession* casession = NULL;
969
970        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
971        casession = dvbnode->caslot->casession;
972
973        debug(620, "res manager %02x %02x %02x", tag[0], tag[1], tag[2]);
974
975        if(debug_level == 620)
976        {
977                int i = 0;
978                printf("Res manager data (len %d): > ", len);
979                for(i = 0; i < len; i++)
980                        printf("%02x ", ((unsigned char*)data)[i]);
981                printf("\n");
982        }
983
984        if(tag[0] == 0x9f && tag[1] == 0x80)
985        {
986                switch(tag[2])
987                {
988                        case 0x10:  // profile enquiry
989                                debug(620, "cam ask what can i");
990                                casession[sessionnr].state = CARESENQUIRY;
991                                return 1;
992                        case 0x11: // Tprofile
993                                if(debug_level == 620)
994                                {
995                                        printf("My cam can: > ");
996                                        if(!len)
997                                                printf("nothing\n");
998                                        else
999                                        {
1000                                                int i = 0;
1001                                                for (i = 0; i < len; i++)
1002                                                        printf("%02x ", ((unsigned char*)data)[i]);
1003                                        }
1004                                }
1005
1006                                if(casession[sessionnr].state == CARESFIRSTENQUIRY)
1007                                {
1008                                        // profile change
1009                                        return 1;
1010                                }
1011                                casession[sessionnr].state = CASESSIONFINAL;
1012                                break;
1013                        default:
1014                                debug(620, "unknown APDU tag 9F 80 %02x\n", tag[2]);
1015                }
1016        }
1017
1018        return 0;
1019}
1020
1021//app functions
1022
1023void caappmenu(struct dvbdev* dvbnode)
1024{
1025        //must be send to the app session
1026        debug(620, "caappmenu");
1027        unsigned char tag[3] = {0x9F, 0x80, 0x22};  //Tenter_menu
1028        int sessionnr = 0;
1029
1030        sessionnr = getfreecasession(dvbnode, 1, 1);
1031        if(sessionnr > -1)
1032                sendAPDU(dvbnode, sessionnr, tag, NULL, 0);
1033}
1034
1035int caappaction(struct dvbdev* dvbnode, int sessionnr)
1036{
1037        struct casession* casession = NULL;
1038
1039        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
1040        casession = dvbnode->caslot->casession;
1041
1042        debug(620, "caappaction nr %d, stat %d", sessionnr, casession[sessionnr].state);
1043
1044        switch(casession[sessionnr].state)
1045        {
1046                case CASESSIONSTART:
1047                {
1048                        debug(620, "state app sessionstart");
1049                        unsigned char tag[3] = {0x9F, 0x80, 0x20}; //app manager info
1050
1051                        sendAPDU(dvbnode, sessionnr, tag, NULL, 0);
1052                        casession[sessionnr].state = CASESSIONFINAL;
1053                        return 1;
1054                }
1055                case CASESSIONFINAL:
1056                {
1057                        debug(620, "state app sessionfinal");
1058                        return 0;
1059                }
1060                default:
1061                        return 0;
1062        }
1063}
1064
1065int caappAPDU(struct dvbdev* dvbnode, int sessionnr, unsigned char *tag, void *data, int len)
1066{
1067        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
1068
1069        debug(620, "app manager %02x %02x %02x", tag[0], tag[1], tag[2]);
1070
1071        if(debug_level == 620)
1072        {
1073                int i = 0;
1074                printf("App manager data (len %d): > ", len);
1075                for(i = 0; i < len; i++)
1076                        printf("%02x ", ((unsigned char*)data)[i]);
1077                printf("\n");
1078        }
1079
1080        if(tag[0] == 0x9f && tag[1] == 0x80)
1081        {
1082                switch (tag[2])
1083                {
1084                        case 0x21:
1085                        {
1086                                int dl;
1087                                debug(620, "app manager info:");
1088                                debug(620, "len: %d", len);
1089                                debug(620, "type: %d", ((unsigned char*)data)[0]);
1090                                debug(620, "manufacturer: %02x %02x", ((unsigned char*)data)[2], ((unsigned char*)data)[1]);
1091                                debug(620, "code: %02x %02x", ((unsigned char*)data)[4],((unsigned char*)data)[3]);
1092
1093                                dl = ((unsigned char*)data)[5];
1094                                if(dl + 6 > len)
1095                                {
1096                                        debug(620, "invalid length (%d vs %d)", dl + 6, len);
1097                                        dl = len - 6;
1098                                }
1099
1100                                char str[dl + 1];
1101                                memcpy(str, data + 6, dl);
1102                                str[dl] = '\0';
1103
1104                                if(debug_level == 620)
1105                                {
1106                                        int i = 0;
1107                                        printf("Menu string (len %d): > ", dl);
1108                                        for(i = 0; i < dl; ++i)
1109                                                printf("%c", ((unsigned char*)data)[i + 6]);
1110                                        printf("\n");
1111                                }
1112
1113                                free(dvbnode->caslot->name);
1114                                dvbnode->caslot->name = strstrip(ostrcat(str, NULL, 0, 1));
1115                                debug(620, "set name %s on slot %d", dvbnode->caslot->name, dvbnode->devnr);
1116                                break;
1117                        }
1118                        default:
1119                        {
1120                                debug(620, "unknown APDU tag 9F 80 %02x\n", tag[2]);
1121                                break;
1122                        }
1123                }
1124        }
1125
1126        return 0;
1127}
1128
1129//session functions
1130
1131//inuse: 1 is only that the session is in use
1132//inuse: >1 the session is used for decrypt
1133int getfreecasession(struct dvbdev* dvbnode, int type, int value)
1134{
1135        int i;
1136
1137        if(dvbnode != NULL && dvbnode->caslot != NULL)
1138        {
1139                for(i = 0; i < MAXCASESSION; i++)
1140                {
1141                        if(type == 0 && dvbnode->caslot->casession[i].resmanager == 1 && dvbnode->caslot->casession[i].inuse == 1) //resmanager
1142                        {
1143                                dvbnode->caslot->casession[i].inuse = value;
1144                                return i;
1145                        }
1146                        if(type == 1 && dvbnode->caslot->casession[i].appmanager == 1 && dvbnode->caslot->casession[i].inuse == 1) //appmanager
1147                        {
1148                                dvbnode->caslot->casession[i].inuse = value;
1149                                return i;
1150                        }
1151                        if(type == 2 && dvbnode->caslot->casession[i].camanager == 1 && dvbnode->caslot->casession[i].inuse == 1) //camanager
1152                        {
1153                                dvbnode->caslot->casession[i].inuse = value;
1154                                return i;
1155                        }
1156                        if(type == 3 && dvbnode->caslot->casession[i].datetimemanager == 1 && dvbnode->caslot->casession[i].inuse == 1) //datetimemanager
1157                        {
1158                                dvbnode->caslot->casession[i].inuse = value;
1159                                return i;
1160                        }
1161                        if(type == 4 && dvbnode->caslot->casession[i].mmimanager == 1 && dvbnode->caslot->casession[i].inuse == 1) //mmimemanager
1162                        {
1163                                dvbnode->caslot->casession[i].inuse = value;
1164                                return i;
1165                        }
1166                        if(type == 5 && dvbnode->caslot->casession[i].ccmanager == 1 && dvbnode->caslot->casession[i].inuse == 1) //ccmanager
1167                        {
1168                                dvbnode->caslot->casession[i].inuse = value;
1169                                return i;
1170                        }
1171                }
1172        }
1173        return -1;
1174}
1175
1176void casessiondel(struct dvbdev* dvbnode, int sessionnr)
1177{
1178        if(dvbnode != NULL && dvbnode->caslot != NULL)
1179        {
1180                free(dvbnode->caslot->casession[sessionnr].mmititle);
1181                free(dvbnode->caslot->casession[sessionnr].mmisubtitle);
1182                free(dvbnode->caslot->casession[sessionnr].mmitext);
1183                free(dvbnode->caslot->casession[sessionnr].mmibottom);
1184                memset(&dvbnode->caslot->casession[sessionnr], 0, sizeof(struct casession));
1185        }
1186}
1187
1188void casessionfree(struct dvbdev* dvbnode)
1189{
1190        int i = 0;
1191
1192        for(i = 0; i < MAXCASESSION; i++)
1193                casessiondel(dvbnode, i);
1194}
1195
1196int casessionpoll(struct dvbdev* dvbnode)
1197{
1198        int sessionnr = 0;
1199        struct casession* casession = NULL;
1200
1201        if(dvbnode == NULL || dvbnode->caslot == NULL) return 0;
1202        casession = dvbnode->caslot->casession;
1203
1204        for(sessionnr = 1; sessionnr < MAXCASESSION; ++sessionnr)
1205        {
1206                if(casession[sessionnr].inuse > 0)
1207                {
1208                        if(casession[sessionnr].state == CASESSIONDEL)
1209                        {
1210                                unsigned char data[1] = {0x00};
1211                                sendSPDU(dvbnode, 0x96, data, 1, sessionnr, NULL, 0);
1212                                casessiondel(dvbnode, sessionnr);
1213                                return 1;
1214                        }
1215                        else if(casession[sessionnr].action == 1)
1216                        {
1217                                if(casession[sessionnr].resmanager == 1)
1218                                        casession[sessionnr].action = caresaction(dvbnode, sessionnr);
1219                                else if(casession[sessionnr].appmanager == 1)
1220                                        casession[sessionnr].action = caappaction(dvbnode, sessionnr);
1221                                else if(casession[sessionnr].ccmanager == 1)
1222                                        casession[sessionnr].action = caccaction(dvbnode, sessionnr);
1223                                else if(casession[sessionnr].camanager == 1)
1224                                        casession[sessionnr].action = cacaaction(dvbnode, sessionnr);
1225                                else if(casession[sessionnr].datetimemanager == 1)
1226                                        casession[sessionnr].action = cadatetimeaction(dvbnode, sessionnr);
1227                                else if(casession[sessionnr].mmimanager == 1)
1228                                        casession[sessionnr].action = cammiaction(dvbnode, sessionnr);
1229                                return 1;
1230                        }
1231                }
1232        }
1233        return 0;
1234}
1235
1236struct casession* casessioncreate(struct dvbdev* dvbnode, unsigned char* resid, unsigned char status, unsigned long newtag)
1237{
1238        unsigned long tag = 0;
1239        int sessionnr = 0;
1240        struct casession* casession = NULL;
1241
1242        if(dvbnode == NULL || dvbnode->caslot == NULL) return NULL;
1243        casession = dvbnode->caslot->casession;
1244
1245        for(sessionnr = 1; sessionnr < MAXCASESSION; ++sessionnr)
1246                if(casession[sessionnr].inuse == 0)
1247                        break;
1248
1249        if(sessionnr == MAXCASESSION)
1250        {
1251                status = 0xF3;
1252                debug(620, "no free session found nr = %d", sessionnr);
1253                return NULL;
1254        }
1255
1256        debug(620, "use sessionnr = %d", sessionnr);
1257        if(newtag == 0)
1258        {
1259                tag = resid[0] << 24;
1260                tag |= resid[1] << 16;
1261                tag |= resid[2] << 8;
1262                tag |= resid[3];
1263        }
1264        else
1265                tag = newtag;
1266
1267        switch(tag)
1268        {
1269                case 0x00010041:
1270                        casession[sessionnr].inuse = 1;
1271                        casession[sessionnr].resmanager = 1;
1272                        debug(620, "create session res manager");
1273                        break;
1274                case 0x00020041:
1275                case 0x00020043:
1276                        casession[sessionnr].inuse = 1;
1277                        casession[sessionnr].appmanager = 1;
1278                        debug(620, "create session app manager");
1279                        break;
1280                case 0x00030041:
1281                        casession[sessionnr].inuse = 1;
1282                        casession[sessionnr].camanager = 1;
1283                        debug(620, "create session ca manager");
1284                        break;
1285                case 0x00240041:
1286                        casession[sessionnr].inuse = 1;
1287                        casession[sessionnr].datetimemanager = 1;
1288                        debug(620, "create session datetime manager");
1289                        break;
1290                case 0x00400041:
1291                        casession[sessionnr].inuse = 1;
1292                        casession[sessionnr].mmimanager = 1;
1293                        //neutrino sessions[session_nb - 1] = new eDVBCIMMISession(slot);
1294                        debug(620, "create session mmi manager");
1295                        break;
1296                if(checkcerts())
1297                {
1298                        case 0x008c1001:
1299                                casession[sessionnr].inuse = 1;
1300                                casession[sessionnr].ccmanager = 1;
1301                                //neutrino [session_nb - 1] = new eDVBCIContentControlManagerSession(slot);
1302                                debug(620, "create session cc manager");
1303                                break;
1304                }
1305                case 0x00100041:
1306                        debug(620, "create session auth manager");
1307                case 0x00200041:
1308                default:
1309                        status = 0xF0;
1310                        if(resid != NULL)
1311                                debug(620, "unknown resource type %02x %02x %02x %02x\n", resid[0], resid[1], resid[2], resid[3]);
1312                        return NULL;
1313        }
1314
1315        debug(620, "new session nr: %d", sessionnr);
1316        casession[sessionnr].sessionnr = sessionnr;
1317        casession[sessionnr].state = CASESSIONCREATE;
1318        status = 0;
1319
1320        if(newtag != 0)
1321        {
1322                unsigned char data[4];
1323                data[0] = (newtag >> 24) & 0xff;
1324                data[1] = (newtag >> 16) & 0xff;
1325                data[2] = (newtag >> 8) & 0xff;
1326                data[3] = newtag & 0xff;
1327                sendSPDU(dvbnode, 0x93, data, 4, sessionnr, NULL, 0);
1328        }
1329
1330        return &casession[sessionnr];
1331}
1332
1333void casessionreceive(struct dvbdev* dvbnode, unsigned char *buf, size_t len)
1334{
1335        unsigned char *pkt = buf;
1336        unsigned char tag = *pkt++;
1337        int llen = 0, hlen = 0;
1338        struct casession* casession = NULL;
1339        int sessionnr = 0;
1340
1341        if(dvbnode == NULL || dvbnode->caslot == NULL) return;
1342
1343        if(debug_level == 620)
1344        {
1345                printf("Session Data (len %d): > ", len);
1346                int i = 0;
1347                for(i = 0; i < len; i++)
1348                        printf("%02x ", buf[i]);
1349                printf("\n");
1350        }
1351
1352        llen = parselenfield(pkt, &hlen);
1353        pkt += llen;
1354
1355        if(tag == 0x91)
1356        {
1357                unsigned char status = 0;
1358
1359                casession = casessioncreate(dvbnode, pkt, status, 0);
1360
1361                //open session
1362                unsigned char data[6];
1363                data[0] = status;
1364                memcpy(data + 1, pkt, 4);
1365                if(casession != NULL)
1366                {
1367                        sendSPDU(dvbnode, 0x92, data, 5, casession->sessionnr, NULL, 0);
1368                        casession->state = CASESSIONSTART;
1369                        casession->action = 1;
1370                }
1371                else
1372                        sendSPDU(dvbnode, 0x92, data, 5, 0, NULL, 0);
1373        }
1374        else
1375        {
1376                sessionnr = pkt[hlen - 2] << 8;
1377                sessionnr |= pkt[hlen - 1] & 0xFF;
1378                debug(620, "tag = %x, hlen = %d, session = %d", tag, hlen, sessionnr);
1379
1380                if(sessionnr < 1 || sessionnr >= MAXCASESSION)
1381                {
1382                        debug(620, "illegal session number %d", sessionnr);
1383                        return;
1384                }
1385
1386                casession = &dvbnode->caslot->casession[sessionnr];
1387                if(casession->inuse == 0)
1388                {
1389                        debug(620, "data on closed session %d", sessionnr);
1390                        return;
1391                }
1392
1393                switch(tag)
1394                {
1395                        case 0x90:
1396                                break;
1397                        case 0x94:
1398                                debug(620, "recv create session response %02x", pkt[0]);
1399                                if(pkt[0] != 0)
1400                                        casessiondel(dvbnode, sessionnr);
1401                                else
1402                                {
1403                                        casession->state = CASESSIONSTART;
1404                                        casession->action = 1;
1405                                }
1406                                break;
1407                        case 0x95:
1408                                debug(620, "recv close session");
1409                                casession->state = CASESSIONDEL;
1410                                casession->action = 1;
1411                                break;
1412                        default:
1413                                debug(620, "not supported tag %02x", tag);
1414                                return;
1415                }
1416        }
1417
1418        hlen += llen + 1; // lengthfield and tag
1419
1420        pkt = buf + hlen;
1421        len -= hlen;
1422
1423        if(casession != NULL)
1424        {
1425                debug(620, "len %d", len);
1426                while(len > 0)
1427                {
1428                        int alen = 0;
1429                        unsigned char *tag = pkt;
1430                        pkt += 3; //tag
1431                        len -= 3;
1432                        hlen = parselenfield(pkt, &alen);
1433                        pkt += hlen;
1434                        len -= hlen;
1435                        debug(620, "len = %d, hlen = %d, alen = %d", len, hlen, alen);
1436
1437                        if(len - alen > 0 && len - alen < 3)
1438                                alen = len;
1439
1440                        debug(620, "got APDU tag = 0x%2x, len = %d", (int)tag, alen);
1441
1442                        if(casession->resmanager == 1)
1443                        {
1444                                if(caresAPDU(dvbnode, sessionnr, tag, pkt, alen))
1445                                        casession->action = 1;
1446                        }
1447                        else if(casession->appmanager == 1)
1448                        {
1449                                if(caappAPDU(dvbnode, sessionnr, tag, pkt, alen))
1450                                        casession->action = 1;
1451                        }
1452                        else if(casession->ccmanager == 1)
1453                        {
1454                                if(caccAPDU(dvbnode, sessionnr, tag, pkt, alen))
1455                                        casession->action = 1;
1456                        }
1457                        else if(casession->camanager == 1)
1458                        {
1459                                if(cacaAPDU(dvbnode, sessionnr, tag, pkt, alen))
1460                                        casession->action = 1;
1461                        }
1462                        else if(casession->datetimemanager == 1)
1463                        {
1464                                if(cadatetimeAPDU(dvbnode, sessionnr, tag, pkt, alen))
1465                                        casession->action = 1;
1466                        }
1467                        else if(casession->mmimanager == 1)
1468                        {
1469                                if(cammiAPDU(dvbnode, sessionnr, tag, pkt, alen))
1470                                        casession->action = 1;
1471                        }
1472
1473                        pkt += alen;
1474                        len -= alen;
1475                }
1476
1477        }
1478
1479        if(len != 0)
1480                debug(620, "warning, TL-Data has invalid length");
1481}
1482
1483//slot function
1484
1485//send a transport connection create request
1486int cacreatetc(struct dvbdev* dvbnode)
1487{
1488        int ret = 0;
1489        unsigned char* buf = NULL;
1490
1491        if(dvbnode == NULL || dvbnode->caslot == NULL ) return 1;
1492
1493        buf = (unsigned char*) malloc(sizeof(char) * 5);
1494        if(buf == NULL)
1495        {
1496                err("no mem");
1497                return 1;
1498        }
1499
1500        buf[0] = dvbnode->devnr;
1501        buf[1] = dvbnode->caslot->connid;
1502        buf[2] = T_CREATE_T_C;
1503        buf[3] = 1;
1504        buf[4] = dvbnode->caslot->connid;
1505
1506        ret = cawrite(dvbnode, dvbnode->fd, buf, 5, 0, -1);
1507        free(buf); buf = NULL;
1508        dvbnode->caslot->poll = 0;
1509        if(checkbox("DM7020HD") == 1 || checkbox("DM7020HDV2") == 1)
1510                sleep(1);
1511        return ret;
1512}
1513
1514void caslotfree(struct dvbdev* dvbnode)
1515{
1516        if(dvbnode != NULL && dvbnode->caslot != NULL)
1517        {
1518                free(dvbnode->caslot->name);
1519                dvbnode->caslot->name = NULL;
1520                free(dvbnode->caslot->rbuf);
1521                dvbnode->caslot->rbuf = NULL;
1522                free(dvbnode->caslot->caids);
1523                dvbnode->caslot->caids = NULL;
1524                memset(dvbnode->caslot, 0, sizeof(struct caslot));
1525        }
1526        if(dvbnode != NULL) caservicedel(NULL, dvbnode->caslot);
1527}
1528
1529void processtpdu(struct dvbdev* dvbnode, unsigned char tpdutag, unsigned char* buf, int asnlen)
1530{
1531        struct caslot* canode = NULL;
1532
1533        if(dvbdev == NULL) return;
1534        canode = dvbnode->caslot;
1535
1536        switch(tpdutag)
1537        {
1538                case T_C_T_C_REPLY:
1539                        debug(620, "got ctc replay (slot %d, conn %d)", dvbnode->devnr, canode->connid);
1540
1541                        casend(dvbnode, NULL, 0);
1542
1543                        break;
1544                case T_DELETE_T_C:
1545                        debug(620, "got delete transport connection (slot %d, conn %d)", dvbnode->devnr, canode->connid);
1546
1547                        //send the D_T_C_REPLAY
1548                        unsigned char sendbuf[5];
1549
1550                        sendbuf[0] = dvbnode->devnr;
1551                        sendbuf[1] = canode->connid;
1552                        sendbuf[2] = T_D_T_C_REPLY;
1553                        sendbuf[3] = 1;
1554                        sendbuf[4] = canode->connid;
1555
1556                        cawrite(dvbnode, dvbnode->fd, sendbuf, 5, 0, -1);
1557                        casessionfree(dvbnode);
1558                        caslotfree(dvbnode);
1559
1560                        break;
1561                case T_D_T_C_REPLY:
1562
1563                        debug(620, "got delete transport connection replay (slot %d, conn %d)", dvbnode->devnr, canode->connid);
1564
1565                        casessionfree(dvbnode);
1566                        caslotfree(dvbnode);
1567                        break;
1568
1569                case T_REQUEST_T_C:
1570
1571                        debug(620, "got request transport connection (slot %d, conn %d)", dvbnode->devnr, canode->connid);
1572
1573                        break;
1574                case T_DATA_MORE:
1575                {
1576                        int newbuflen = canode->rlen + asnlen;
1577
1578                        debug(620, "got data more (slot %d, conn %d)", dvbnode->devnr, canode->connid);
1579
1580                        canode->rbuf = realloc(canode->rbuf, newbuflen);
1581                        if(canode->rbuf != NULL)
1582                        {
1583                                memcpy(canode->rbuf + canode->rlen, buf, asnlen);
1584                                canode->rlen = newbuflen;
1585                        }
1586
1587                        break;
1588                }
1589                case T_DATA_LAST:
1590                {
1591                        if(canode->rbuf == NULL)
1592                        {
1593                                debug(620, "got data last single package (slot %d, conn %d)", dvbnode->devnr, canode->connid);
1594
1595                                casessionreceive(dvbnode, buf, asnlen);
1596                                casessionpoll(dvbnode);
1597                        }
1598                        else
1599                        {
1600                                debug(620, "got data last chained package (slot %d, conn %d)", dvbnode->devnr, canode->connid);
1601                                int newbuflen = canode->rlen + asnlen;
1602
1603                                canode->rbuf = realloc(canode->rbuf, newbuflen);
1604                                if(canode->rbuf != NULL)
1605                                {
1606                                        memcpy(canode->rbuf + canode->rlen, buf, asnlen);
1607                                        canode->rlen = newbuflen;
1608                                        casessionreceive(dvbnode, canode->rbuf, canode->rlen);
1609                                        casessionpoll(dvbnode);
1610                                }
1611
1612                                free(canode->rbuf);
1613                                canode->rbuf = NULL;
1614                                canode->rlen = 0;
1615                        }
1616                        break;
1617                }
1618                case T_SB:
1619                {
1620                        //debug(620, "got sb (slot %d, conn %d, buf %02x)", dvbnode->devnr, canode->connid, buf[0]);
1621
1622                        if(buf[0] & 0x80)
1623                        {
1624                                debug(620, "data ready (slot %d)", dvbnode->devnr);
1625
1626                                //send the RCV and ask for the data
1627                                unsigned char sendbuf[5];
1628
1629                                sendbuf[0] = dvbnode->devnr;
1630                                sendbuf[1] = canode->connid;
1631                                sendbuf[2] = T_RCV;
1632                                sendbuf[3] = 1;
1633                                sendbuf[4] = canode->connid;
1634
1635                                cawrite(dvbnode, dvbnode->fd, sendbuf, 5, 0, -1);
1636                        }
1637                        break;
1638                }
1639                case 0x13: //MIPSEL
1640                {
1641                        debug(620, "got mipsel session data (slot %d, conn %d)", dvbnode->devnr, canode->connid);
1642                        casessionreceive(dvbnode, buf, asnlen);
1643                        casessionpoll(dvbnode);
1644                        break;
1645                }
1646                default:
1647                        debug(620, "unknown tpdu tag 0x%0x (slot %d, conn %d)", tpdutag, dvbnode->devnr, canode->connid);
1648        }
1649}
1650
1651void cacheck(struct stimerthread* self, struct dvbdev* dvbnode)
1652{
1653        int ret = 0, len = MINMALLOC;
1654        ca_slot_info_t info;
1655        struct caslot* canode = NULL;
1656        unsigned char* buf = NULL;
1657#ifdef SH4
1658        unsigned char* tmpbuf = NULL;
1659#endif
1660#ifdef SIMULATE
1661        unsigned char* tmpbuf = NULL;
1662#endif
1663        if(dvbnode == NULL) return;
1664        canode = dvbnode->caslot;
1665
1666        buf = calloc(1, MINMALLOC);
1667        if(buf == NULL)
1668        {
1669                err("no mem");
1670                return;
1671        }
1672
1673        switch(canode->status)
1674        {
1675                case 0: //idle
1676                case 100: //manuell reset
1677                {
1678                        if(canode->status == 0)
1679                                cawait(self, dvbnode, -1);
1680                        canode->status = 0;
1681                        debug(620, "status: no, slot %d", dvbnode->devnr);
1682                        if(dvbnode->caslot->status == 101) break; //titan end
1683
1684                        //reset the module an wait max 10 sek
1685                        careseting(self, dvbnode, 0);
1686
1687                        info.num = dvbnode->devnr;
1688                        if(cagetslotinfo(dvbnode, &info) == 0)
1689                        {
1690                                debug(620, "flags %d %d %d, slot %d", info.flags, CA_CI_MODULE_READY, info.flags & CA_CI_MODULE_READY, dvbnode->devnr);
1691
1692                                if(info.flags & CA_CI_MODULE_READY)
1693                                {
1694                                        debug(620, "cam (slot %d) status changed, cam now present", dvbnode->devnr);
1695                                        canode->connid = dvbnode->devnr + 1;
1696                                        if(cacreatetc(dvbnode) == 5)
1697                                        {
1698                                                casessionfree(dvbnode);
1699                                                caslotfree(dvbnode);
1700                                                canode->status = 1;
1701                                                canode->connid = dvbnode->devnr + 1;
1702                                                dvbnode->caslot->fastrun = getconfigint("camwait", NULL);
1703                                        }
1704                                        else
1705                                        {
1706                                                canode->connid = 0;
1707                                                sleep(1);
1708                                        }
1709                                }
1710                        }
1711                        else
1712                                sleep(1);
1713                }
1714                break;
1715                case 1: //active
1716                case 2: //active (ca and app ready)
1717                {
1718                        //debug(620, "status: wait, slot %d", dvbnode->devnr);
1719                        ret = caread(dvbnode, buf, &len);
1720                        if(dvbnode->caslot->status == 101) break; //titan end
1721                        if(ret == 0) //ready
1722                        {
1723                                //debug(620, "read, slot %d, ret %d", dvbnode->devnr, ret);
1724#ifdef MIPSEL
1725                                canode->poll = 1;
1726                                canode->connid = dvbnode->devnr + 1;
1727                                processtpdu(dvbnode, 0x13, buf, len);
1728#else
1729                                tmpbuf = buf;
1730                                int buflen = len - 2;
1731                                tmpbuf += 2; //remove leading slot and connection id
1732                                while(buflen > 0)
1733                                {
1734                                        unsigned char tpdutag = tmpbuf[0];
1735                                        unsigned short asnlen;
1736                                        int lenfieldlen;
1737
1738                                        canode->poll = 1;
1739                                        lenfieldlen = asn1decode(&asnlen, tmpbuf + 1, buflen - 1);
1740
1741                                        if(lenfieldlen < 0 || asnlen < 1 || asnlen > (buflen - (1 + lenfieldlen)))
1742                                        {
1743                                                err("received data with invalid asn from module on slot %d", dvbnode->devnr);
1744                                                break;
1745                                        }
1746
1747                                        canode->connid = tmpbuf[1 + lenfieldlen];
1748                                        tmpbuf += 1 + lenfieldlen + 1;
1749                                        buflen -= (1 + lenfieldlen + 1);
1750                                        asnlen--;
1751
1752                                        processtpdu(dvbnode, tpdutag, tmpbuf, asnlen);
1753
1754                                        //skip over the consumed data
1755                                        tmpbuf += asnlen;
1756                                        buflen -= asnlen;
1757                                }
1758#endif
1759                        }
1760                        else if(ret == 1 && canode->poll == 1) //write
1761                        {
1762#ifdef MIPSEL
1763                                int count = 0;
1764                                struct queue* qe = getqueue(dvbnode->devnr);
1765                                if(qe != NULL)
1766                                {
1767                                        while(qe != NULL && count < 10)
1768                                        {
1769                                                //debug(620, "write (queue), slot %d, ret %d", dvbnode->devnr, ret);
1770                                               
1771                                                int writeret = cawrite(dvbnode, dvbnode->fd, qe->data, qe->len, qe->flag, -1);
1772                                                if(writeret >= 0 && writeret == qe->len)
1773                                                {
1774                                                        delqueue(qe, 0);
1775                                                        qe = getqueue(dvbnode->devnr);
1776                                                }
1777                                                else
1778                                                        count++;
1779                                        }
1780                                }
1781                                else
1782                                {
1783                                        //debug(620, "write (poll), slot %d, ret %d", dvbnode->devnr, ret);
1784                                        casend(dvbnode, NULL, 0);
1785                                        if(canode->fastrun > 0) canode->fastrun--;
1786                                }
1787#else                   
1788                                struct queue* qe = getqueue(dvbnode->devnr);
1789                                if(qe != NULL)
1790                                {
1791                                        //debug(620, "write (queue), slot %d, ret %d", dvbnode->devnr, ret);
1792                                       
1793                                        int writeret = cawrite(dvbnode, dvbnode->fd, qe->data, qe->len, qe->flag, -1);
1794                                        if(writeret >= 0 && writeret == qe->len)
1795                                        {
1796                                                delqueue(qe, 0);
1797                                        }
1798                                }
1799                                else
1800                                {
1801                                        //debug(620, "write (poll), slot %d, ret %d", dvbnode->devnr, ret);
1802                                        casend(dvbnode, NULL, 0);
1803                                        if(canode->fastrun > 0) canode->fastrun--;
1804                                }
1805#endif
1806                        }
1807                        else if(ret == 1 && canode->poll == 0)
1808                        {
1809                                debug(620, "write but poll=0, slot %d, ret %d", dvbnode->devnr, ret);
1810                                if(canode->fastrun > 0) canode->fastrun--;
1811                        }
1812                        else if(ret == 2) //change
1813                        {
1814                                debug(620, "change, slot %d, ret %d", dvbnode->devnr, ret);
1815                                info.num = dvbnode->devnr;
1816
1817                                if(cagetslotinfo(dvbnode, &info) == 1 || !(info.flags & CA_CI_MODULE_READY))
1818                                {
1819                                        debug(620, "flags %d %d %d, slot %d", info.flags, CA_CI_MODULE_READY, info.flags & CA_CI_MODULE_READY, dvbnode->devnr);
1820                                        debug(620, "cam (slot %d) status changed, cam not present", dvbnode->devnr);
1821
1822                                        //reset routing
1823                                        debug(620, "reset routing tuner %d", dvbnode->devnr);
1824                                        switch(dvbnode->devnr)
1825                                        {
1826                                                case 0: setcisource(dvbnode->devnr, "A"); break;
1827                                                case 1: setcisource(dvbnode->devnr, "B"); break;
1828                                                case 2: setcisource(dvbnode->devnr, "C"); break;
1829                                                case 3: setcisource(dvbnode->devnr, "D"); break;
1830                                        }
1831
1832                                        casessionfree(dvbnode);
1833                                        caslotfree(dvbnode);
1834                                        canode->fastrun = 0;
1835
1836                                        sleep(1);
1837                                }
1838                        }
1839                        else if(ret == -2) //timeout
1840                        {
1841                                debug(620, "timeout slot %d, ret %d", dvbnode->devnr, ret);
1842                                if(canode->fastrun > 0) canode->fastrun--;
1843                                break;
1844                        }
1845                        else if(ret < 0) //error
1846                        {
1847                                debug(620, "error slot %d, ret %d", dvbnode->devnr, ret);
1848                                casessionfree(dvbnode);
1849                                caslotfree(dvbnode);
1850                                sleep(1);
1851                        }
1852                }
1853                break;
1854                default:
1855                {
1856                        debug(620, "unknown status");
1857                }
1858                break;
1859        }
1860
1861        //declear as ready, but not complete
1862        if(canode->caids != NULL && canode->status == 1 && canode->fastrun < 1)
1863        {
1864                if(getfreecasession(dvbnode, 1, 1) > -1 && getfreecasession(dvbnode, 2, 1) > -1)
1865                {
1866                        canode->status = 2;
1867                        //m_lock(&status.servicemutex, 2);
1868                        //sendcapmt(status.aktservice, 0, 2);
1869                        //m_unlock(&status.servicemutex, 2);
1870                }
1871        }
1872
1873        free(buf); buf = NULL;
1874}
1875
1876void cathread(struct stimerthread* self, struct dvbdev* dvbnode)
1877{
1878        if(dvbnode == NULL || dvbnode->caslot == NULL) return;
1879        debug(620, "CA thread start (slot %d)", dvbnode->devnr);
1880//#ifdef MIPSEL
1881        dvbnode->caslot->status = 100;
1882//#endif
1883        while(self != NULL && self->aktion != STOP && self->aktion != PAUSE)
1884        {
1885                if(dvbnode->caslot->status != 101)
1886                        cacheck(self, dvbnode);
1887                if(dvbnode->caslot->fastrun == 0)
1888                        sleep(1);
1889                else
1890                        usleep(100000);
1891        }
1892        debug(620, "CA thread end (slot %d)", dvbnode->devnr);
1893}
1894
1895void castart()
1896{
1897        struct dvbdev* dvbnode = dvbdev;
1898
1899        while(dvbnode != NULL)
1900        {
1901                if(dvbnode->type == CIDEV && dvbnode->fd > -1)
1902                {
1903                        if(debug_level == 620)
1904                        {
1905                                struct ca_caps caps;
1906                                ca_slot_info_t info;
1907
1908                                caps.slot_num = dvbnode->devnr;
1909                                if(cagetcaps(dvbnode, &caps) == 0)
1910                                        debug(620, "caps: slotsum:%d, type:%d, descrnr:%d, descrtype:%d", caps.slot_num, caps.slot_type, caps.descr_num, caps.descr_type);
1911
1912                                info.num = dvbnode->devnr;
1913                                if(cagetslotinfo(dvbnode, &info) == 0)
1914                                        debug(620, "info: slot:%d, type:%d, flag:%d", info.num, info.type, info.flags);
1915                        }
1916                        addtimer(&cathread, START, 1000, -1, (void*)dvbnode, NULL, NULL);
1917                }
1918                dvbnode = dvbnode->next;
1919        }
1920}
1921
1922int sendcapmttocam(struct dvbdev* dvbnode, struct service* node, unsigned char* buf, int len, int caservicenr, int cmdpos, int clear)
1923{
1924        int i = 0;
1925        char* tmpstr = NULL, *blacklist = NULL;
1926
1927        if(node == NULL && dvbnode == NULL) return 1;
1928
1929        dvbnode->caslot->scrambled = 0;
1930
1931        if(dvbnode->type == CIDEV && dvbnode->fd > -1 && dvbnode->caslot != NULL && dvbnode->caslot->status == 2 && dvbnode->caslot->caids != NULL)
1932        {
1933                //check if crypt can onyl handle single service
1934                tmpstr = ostrcat("camtype_", oitoa(dvbnode->devnr), 0, 1);
1935                if(clear == 0 && getconfigint(tmpstr, NULL) == 0 && getcaservicebyslot(dvbnode->caslot, 1) > -1)
1936                {
1937                        debug(620, "cam is singel and is in use");
1938                        free(tmpstr); tmpstr = NULL;
1939                        return 1;
1940                }
1941                free(tmpstr); tmpstr = NULL;
1942               
1943                int foundcaid = 0;
1944               
1945    //check if channel used this slot
1946                if(node->channel != NULL)
1947                {
1948                        struct channelslot *channelslotnode = channelslot;
1949                        while(channelslotnode != NULL)
1950                        {
1951                                if(channelslotnode->transponderid == node->channel->transponderid && channelslotnode->serviceid == node->channel->serviceid)
1952                                {
1953          if(channelslotnode->slot == dvbnode->devnr)
1954          {
1955                                                debug(620, "channel support cam (channelslot=%d, slot=%d)", channelslotnode->slot, dvbnode->devnr);
1956                                                foundcaid = 1;
1957                                                break;
1958          }
1959          else
1960          {
1961                debug(620, "channel not support cam (channelslot=%d, slot=%d)", channelslotnode->slot, dvbnode->devnr);
1962                                                return 1;
1963                                        }
1964                                }                       
1965                                channelslotnode = channelslotnode->next;                       
1966                        }
1967                }
1968
1969                //check if cam can caid
1970                if(foundcaid == 0)
1971                {
1972                        tmpstr = ostrcat("camblacklist_", oitoa(dvbnode->devnr), 0, 1);
1973                        blacklist = getconfig(tmpstr, NULL);
1974                        free(tmpstr); tmpstr = NULL;
1975                        if(node->channel != NULL)
1976                        {
1977                                struct cadesc *nodecadesc = node->channel->cadesc;
1978                                while(nodecadesc != NULL)
1979                                {
1980                                        debug(620, "cam-ciads=%s", dvbnode->caslot->caids);
1981                                        debug(620, "videopid=%d, audiopid=%d, ac3pid=%d, capid=%d, caid=%d", node->channel->videopid, node->channel->audiopid, node->channel->ac3audiopid, nodecadesc->pid, nodecadesc->systemid);
1982                                        tmpstr = oitoa(nodecadesc->systemid);
1983                                        if(ostrstr(dvbnode->caslot->caids, tmpstr) != NULL)
1984                                        {
1985                                                //check if caid is in cams blacklist
1986                                                if(blacklist == NULL || ostrstr(blacklist, tmpstr) == NULL)
1987                                                {
1988                                                        foundcaid = 1;
1989                                                        break;
1990                                                }
1991                                                else
1992                                                        debug(620, "caid is in blacklist (%s -> %s)", tmpstr, blacklist);
1993                                        }
1994                                        free(tmpstr); tmpstr = NULL;
1995                        nodecadesc = nodecadesc->next;
1996                                }
1997                        }
1998                        free(tmpstr); tmpstr = NULL;
1999                }
2000
2001                if(foundcaid == 0)
2002                {
2003                        debug(620, "cam not supports caid");
2004                        return 1;
2005                }
2006
2007                //check if we can change input sources
2008                for(i = 0; i < MAXCASERVICE; i++)
2009                {
2010                        if(caservice[i].caslot != NULL && caservice[i].service != NULL && caservice[i].service->fedev != NULL && node->fedev != NULL)
2011                        {
2012                                if(caservice[i].caslot == dvbnode->caslot && caservice[i].service->fedev->devnr != node->fedev->devnr && (caservice[i].service->type == RECORDDIRECT || caservice[i].service->type == RECORDTIMER))
2013                                {
2014                                        debug(620, "can't change input sources");
2015                                        return 1;
2016                                }
2017                        }
2018                }
2019
2020                //got free camanager
2021                if(caservice[caservicenr].camanager == -1)
2022                {
2023                        caservice[caservicenr].camanager = getfreecasession(dvbnode, 2, 1);
2024                        debug(620, "use camanager %d", caservice[caservicenr].camanager);
2025                }
2026
2027                //check if cam can decrypt
2028                if(clear == 0 && caservice[caservicenr].camanager > -1 && getconfigint("checkcamdecrypt", NULL) == 1)
2029                {
2030                        if(buf != NULL && len >= cmdpos)
2031                        {
2032                                status.checkcamdecrypt = 100;
2033                                buf[cmdpos] = 0x03;
2034                                buf[cmdpos - 6] = 0x04; //WA for alphacrypt, only delete all ca-pmt
2035                                sendSPDU(dvbnode, 0x90, NULL, 0, caservice[caservicenr].camanager, buf, len);
2036                                buf[cmdpos] = 0x01;
2037                                buf[cmdpos - 6] = 0x03;
2038                                while(status.checkcamdecrypt > 0)
2039                                {
2040                                        status.checkcamdecrypt--;
2041                                        usleep(30000);
2042                                }
2043                if(status.checkcamdecrypt == -2)
2044                                {
2045                                        dvbnode->caslot->casession[caservice[caservicenr].camanager].inuse = 1;
2046                                        caservice[caservicenr].camanager = -1;
2047                                }
2048                        }
2049                }
2050
2051                //decrypt
2052                if(caservice[caservicenr].camanager > -1)
2053                {
2054                        //change ciX_input and inputX
2055                        if(clear == 0 && node->fedev != NULL)
2056                        {
2057                                char* ci = NULL;
2058                                debug(620, "set ci slot %d to tuner %d", dvbnode->devnr, node->fedev->devnr);
2059                                switch(node->fedev->devnr)
2060                                {
2061                                        case 0:
2062                                                setciinput(dvbnode->devnr, "A");
2063                                                ci = ostrcat("CI", oitoa(dvbnode->devnr), 0, 1);
2064                                                setcisource(node->fedev->devnr, ci);
2065                                                free(ci); ci = NULL;
2066                                                break;
2067                                        case 1:
2068                                                setciinput(dvbnode->devnr, "B");
2069                                                ci = ostrcat("CI", oitoa(dvbnode->devnr), 0, 1);
2070                                                setcisource(node->fedev->devnr, ci);
2071                                                free(ci); ci = NULL;
2072                                                break;
2073                                        case 2:
2074                                                setciinput(dvbnode->devnr, "C");
2075                                                ci = ostrcat("CI", oitoa(dvbnode->devnr), 0, 1);
2076                                                setcisource(node->fedev->devnr, ci);
2077                                                free(ci); ci = NULL;
2078                                                break;
2079                                        case 3:
2080                                                setciinput(dvbnode->devnr, "D");
2081                                                ci = ostrcat("CI", oitoa(dvbnode->devnr), 0, 1);
2082                                                setcisource(node->fedev->devnr, ci);
2083                                                free(ci); ci = NULL;
2084                                                break;
2085                                }
2086                        }
2087                        //send all saved capmt first
2088                        int first = 0;
2089                        for(i = 0; i < MAXCASERVICE; i++)
2090                        {
2091                                if(dvbnode->caslot == caservice[i].caslot && caservice[i].capmt != NULL && caservice[i].capmtlen > 0)
2092                                {
2093                                        if(i == 0)
2094                                                caservice[i].capmt[caservice[i].cmdpos - 6] = 0x01;
2095                                        else
2096                                                caservice[i].capmt[caservice[i].cmdpos - 6] = 0x00;
2097                                        first = 1;
2098                                        sendSPDU(dvbnode, 0x90, NULL, 0, caservice[i].camanager, caservice[i].capmt, caservice[i].capmtlen);
2099                                }
2100                        }
2101                        //send new capmt
2102                        if(first == 1) buf[cmdpos - 6] = 0x02;
2103                        sendSPDU(dvbnode, 0x90, NULL, 0, caservice[caservicenr].camanager, buf, len);
2104                        caservice[caservicenr].caslot = dvbnode->caslot;
2105                        //save new capmt
2106                        char* tmpbuf = malloc(len);
2107                        if(tmpbuf != NULL)
2108                        {
2109                                memcpy(tmpbuf, buf, len);
2110                                free(caservice[caservicenr].capmt);
2111                                caservice[caservicenr].capmt = tmpbuf;
2112                                caservice[caservicenr].capmtlen = len;
2113                                caservice[caservicenr].cmdpos = cmdpos;
2114                        }
2115                        debug(620, "found cam for decrypt (slot=%d)", dvbnode->devnr);
2116                        //if(dvbnode->caslot->private_data != NULL)
2117                        //      resendKey(dvbnode);
2118                        dvbnode->caslot->scrambled = 1;
2119                        return 0;
2120                }
2121                else
2122                        debug(620, "no free camanager found");
2123        }
2124        return 1;
2125}
2126
2127#endif
Note: See TracBrowser for help on using the repository browser.