source: titan/titan/ca.h @ 40686

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

fix

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