source: titan/titan/ca.h @ 41425

Last change on this file since 41425 was 41425, checked in by gost, 5 years ago

[titan] hd51.. fix ca modul I hope

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