source: titan/titan/cam.h @ 17041

Last change on this file since 17041 was 17041, checked in by nit, 12 years ago

[titan] add debugs

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