source: titan/titan/cam.h @ 37438

Last change on this file since 37438 was 23206, checked in by nit, 11 years ago

[titan] revert

File size: 16.7 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                while(dvbnode != NULL)
505                {
506                        if(dvbnode->type == CIDEV && dvbnode->fd > -1 && dvbnode->caslot != NULL && dvbnode->caslot->status == 2 && dvbnode->caslot->caids != NULL)
507                        {
508                                if(caservice[caservicenr].caslot == NULL)
509                                {
510                                        lenbytes = 0;
511                                        len = createcapmt(dvbnode, node, buf, &lenbytes, 0);
512                                        if(len > -1)
513                                        {
514                                                if(sendcapmttocam(dvbnode, node, buf, len, caservicenr, lenbytes + 9, clear) == 0) break;
515                                        }
516                                }
517                        }
518                        dvbnode = dvbnode->next;
519                }
520
521                if(caservice[caservicenr].camsockfd < 0)
522                {
523                        lenbytes = 0;
524                        len = createcapmt(NULL, node, buf, &lenbytes, 1);
525                        if(len > -1)
526                                sendcapmttosock(node, buf, len, caservicenr);
527                }
528        }
529
530        if(clear > 0)
531        {
532                while(dvbnode != NULL)
533                {
534                        if(dvbnode->type == CIDEV && dvbnode->fd > -1 && dvbnode->caslot != NULL && dvbnode->caslot->status == 2 && dvbnode->caslot->caids != NULL)
535                        {
536                                if(caservice[clear - 1].caslot == dvbnode->caslot)
537                                {
538                                        lenbytes = 0;
539                                        len = createcapmt(dvbnode, node, buf, &lenbytes, 2);
540                                        if(len > -1)
541                                                sendcapmttocam(dvbnode, node, buf, len, caservicenr, lenbytes + 9, clear);
542                                        break;
543                                }
544                        }
545                        dvbnode = dvbnode->next;
546                }
547        }
548
549        free(buf);
550}
551
552void checkcam()
553{
554        int i = 0;
555
556        if(status.pmtmode == 1) return;
557 
558        //struct can change from another thread
559        m_lock(&status.servicemutex, 2);
560        for(i = 0; i < MAXCASERVICE; i++)
561        {
562                if(caservice[i].service != NULL)
563                {
564                        sockcheck(&caservice[i].camsockfd);
565                        if(caservice[i].camsockfd < 0 || caservice[i].caslot == NULL)
566                                sendcapmt(caservice[i].service, 0, 1);
567                }
568        }
569        m_unlock(&status.servicemutex, 2);
570}
571
572struct pmt* addpmt(struct channel* chnode, int programnumber, int versionnumber, int currentnextindicator)
573{
574        struct pmt *newnode = NULL;
575
576        if(chnode == NULL)
577        {
578                err("NULL detect");
579                return NULL;
580        }
581
582        newnode = (struct pmt*)malloc(sizeof(struct pmt));     
583        if(newnode == NULL)
584        {
585                err("no memory");
586                return NULL;
587        }
588
589        memset(newnode, 0, sizeof(struct pmt));
590
591        newnode->programnumber = programnumber;
592        newnode->versionnumber = versionnumber;
593        newnode->currentnextindicator = currentnextindicator;
594
595        chnode->pmt = newnode;
596
597        return newnode;
598}
599
600struct cadesc* addcadesc(struct channel* chnode, int pid, unsigned char* buf, struct cadesc* last)
601{
602        struct cadesc *newnode = NULL, *prev = NULL, *node = NULL;
603
604        if(chnode == NULL || buf == NULL)
605        {
606                err("NULL detect");
607                return NULL;
608        }
609
610        node = chnode->cadesc;
611
612        newnode = (struct cadesc*)malloc(sizeof(struct cadesc));       
613        if(newnode == NULL)
614        {
615                err("no memory");
616                return NULL;
617        }
618
619        memset(newnode, 0, sizeof(struct cadesc));
620
621        newnode->pid = pid;
622        newnode->len = buf[1];
623        newnode->systemid = (buf[2] << 8) | buf[3];
624        newnode->reserved = buf[4] >> 5;
625        newnode->capid = ((buf[4] & 0x1F) << 8) | buf[5];
626
627        if(newnode->len > 4)
628        {
629                newnode->privat = malloc(newnode->len - 4);
630                if(newnode->privat == NULL)
631                {
632                        err("no mem");
633                }
634                else
635                        memcpy(newnode->privat, &buf[6], newnode->len - 4);
636        }
637
638        if(last == NULL)
639        {
640                while(node != NULL)
641                {
642                        prev = node;
643                        node = node->next;
644                }
645        }
646        else
647        {
648                prev = last;
649                node = last->next;
650        }
651
652        if(prev == NULL)
653                chnode->cadesc = newnode;
654        else
655                prev->next = newnode;
656
657        newnode->next = node;
658
659        return newnode;
660}
661
662struct esinfo* addesinfo(struct channel* chnode, int streamtype, int pid, struct esinfo* last)
663{
664        struct esinfo *newnode = NULL, *prev = NULL, *node = NULL;
665
666        if(chnode == NULL)
667        {
668                err("NULL detect");
669                return NULL;
670        }
671
672        node = chnode->esinfo;
673
674        newnode = (struct esinfo*)malloc(sizeof(struct esinfo));       
675        if(newnode == NULL)
676        {
677                err("no memory");
678                return NULL;
679        }
680
681        memset(newnode, 0, sizeof(struct esinfo));
682
683        newnode->streamtype = streamtype;
684        newnode->pid = pid;
685
686        if(last == NULL)
687        {
688                while(node != NULL)
689                {
690                        prev = node;
691                        node = node->next;
692                }
693        }
694        else
695        {
696                prev = last;
697                node = last->next;
698        }
699
700        if(prev == NULL)
701                chnode->esinfo = newnode;
702        else
703                prev->next = newnode;
704
705        newnode->next = node;
706
707        return newnode;
708}
709
710void freepmt(struct channel* chnode)
711{
712        if(chnode == NULL || chnode->pmt == NULL) return;
713
714        free(chnode->pmt);
715        chnode->pmt = NULL;
716}
717
718void freecadesc(struct channel* chnode)
719{
720        struct cadesc *node = NULL, *prev = NULL;
721
722        if(chnode == NULL) return;
723
724        node = chnode->cadesc;
725        prev = chnode->cadesc;
726
727        while(node != NULL)
728        {
729                prev = node;
730                node = node->next;
731                chnode->cadesc = node;
732
733                free(prev->privat);
734                prev->privat = NULL;
735
736                free(prev);
737                prev = NULL;
738
739        }
740}
741
742void freeesinfo(struct channel* chnode)
743{
744        struct esinfo *node = NULL, *prev = NULL;
745
746        if(chnode == NULL) return;
747
748        node = chnode->esinfo;
749        prev = chnode->esinfo;
750
751        while(node != NULL)
752        {
753                prev = node;
754                node = node->next;
755                chnode->esinfo = node;
756
757                free(prev);
758                prev = NULL;
759
760        }
761}
762
763#endif
Note: See TracBrowser for help on using the repository browser.