source: titan/titan/ca.h @ 38256

Last change on this file since 38256 was 38256, checked in by gost, 7 years ago

schubs

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