source: titan/titan/ca.h @ 44528

Last change on this file since 44528 was 44312, checked in by gost, 4 years ago

fix

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