source: titan/titan/ca.h @ 38396

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

[titan] test... save pin

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