source: titan/titan/cam.h @ 41327

Last change on this file since 41327 was 41327, checked in by gost, 6 years ago

[titan] hd51.. fix dmxsetsource

File size: 16.9 KB
Line 
1#ifndef CAM_H
2#define CAM_H
3
4void debugcaservice()
5{
6        int i = 0;
7
8        for(i = 0; i < MAXCASERVICE; i++)
9        {
10                if(caservice[i].service != NULL)
11                {
12                        printf("number: %d\n", i);
13                        printf("service: %p\n", caservice[i].service);
14                        if(caservice[i].channel != NULL)
15                                printf("channel: %s\n", caservice[i].channel->name);
16                        printf("camsockfd: %d\n", caservice[i].camsockfd);
17                        printf("caslot: %p\n", caservice[i].caslot);
18                        printf("count: %d\n", caservice[i].count);
19                }
20        }
21}
22
23int getcaservicebyslot(struct caslot* caslot, int flag)
24{
25        int i = 0;
26
27        for(i = 0; i < MAXCASERVICE; i++)
28        {
29                if(caslot == caservice[i].caslot)
30                {
31                        if(flag == 1)
32                        {
33                                if(caservice[i].service != NULL && (caservice[i].service->type == RECORDDIRECT || caservice[i].service->type == RECORDTIMER))
34                                        return i;
35                        }
36                        else
37                                return i;
38                }
39        }
40        return -1;
41}
42
43//flag 0 = from zap
44//flag 1 = from watchthread
45//flag 2 = from cathread / caservicedel
46//flag 3 = from recordthread
47int caserviceadd(struct service* snode, int flag)
48{
49        int i = 0, first = -1;
50
51        if(snode == NULL) return -1;
52
53        for(i = 0; i < MAXCASERVICE; i++)
54        {
55                if(caservice[i].service != NULL && caservice[i].channel == snode->channel)
56                {
57                        if((flag == 0 || flag == 3))
58                        {
59                                caservice[i].service = snode;
60                                caservice[i].count++;
61                                return -1;
62                        }
63                        return i;
64                }
65                if(caservice[i].service == NULL && first == -1)
66                        first = i;
67        }
68
69        if(first != -1)
70        {
71                caservice[first].service = snode;
72                caservice[first].channel = snode->channel;
73                caservice[first].count = 1;
74                caservice[first].camsockfd = -1;
75                if(caservice[first].caslot != NULL && caservice[first].camanager > -1 && caservice[first].caslot->casession[caservice[first].camanager].inuse > 0) caservice[first].caslot->casession[caservice[first].camanager].inuse = 1;
76                caservice[first].caslot = NULL;
77                caservice[first].camanager = -1;
78                free(caservice[first].capmt); caservice[first].capmt = NULL;
79                caservice[first].capmtlen = 0;
80                caservice[first].cmdpos = 0;
81                return first;
82        }
83
84        return -1;
85}
86
87void caservicedel(struct service* snode, struct caslot* caslot)
88{
89        int i = 0;
90
91        for(i = 0; i < MAXCASERVICE; i++)
92        {
93                if(snode != NULL && caservice[i].service != NULL && caservice[i].channel == snode->channel)
94                {
95                        caservice[i].count--;
96                        if(caservice[i].count < 1)
97                        {
98                                if(caservice[i].camsockfd > -1)
99                                        sockclose(&caservice[i].camsockfd);
100                                if(caservice[i].caslot != NULL)
101                                {
102                                        //sendcapmt(caservice[i].service, i + 1, 2);
103                                        if(caservice[i].caslot != NULL && caservice[i].camanager > -1 && caservice[i].caslot->casession[caservice[i].camanager].inuse > 0) caservice[i].caslot->casession[caservice[i].camanager].inuse = 1;
104                                        caservice[i].caslot = NULL;
105                                        caservice[i].camanager = -1;
106                                }
107                                free(caservice[i].capmt); caservice[i].capmt = NULL;
108                                caservice[i].count = 0;
109                                caservice[i].capmtlen = 0;
110                                caservice[i].cmdpos = 0;
111                                caservice[i].service = NULL;
112                                caservice[i].channel = NULL;
113                        }
114                        else
115                                caservice[i].service = getservicebyservice(snode, 1);
116                }
117                //remove cam from slot
118                if(caservice[i].service != NULL && caservice[i].caslot == caslot)
119                {
120                        if(caservice[i].caslot != NULL && caservice[i].camanager > -1 && caservice[i].caslot->casession[caservice[i].camanager].inuse > 0) caservice[i].caslot->casession[caservice[i].camanager].inuse = 1;
121                        caservice[i].caslot = NULL;
122                        caservice[i].camanager = -1;
123                }
124        }
125}
126
127void freecaservice()
128{
129        int i = 0;
130
131        for(i = 0; i < MAXCASERVICE; i++)
132        {
133                free(caservice[i].capmt);
134                caservice[i].capmt = NULL;
135
136                caservice[i].caslot = NULL;
137                caservice[i].camanager = -1;
138                caservice[i].capmtlen = 0;
139                caservice[i].cmdpos = 0;
140                caservice[i].service = NULL;
141                caservice[i].channel = NULL;
142
143                if(caservice[i].camsockfd > -1)
144                        sockclose(&caservice[i].camsockfd);
145        }
146}
147
148void dvbwritepmt(struct service* node, unsigned char* pmtbuf)
149{
150        int length;
151        FILE *fd;
152        char* filename = NULL, *tmpnr = NULL;
153
154        if(node == NULL || pmtbuf == NULL)
155        {
156                debug(1000, "NULL detect");
157                return;
158        }
159
160        if(node->fedev == NULL || (node->fedev != NULL && node->fedev->devnr == 0))
161        {
162                filename = ostrcat(filename, "/tmp/pmt.tmp", 0, 0);
163        }
164        else
165        {
166                tmpnr = oitoa(node->fedev->devnr);
167                filename = ostrcat(filename, "/tmp/pmt", 1, 0);
168                filename = ostrcat(filename, tmpnr, 1, 1);
169                filename = ostrcat(filename, ".tmp", 1, 0);
170        }
171
172        unlink(filename);
173        length =((pmtbuf[1] & 0xf) << 8) + ((pmtbuf[2] + 3) & 0xff);
174        if(filename != NULL)
175        {
176                fd=fopen(filename, "wbt");
177                if(fd != NULL)
178                {
179                        if((int) fwrite(pmtbuf, sizeof(unsigned char), length, fd) != length)
180                                unlink(filename);
181                        else
182                                debug(200, "write %s", filename);
183                        fclose(fd);
184                }
185        }
186        free(filename);
187}
188
189void sendcapmttosock(struct service* node, unsigned char* buf, int pos, int caservicenr)
190{
191        int ret = 0, i = 0;
192
193        if(caservice[caservicenr].camsockfd < 0 || socksend(&caservice[caservicenr].camsockfd, buf, pos, -1) != 0)
194        {
195                ret = sockopen(&caservice[caservicenr].camsockfd, "/tmp/camd.socket", 0, -1);
196                if(ret == 0)
197                        ret = socksend(&caservice[caservicenr].camsockfd, buf, pos, -1);
198        }
199
200        if(ret == 0 && debug_level == 620)
201        {
202                printf("CA-PMT: ");
203                for(i = 0; i < pos; i++)
204                        printf("%02x ", buf[i] & 0xff);
205                printf("\n");
206        }
207}
208
209//flag 0: cam capmt
210//flag 1: emu capmt
211//flag 2: clear capmt
212int createcapmt(struct dvbdev* dvbnode, struct service* node, unsigned char* buf, int* lenbytes, int flag)
213{
214        if(buf == NULL || node == NULL || node->channel == NULL) return -1;
215        if(node->fedev == NULL || node->channel->pmt == NULL) return -1;
216        if(node->channel->cadesc == NULL || node->channel->esinfo == NULL) return -1;
217
218        int pos = 10, i = 0;
219        struct cadesc* cadescnode = node->channel->cadesc;
220        struct esinfo* esinfonode = node->channel->esinfo;
221
222        memset(buf, 0, MINMALLOC);
223
224        buf[0] = 0x9F; // ca_pmt_tag
225        buf[1] = 0x80; // ca_pmt_tag
226        buf[2] = 0x32; // ca_pmt_tag
227
228        buf[pos++] = 0x03; //ca_pmt_lst_management: 0=more, 1=first, 2=last, 3=only, 4=add, 5=update
229        buf[pos++] = node->channel->pmt->programnumber >> 8;
230        buf[pos++] = node->channel->pmt->programnumber & 0xff;
231
232        buf[pos++] = (node->channel->pmt->versionnumber << 1) | node->channel->pmt->currentnextindicator;
233
234        buf[pos++] = 0x00; //len from here (programinfo len)
235        buf[pos++] = 0x00; //len from here (programinfo len)
236        buf[pos++] = 0x01; //ca_pmt_cmd_id: ok_descrambling=1
237
238        if(flag == 1)
239        {
240                buf[pos++] = 0x81; //id (fix)
241                buf[pos++] = 0x08; //len
242                buf[pos++] = 0x00; //namespace >> 24
243                buf[pos++] = 0x00; //(namespace >> 16) & 0xff
244                buf[pos++] = 0x00; //(namespace >> 8) & 0xff
245                buf[pos++] = 0x00; //namespace & 0xff
246                buf[pos++] = 0x00; //transportstreamid >> 8
247                buf[pos++] = 0x00; //transportstreamid & 0xff
248                buf[pos++] = 0x00; //original network id >> 8
249                buf[pos++] = 0x00; //original network id & 0xff
250
251                buf[pos++] = 0x82; //id (fix)
252                buf[pos++] = 0x02; //len
253
254/*
255                while(tmpnode != NULL)
256                {
257                        if(tmpnode->fedev != NULL)
258                        {
259                                //(demuxmask |= (1 << dmxdev->devnr)
260                                buf[pos] |= (1 << tmpnode->fedev->devnr);
261                        }
262                        tmpnode = tmpnode->next;
263                }
264                pos++;
265*/
266                buf[pos++] |= (1 << node->fedev->devnr); //cadev_nr
267                buf[pos++] = node->fedev->devnr; //demux_dev_nr
268
269                buf[pos++] = 0x84; //id (fix)
270                buf[pos++] = 0x02; //len
271                buf[pos++] = node->channel->pmtpid >> 8; //pmtpid >> 8
272                buf[pos++] = node->channel->pmtpid & 0xff; //pmtpid & 0xff
273        }
274
275        while(cadescnode != NULL && flag < 2)
276        {
277                //remove caids, cam can't
278                if(flag == 0 && status.casendallcaids == 0)
279                {
280                        char* tmpnr = NULL;
281
282                        if(dvbnode != NULL)
283                        {
284                                tmpnr = oitoa(cadescnode->systemid);
285                                if(ostrstr(dvbnode->caslot->caids, tmpnr) == NULL)
286                                {
287                                        free(tmpnr); tmpnr = NULL;
288                                        cadescnode = cadescnode->next;
289                                        continue;
290                                }
291                                free(tmpnr); tmpnr = NULL;
292                        }
293                }
294
295                if(cadescnode->len > 0 && cadescnode->pid == 0)
296                {
297                        int cadesclen = 0;
298
299                        buf[pos++] = 0x09; //ca desc tag
300                        if(flag == 0 && status.caskipprivat == 1) //workaround for to long capmt
301                        {
302                                buf[pos++] = 4;
303                                cadesclen = cadesclen;
304                        }
305                        else
306                        {
307                                cadesclen = cadescnode->len;
308                                buf[pos++] = cadesclen;
309                        }
310                        buf[pos++] = cadescnode->systemid >> 8;
311                        buf[pos++] = cadescnode->systemid & 0xff;
312                        buf[pos++] = (cadescnode->reserved << 5) | (cadescnode->capid >> 8);
313                        buf[pos++] = cadescnode->capid & 0xff;
314
315                        if(cadesclen > 4)
316                        {
317                                memcpy(&buf[pos], cadescnode->privat, cadesclen - 4);
318                                pos += cadesclen - 4;
319                        }
320                }
321                cadescnode = cadescnode->next;
322        }
323
324        int tmppos = pos;
325
326        while(esinfonode != NULL)
327        {
328                buf[pos++] = esinfonode->streamtype;
329                buf[pos++] = esinfonode->pid >> 8;
330                buf[pos++] = esinfonode->pid & 0xff;
331
332                int eslenpos = pos;
333                int eslen = 0;
334                pos += 2;
335
336                cadescnode = node->channel->cadesc;
337                while(cadescnode != NULL && flag < 2)
338                {
339                        if(cadescnode->len > 0 && cadescnode->pid == esinfonode->pid)
340                        {
341                                //remove caids, cam can't
342                                if(flag == 0 && status.casendallcaids == 0)
343                                {
344                                        char* tmpnr = NULL;
345
346                                        if(dvbnode != NULL)
347                                        {
348                                                tmpnr = oitoa(cadescnode->systemid);
349                                                if(ostrstr(dvbnode->caslot->caids, tmpnr) == NULL)
350                                                {
351                                                        free(tmpnr); tmpnr = NULL;
352                                                        cadescnode = cadescnode->next;
353                                                        continue;
354                                                }
355                                                free(tmpnr); tmpnr = NULL;
356                                        }
357                                }
358
359                                if(eslen == 0)
360                                {
361                                        eslen = 1;
362                                        buf[pos++] = 0x01; //ca_pmt_cmd_id: ok_descrambling=1
363                                }
364                                eslen = eslen + cadescnode->len + 2;
365                                buf[pos++] = 0x09; //ca desc tag
366                                buf[pos++] = cadescnode->len;
367                                buf[pos++] = cadescnode->systemid >> 8;
368                                buf[pos++] = cadescnode->systemid & 0xff;
369                                buf[pos++] = (cadescnode->reserved << 5) | (cadescnode->capid >> 8);
370                                buf[pos++] = cadescnode->capid & 0xff;
371                                if(cadescnode->len > 4)
372                                {
373                                        memcpy(&buf[pos], cadescnode->privat, cadescnode->len - 4);
374                                        pos += cadescnode->len - 4;
375                                }
376                        }
377                        cadescnode = cadescnode->next;
378                }
379
380                buf[eslenpos + 1] = eslen & 0xff;
381                buf[eslenpos] = (eslen >> 8) & 0x0f;
382
383                esinfonode = esinfonode->next;
384        }
385
386        *lenbytes = writelengthfield(&buf[3], pos - 10);
387        for(i = 0; i < pos + 10; i++)
388        {
389                buf[(*lenbytes) + 3 + i] = buf[10 + i];
390        }
391        pos = pos - 10 + (*lenbytes) + 3;
392        tmppos = tmppos - 10 + (*lenbytes) + 3;
393
394        //programinfo len
395        buf[8 + (*lenbytes)] = (tmppos - 9 - (*lenbytes)) & 0xff;
396        buf[7 + (*lenbytes)] = ((tmppos - 9 - (*lenbytes)) >> 8) & 0x0f;
397
398        return pos;
399}
400
401//flag 0 = from zap
402//flag 1 = from watchthread
403//flag 2 = from cathread / caservicedel
404//flag 3 = from recordthread
405void sendcapmt(struct service* node, int clear, int flag)
406{
407        int len = 0, i = 0, caservicenr = 0, lenbytes = 0;
408        unsigned char* buf = NULL;
409        struct dvbdev* dvbnode = dvbdev;
410
411        //check if service should decrypt
412        if(node == NULL)
413        {
414                debug(620, "service empty");
415                return;
416        }
417        if(node->channel == NULL)
418        {
419                debug(620, "channel empty");
420                return;
421        }
422        if(node->fedev == NULL)
423        {
424                debug(620, "no frontend");
425                return;
426        }
427       
428        if(node->channel->crypt == 0)
429        {
430                debug(620, "channel not crypt");
431
432                //check if we can change input sources
433                int doswitch = 1;
434                for(i = 0; i < MAXCASERVICE; i++)
435                {
436                        if(caservice[i].caslot != NULL && caservice[i].service != NULL && caservice[i].service->fedev != NULL)
437                        {
438                                if(caservice[i].service->fedev->devnr == node->fedev->devnr && (caservice[i].service->type == RECORDDIRECT || caservice[i].service->type == RECORDTIMER))
439                                {
440                                        debug(620, "can't change input sources");
441                                        doswitch = 0;
442                                }
443                        }
444                }
445
446                if(doswitch == 1)
447                {
448                        debug(200, "reset routing tuner %d", node->fedev->devnr);
449                        switch(node->fedev->devnr)
450                        {
451                                case 0: setcisource(node->fedev->devnr, "A"); break;
452                                case 1: setcisource(node->fedev->devnr, "B"); break;
453                                case 2: setcisource(node->fedev->devnr, "C"); break;
454                                case 3: setcisource(node->fedev->devnr, "D"); break;
455                        }
456                }
457               
458                return;
459        }
460       
461        if(node->channel->pmt == NULL)
462        {
463                debug(620, "pmt empty");
464                return;
465        }
466        if(node->channel->cadesc == NULL)
467        {
468                debug(620, "cadesc empty");
469                return;
470        }
471        if(node->channel->esinfo == NULL)
472        {
473                debug(620, "esinfo empty");
474                return;
475        }
476        if(node->fedev->type == FRONTENDDEVDUMMY)
477        {
478                debug(620, "dummy frontend not crypt");
479                return;
480        }
481        if(flag != 3 && node->type != CHANNEL && node->type != RECORDDIRECT && node->type != RECORDTIMER && node->type != RECORDTIMESHIFT && node->type != RECORDSTREAM)
482        {
483                debug(620, "service type should not decrypt");
484                return;
485        }
486
487        buf = malloc(MINMALLOC);
488        if(buf == NULL)
489        {
490                err("no mem");
491                return;
492        }
493
494        if(clear == 0)
495        {
496                caservicenr = caserviceadd(node, flag);
497                if(caservicenr < 0)
498                {
499                        debug(620, "service is decrypt");
500                        free(buf);
501                        return;
502                }
503
504                int foundcam = 0;
505
506                while(dvbnode != NULL)
507                {
508                        if(dvbnode->type == CIDEV && dvbnode->fd > -1 && dvbnode->caslot != NULL && dvbnode->caslot->status == 2 && dvbnode->caslot->caids != NULL)
509                        {
510                                if(caservice[caservicenr].caslot == NULL)
511                                {
512                                        lenbytes = 0;
513                                        len = createcapmt(dvbnode, node, buf, &lenbytes, 0);
514                                        if(len > -1)
515                                        {
516                                                if(sendcapmttocam(dvbnode, node, buf, len, caservicenr, lenbytes + 9, clear) == 0)
517                                                {
518                                                        foundcam = 1;
519                                                        break;
520                                                }
521                                        }
522                                }
523                        }
524                        dvbnode = dvbnode->next;
525                }
526
527                if(caservice[caservicenr].camsockfd < 0 && foundcam == 0)
528                {
529                        lenbytes = 0;
530                        len = createcapmt(NULL, node, buf, &lenbytes, 1);
531                        if(len > -1)
532                                sendcapmttosock(node, buf, len, caservicenr);
533                }
534        }
535
536        if(clear > 0)
537        {
538                while(dvbnode != NULL)
539                {
540                        if(dvbnode->type == CIDEV && dvbnode->fd > -1 && dvbnode->caslot != NULL && dvbnode->caslot->status == 2 && dvbnode->caslot->caids != NULL)
541                        {
542                                if(caservice[clear - 1].caslot == dvbnode->caslot)
543                                {
544                                        lenbytes = 0;
545                                        len = createcapmt(dvbnode, node, buf, &lenbytes, 2);
546                                        if(len > -1)
547                                                sendcapmttocam(dvbnode, node, buf, len, caservicenr, lenbytes + 9, clear);
548                                        break;
549                                }
550                        }
551                        dvbnode = dvbnode->next;
552                }
553        }
554
555        free(buf);
556}
557
558void checkcam()
559{
560        int i = 0;
561        if(status.pmtmode == 1) return;
562
563        //struct can change from another thread
564        m_lock(&status.servicemutex, 2);
565        for(i = 0; i < MAXCASERVICE; i++)
566        {
567                if(caservice[i].service != NULL)
568                {
569                        sockcheck(&caservice[i].camsockfd);
570                        if((caservice[i].camsockfd < 0 && caservice[i].camanager == -1) || caservice[i].caslot == NULL)
571                                sendcapmt(caservice[i].service, 0, 1);
572                }
573        }
574        m_unlock(&status.servicemutex, 2);
575}
576
577struct pmt* addpmt(struct channel* chnode, int programnumber, int versionnumber, int currentnextindicator)
578{
579        struct pmt *newnode = NULL;
580
581        if(chnode == NULL)
582        {
583                err("NULL detect");
584                return NULL;
585        }
586
587        newnode = (struct pmt*)malloc(sizeof(struct pmt));     
588        if(newnode == NULL)
589        {
590                err("no memory");
591                return NULL;
592        }
593
594        memset(newnode, 0, sizeof(struct pmt));
595
596        newnode->programnumber = programnumber;
597        newnode->versionnumber = versionnumber;
598        newnode->currentnextindicator = currentnextindicator;
599
600        chnode->pmt = newnode;
601
602        return newnode;
603}
604
605struct cadesc* addcadesc(struct channel* chnode, int pid, unsigned char* buf, struct cadesc* last)
606{
607        struct cadesc *newnode = NULL, *prev = NULL, *node = NULL;
608
609        if(chnode == NULL || buf == NULL)
610        {
611                err("NULL detect");
612                return NULL;
613        }
614
615        node = chnode->cadesc;
616
617        newnode = (struct cadesc*)malloc(sizeof(struct cadesc));       
618        if(newnode == NULL)
619        {
620                err("no memory");
621                return NULL;
622        }
623
624        memset(newnode, 0, sizeof(struct cadesc));
625
626        newnode->pid = pid;
627        newnode->len = buf[1];
628        newnode->systemid = (buf[2] << 8) | buf[3];
629        newnode->reserved = buf[4] >> 5;
630        newnode->capid = ((buf[4] & 0x1F) << 8) | buf[5];
631
632        if(newnode->len > 4)
633        {
634                newnode->privat = malloc(newnode->len - 4);
635                if(newnode->privat == NULL)
636                {
637                        err("no mem");
638                }
639                else
640                        memcpy(newnode->privat, &buf[6], newnode->len - 4);
641        }
642
643        if(last == NULL)
644        {
645                while(node != NULL)
646                {
647                        prev = node;
648                        node = node->next;
649                }
650        }
651        else
652        {
653                prev = last;
654                node = last->next;
655        }
656
657        if(prev == NULL)
658                chnode->cadesc = newnode;
659        else
660                prev->next = newnode;
661
662        newnode->next = node;
663
664        return newnode;
665}
666
667struct esinfo* addesinfo(struct channel* chnode, int streamtype, int pid, struct esinfo* last)
668{
669        struct esinfo *newnode = NULL, *prev = NULL, *node = NULL;
670
671        if(chnode == NULL)
672        {
673                err("NULL detect");
674                return NULL;
675        }
676
677        node = chnode->esinfo;
678
679        newnode = (struct esinfo*)malloc(sizeof(struct esinfo));       
680        if(newnode == NULL)
681        {
682                err("no memory");
683                return NULL;
684        }
685
686        memset(newnode, 0, sizeof(struct esinfo));
687
688        newnode->streamtype = streamtype;
689        newnode->pid = pid;
690
691        if(last == NULL)
692        {
693                while(node != NULL)
694                {
695                        prev = node;
696                        node = node->next;
697                }
698        }
699        else
700        {
701                prev = last;
702                node = last->next;
703        }
704
705        if(prev == NULL)
706                chnode->esinfo = newnode;
707        else
708                prev->next = newnode;
709
710        newnode->next = node;
711
712        return newnode;
713}
714
715void freepmt(struct channel* chnode)
716{
717        if(chnode == NULL || chnode->pmt == NULL) return;
718
719        free(chnode->pmt);
720        chnode->pmt = NULL;
721}
722
723void freecadesc(struct channel* chnode)
724{
725        struct cadesc *node = NULL, *prev = NULL;
726
727        if(chnode == NULL) return;
728
729        node = chnode->cadesc;
730        prev = chnode->cadesc;
731
732        while(node != NULL)
733        {
734                prev = node;
735                node = node->next;
736                chnode->cadesc = node;
737
738                free(prev->privat);
739                prev->privat = NULL;
740
741                free(prev);
742                prev = NULL;
743
744        }
745}
746
747void freeesinfo(struct channel* chnode)
748{
749        struct esinfo *node = NULL, *prev = NULL;
750
751        if(chnode == NULL) return;
752
753        node = chnode->esinfo;
754        prev = chnode->esinfo;
755
756        while(node != NULL)
757        {
758                prev = node;
759                node = node->next;
760                chnode->esinfo = node;
761
762                free(prev);
763                prev = NULL;
764
765        }
766}
767
768#endif
Note: See TracBrowser for help on using the repository browser.