source: titan/titan/ca.h @ 39435

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

[titan] arm.. dm900 add some function

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