source: titan/titan/cam.h @ 15272

Last change on this file since 15272 was 15088, checked in by nit, 10 years ago

[titan] fix debug

File size: 13.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                return first;
79        }
80
81        return -1;
82}
83
84void caservicedel(struct service* snode, struct caslot* caslot)
85{
86        int i = 0;
87
88        for(i = 0; i < MAXCASERVICE; i++)
89        {
90                if(snode != NULL && caservice[i].service != NULL && caservice[i].channel == snode->channel)
91                {
92                        caservice[i].count--;
93                        if(caservice[i].count < 1)
94                        {
95                                if(caservice[i].camsockfd > -1)
96                                        sockclose(&caservice[i].camsockfd);
97                                if(caservice[i].caslot != NULL)
98                                {
99                                        sendcapmt(caservice[i].service, 1, 2);
100                                        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;
101                                        caservice[i].caslot = NULL;
102                                        caservice[i].camanager = -1;
103                                }
104                                caservice[i].service = NULL;
105                                caservice[i].channel = NULL;
106                        }
107                        else
108                                caservice[i].service = getservicebyservice(snode, 1);
109                }
110                //remove cam from slot
111                if(caservice[i].service != NULL && caservice[i].caslot == caslot)
112                {
113                        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;
114                        caservice[i].caslot = NULL;
115                        caservice[i].camanager = -1;
116                }
117        }
118}
119
120void dvbwritepmt(struct service* node, unsigned char* pmtbuf)
121{
122        int length;
123        FILE *fd;
124        char* filename = NULL, *tmpnr = NULL;
125
126        if(node == NULL || pmtbuf == NULL)
127        {
128                debug(1000, "NULL detect");
129                return;
130        }
131
132        if(node->fedev == NULL || (node->fedev != NULL && node->fedev->devnr == 0))
133        {
134                filename = ostrcat(filename, "/tmp/pmt.tmp", 0, 0);
135        }
136        else
137        {
138                tmpnr = oitoa(node->fedev->devnr);
139                filename = ostrcat(filename, "/tmp/pmt", 1, 0);
140                filename = ostrcat(filename, tmpnr, 1, 1);
141                filename = ostrcat(filename, ".tmp", 1, 0);
142        }
143
144        unlink(filename);
145        length =((pmtbuf[1] & 0xf) << 8) + ((pmtbuf[2] + 3) & 0xff);
146        if(filename != NULL)
147        {
148                fd=fopen(filename, "wbt");
149                if(fd != NULL)
150                {
151                        if((int) fwrite(pmtbuf, sizeof(unsigned char), length, fd) != length)
152                                unlink(filename);
153                        else
154                                debug(200, "write %s", filename);
155                        fclose(fd);
156                }
157        }
158        free(filename);
159}
160
161
162void sendcapmttosock(struct service* node, unsigned char* buf, int pos, int caservicenr)
163{
164        int ret = 0, i = 0;
165
166        if(caservice[caservicenr].camsockfd < 0 || socksend(&caservice[caservicenr].camsockfd, buf, pos, -1) != 0)
167        {
168                ret = sockopen(&caservice[caservicenr].camsockfd, "/tmp/camd.socket", 0, -1);
169                if(ret == 0)
170                        ret = socksend(&caservice[caservicenr].camsockfd, buf, pos, -1);
171        }
172
173        if(ret == 0 && debug_level == 620)
174        {
175                printf("CA-PMT: ");
176                for(i = 0; i < pos; i++)
177                        printf("%02x ", buf[i] & 0xff);
178                printf("\n");
179        }
180}
181
182void sendcapmtend(struct service* node)
183{
184        unsigned char* buf = NULL;
185
186        if(node == NULL)
187        {
188                debug(620, "service empty");
189                return;
190        }
191        if(node->fedev == 0)
192        {
193                debug(620, "no frontend");
194                return;
195        }
196
197        buf = malloc(8);
198        if(buf == NULL)
199        {
200                err("no mem");
201                return;
202        }
203        memset(buf, 0, 8);
204
205        buf[0] = 0x9F; // ca_pmt_tag
206        buf[1] = 0x80; // ca_pmt_tag
207        buf[2] = 0x3f; // ca_pmt_tag
208        buf[3] = 0x04; // ca_pmt_tag
209        buf[4] = 0x83; // ca_pmt_tag
210        buf[5] = 0x02; // ca_pmt_tag
211        buf[6] = 0x00; // ca_pmt_tag
212        buf[7] = node->fedev->devnr; //demux_dev_nr
213        //sendcapmttosock(node, buf, 8);
214
215        free(buf);
216}
217
218//flag 0 = from zap
219//flag 1 = from watchthread
220//flag 2 = from cathread / caservicedel
221//flag 3 = from recordthread
222void sendcapmt(struct service* node, int clear, int flag)
223{
224        int pos = 10, i = 0, lenbytes = 0, round = 0, caservicenr = 0;
225        unsigned char* buf = NULL;
226
227        //check if service should decrypt
228        if(node == NULL)
229        {
230                debug(620, "service empty");
231                return;
232        }
233        if(node->channel == NULL)
234        {
235                debug(620, "channel empty");
236                return;
237        }
238        if(node->fedev == NULL)
239        {
240                debug(620, "no frontend");
241                return;
242        }
243       
244        if(node->channel->crypt == 0)
245        {
246                debug(620, "channel not crypt");
247
248                debug(200, "set ci slot %d to tuner %d", node->fedev->devnr, node->fedev->devnr);
249                switch(node->fedev->devnr)
250                {
251                        case 0: setcisource(node->fedev->devnr, "A"); break;
252                        case 1: setcisource(node->fedev->devnr, "B"); break;
253                        case 2: setcisource(node->fedev->devnr, "C"); break;
254                        case 3: setcisource(node->fedev->devnr, "D"); break;
255                }
256               
257                return;
258        }
259       
260        if(node->channel->pmt == NULL)
261        {
262                debug(620, "pmt empty");
263                return;
264        }
265        if(node->channel->cadesc == NULL)
266        {
267                debug(620, "cadesc empty");
268                return;
269        }
270        if(node->channel->esinfo == NULL)
271        {
272                debug(620, "esinfo empty");
273                return;
274        }
275        if(node->fedev->type == FRONTENDDEVDUMMY)
276        {
277                debug(620, "dummy frontend not crypt");
278                return;
279        }
280        if(flag != 3 && node->type != CHANNEL && node->type != RECORDDIRECT && node->type != RECORDTIMER && node->type != RECORDTIMESHIFT && node->type != RECORDSTREAM)
281        {
282                debug(620, "service type should not decrypt");
283                return;
284        }
285
286        buf = malloc(MINMALLOC);
287        if(buf == NULL)
288        {
289                err("no mem");
290                return;
291        }
292
293        if(clear == 0)
294        {
295                caservicenr = caserviceadd(node, flag);
296                if(caservicenr < 0)
297                {
298                        debug(620, "service is decrypt");
299                        free(buf);
300                        return;
301                }
302        }
303
304        struct cadesc* cadescnode = node->channel->cadesc;
305        struct esinfo* esinfonode = node->channel->esinfo;
306
307start:
308        pos = 10, lenbytes = 0, i = 0;
309        cadescnode = node->channel->cadesc;
310        esinfonode = node->channel->esinfo;
311        memset(buf, 0, MINMALLOC);
312
313        buf[0] = 0x9F; // ca_pmt_tag
314        buf[1] = 0x80; // ca_pmt_tag
315        buf[2] = 0x32; // ca_pmt_tag
316
317        buf[pos++] = 3; //ca_pmt_lst_management: fixme 5 for update
318        buf[pos++] = node->channel->pmt->programnumber >> 8;
319        buf[pos++] = node->channel->pmt->programnumber & 0xff;
320
321        buf[pos++] = (node->channel->pmt->versionnumber << 1) | node->channel->pmt->currentnextindicator;
322
323        buf[pos++] = 0x00; //len from here (programinfo len)
324        buf[pos++] = 0x00; //len from here (programinfo len)
325        buf[pos++] = 0x01; //ca_pmt_cmd_id: ok_descrambling=1
326
327        if(round == 1)
328        {
329                buf[pos++] = 0x81; //id (fix)
330                buf[pos++] = 0x08; //len
331                buf[pos++] = 0x00; //namespace >> 24
332                buf[pos++] = 0x00; //(namespace >> 16) & 0xff
333                buf[pos++] = 0x00; //(namespace >> 8) & 0xff
334                buf[pos++] = 0x00; //namespace & 0xff
335                buf[pos++] = 0x00; //transportstreamid >> 8
336                buf[pos++] = 0x00; //transportstreamid & 0xff
337                buf[pos++] = 0x00; //original network id >> 8
338                buf[pos++] = 0x00; //original network id & 0xff
339
340                buf[pos++] = 0x82; //id (fix)
341                buf[pos++] = 0x02; //len
342
343/*
344                while(tmpnode != NULL)
345                {
346                        if(tmpnode->fedev != NULL)
347                        {
348                                //(demuxmask |= (1 << dmxdev->devnr)
349                                buf[pos] |= (1 << tmpnode->fedev->devnr);
350                        }
351                        tmpnode = tmpnode->next;
352                }
353                pos++;
354*/
355                buf[pos++] |= (1 << node->fedev->devnr); //cadev_nr
356                buf[pos++] = node->fedev->devnr; //demux_dev_nr
357
358                buf[pos++] = 0x84; //id (fix)
359                buf[pos++] = 0x02; //len
360                buf[pos++] = node->channel->pmtpid >> 8; //pmtpid >> 8
361                buf[pos++] = node->channel->pmtpid & 0xff; //pmtpid & 0xff
362        }
363
364        while(cadescnode != NULL && clear == 0)
365        {
366                if(cadescnode->len > 0)
367                {
368                        buf[pos++] = 0x09; //ca desc tag
369                        buf[pos++] = cadescnode->len;
370                        buf[pos++] = cadescnode->systemid >> 8;
371                        buf[pos++] = cadescnode->systemid & 0xff;
372                        buf[pos++] = (cadescnode->reserved << 5) | (cadescnode->pid >> 8);
373                        buf[pos++] = cadescnode->pid & 0xff;
374                        if(cadescnode->len > 4)
375                        {
376                                memcpy(&buf[pos], cadescnode->privat, cadescnode->len - 4);
377                                pos += cadescnode->len - 4;
378                        }
379
380                }
381                cadescnode = cadescnode->next;
382        }
383
384        int tmppos = pos;
385
386        while(esinfonode != NULL)
387        {
388                buf[pos++] = esinfonode->streamtype;
389                buf[pos++] = esinfonode->pid >> 8;
390                buf[pos++] = esinfonode->pid & 0xff;
391                pos += 2;
392                esinfonode = esinfonode->next;
393        }
394
395        lenbytes = writelengthfield(&buf[3], pos - 10);
396        for(i = 0; i < pos + 10; i++)
397        {
398                buf[lenbytes + 3 + i] = buf[10 + i];
399        }
400        pos = pos - 10 + lenbytes + 3;
401        tmppos = tmppos - 10 + lenbytes + 3;
402
403        //programinfo len
404        buf[8 + lenbytes] = (tmppos - 9 - lenbytes) & 0xff;
405        buf[7 + lenbytes] = ((tmppos - 9 - lenbytes) >> 8) & 0xff;
406
407        if(round == 0)
408        {
409#ifdef CAMSUPP
410                if(caservice[caservicenr].caslot == NULL || clear == 1)
411                        sendcapmttocam(node, buf, pos, caservicenr);
412#endif
413                if(clear == 0)
414                {
415                        round = 1;
416                        goto start;
417                }
418        }
419        else
420        {
421                if(caservice[caservicenr].camsockfd < 0)
422                        sendcapmttosock(node, buf, pos, caservicenr);
423        }
424
425        free(buf);
426}
427
428void checkcam()
429{
430        int i = 0;
431
432        if(status.pmtmode == 1) return;
433 
434        //struct can change from another thread
435        m_lock(&status.servicemutex, 2);
436        for(i = 0; i < MAXCASERVICE; i++)
437        {
438                if(caservice[i].service != NULL)
439                {
440                        sockcheck(&caservice[i].camsockfd);
441                        if(caservice[i].camsockfd < 0 || caservice[i].caslot == NULL)
442                                sendcapmt(caservice[i].service, 0, 1);
443                }
444        }
445        m_unlock(&status.servicemutex, 2);
446}
447
448struct pmt* addpmt(struct channel* chnode, int programnumber, int versionnumber, int currentnextindicator)
449{
450        debug(1000, "in");
451        struct pmt *newnode = NULL;
452
453        if(chnode == NULL)
454        {
455                debug(1000, "out -> NULL detect");
456                return NULL;
457        }
458
459        newnode = (struct pmt*)malloc(sizeof(struct pmt));     
460        if(newnode == NULL)
461        {
462                err("no memory");
463                return NULL;
464        }
465
466        memset(newnode, 0, sizeof(struct pmt));
467
468        newnode->programnumber = programnumber;
469        newnode->versionnumber = versionnumber;
470        newnode->currentnextindicator = currentnextindicator;
471
472        chnode->pmt = newnode;
473
474        debug(1000, "out");
475        return newnode;
476}
477
478struct cadesc* addcadesc(struct channel* chnode, unsigned char* buf, struct cadesc* last)
479{
480        debug(1000, "in");
481        struct cadesc *newnode = NULL, *prev = NULL, *node = NULL;
482
483        if(chnode == NULL || buf == NULL)
484        {
485                debug(1000, "out -> NULL detect");
486                return NULL;
487        }
488
489        node = chnode->cadesc;
490
491        newnode = (struct cadesc*)malloc(sizeof(struct cadesc));       
492        if(newnode == NULL)
493        {
494                err("no memory");
495                return NULL;
496        }
497
498        memset(newnode, 0, sizeof(struct cadesc));
499
500        newnode->len = buf[1];
501        newnode->systemid = (buf[2] << 8) | buf[3];
502        newnode->reserved = buf[4] >> 5;
503        newnode->pid = ((buf[4] & 0x1F) << 8) | buf[5];
504
505        if(newnode->len > 4)
506        {
507                newnode->privat = malloc(newnode->len - 4);
508                if(newnode->privat == NULL)
509                {
510                        err("no mem");
511                }
512                else
513                        memcpy(newnode->privat, &buf[6], newnode->len - 4);
514        }
515
516        if(last == NULL)
517        {
518                while(node != NULL)
519                {
520                        prev = node;
521                        node = node->next;
522                }
523        }
524        else
525        {
526                prev = last;
527                node = last->next;
528        }
529
530        if(prev == NULL)
531                chnode->cadesc = newnode;
532        else
533                prev->next = newnode;
534
535        newnode->next = node;
536
537        debug(1000, "out");
538        return newnode;
539}
540
541struct esinfo* addesinfo(struct channel* chnode, int streamtype, int pid, struct esinfo* last)
542{
543        debug(1000, "in");
544        struct esinfo *newnode = NULL, *prev = NULL, *node = NULL;
545
546        if(chnode == NULL)
547        {
548                debug(1000, "out -> NULL detect");
549                return NULL;
550        }
551
552        node = chnode->esinfo;
553
554        newnode = (struct esinfo*)malloc(sizeof(struct esinfo));       
555        if(newnode == NULL)
556        {
557                err("no memory");
558                return NULL;
559        }
560
561        memset(newnode, 0, sizeof(struct esinfo));
562
563        newnode->streamtype = streamtype;
564        newnode->pid = pid;
565
566        if(last == NULL)
567        {
568                while(node != NULL)
569                {
570                        prev = node;
571                        node = node->next;
572                }
573        }
574        else
575        {
576                prev = last;
577                node = last->next;
578        }
579
580        if(prev == NULL)
581                chnode->esinfo = newnode;
582        else
583                prev->next = newnode;
584
585        newnode->next = node;
586
587        debug(1000, "out");
588        return newnode;
589}
590
591void freepmt(struct channel* chnode)
592{
593        debug(1000, "in");
594
595        if(chnode == NULL || chnode->pmt == NULL)
596        {
597                debug(1000, "out -> NULL detect");
598                return;
599        }
600
601        free(chnode->pmt);
602        chnode->pmt = NULL;
603
604        debug(1000, "out");
605}
606
607void freecadesc(struct channel* chnode)
608{
609        debug(1000, "in");
610        struct cadesc *node = NULL, *prev = NULL;
611
612        if(chnode == NULL)
613        {
614                debug(1000, "out -> NULL detect");
615                return;
616        }
617
618        node = chnode->cadesc;
619        prev = chnode->cadesc;
620
621        while(node != NULL)
622        {
623                prev = node;
624                node = node->next;
625                chnode->cadesc = node;
626
627                free(prev->privat);
628                prev->privat = NULL;
629
630                free(prev);
631                prev = NULL;
632
633        }
634
635        debug(1000, "out");
636}
637
638void freeesinfo(struct channel* chnode)
639{
640        debug(1000, "in");
641        struct esinfo *node = NULL, *prev = NULL;
642
643        if(chnode == NULL)
644        {
645                debug(1000, "out -> NULL detect");
646                return;
647        }
648
649        node = chnode->esinfo;
650        prev = chnode->esinfo;
651
652        while(node != NULL)
653        {
654                prev = node;
655                node = node->next;
656                chnode->esinfo = node;
657
658                free(prev);
659                prev = NULL;
660
661        }
662
663        debug(1000, "out");
664}
665
666#endif
Note: See TracBrowser for help on using the repository browser.