source: trunk/module-dvbapi.c@ 1013

Last change on this file since 1013 was 1013, checked in by landlord, 13 years ago

Added HAVE_DVBAPI compile option for DVBAPI module, reviewed 'module-dvbapi.c'

File size: 18.0 KB
Line 
1/*
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 */
18
19#ifdef HAVE_DVBAPI
20
21#include <errno.h>
22#include <fcntl.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <sys/ioctl.h>
27#include <sys/poll.h>
28#include <sys/socket.h>
29#include <sys/types.h>
30#include <sys/un.h>
31#include <unistd.h>
32
33#include "globals.h"
34
35#include <linux/dvb/ca.h>
36#include <linux/dvb/dmx.h>
37
38#define CADEV "/dev/dvb/adapter0/ca1"
39#define DMXDEV "/dev/dvb/adapter0/demux0"
40#define CAMDSOCKET "/tmp/camd.socket"
41
42#define BUFSIZE 1024
43#define MAX_CAID 50
44
45typedef struct ca_descriptor_s
46{
47 unsigned char descriptor_tag : 8;
48 unsigned char descriptor_length : 8;
49 unsigned short ca_system_id : 16;
50 unsigned char reserved : 3;
51 unsigned short ca_pid : 13;
52 unsigned char * private_data_byte;
53} __attribute__ ((packed)) ca_descriptor;
54
55typedef struct ca_pmt_program_info_s
56{
57 unsigned char ca_pmt_cmd_id : 8;
58 ca_descriptor * descriptor;
59} __attribute__ ((packed)) ca_pmt_program_info;
60
61typedef struct ca_pmt_es_info_s
62{
63 unsigned char stream_type : 8;
64 unsigned char reserved : 3;
65 unsigned short elementary_pid : 13;
66 unsigned char reserved2 : 4;
67 unsigned short es_info_length : 12;
68 ca_pmt_program_info * program_info;
69} __attribute__ ((packed)) ca_pmt_es_info;
70
71typedef struct ca_pmt_s
72{
73 unsigned char ca_pmt_list_management : 8;
74 unsigned short program_number : 16;
75 unsigned char reserved1 : 2;
76 unsigned char version_number : 5;
77 unsigned char current_next_indicator : 1;
78 unsigned char reserved2 : 4;
79 unsigned short program_info_length : 12;
80 ca_pmt_program_info * program_info;
81 ca_pmt_es_info * es_info;
82} __attribute__ ((packed)) ca_pmt;
83
84static int camfd = -1;
85static int dmxfd_ecm = -1;
86static int dmxfd_emm = -1;
87static int listenfd = -1;
88
89// if set descrabling
90unsigned short global_capid=0;
91unsigned short global_caid=0;
92unsigned short global_emmpid=0;
93
94unsigned short global_caid_list[MAX_CAID];
95
96unsigned short prg_nr=0;
97
98unsigned char buffer_cache_dmx[12];
99unsigned char buffer_cache_capmt[12];
100
101unsigned char lastcw0[8], lastcw1[8];
102
103typedef struct ECMPIDS
104{
105 int CA_PID;
106 int CA_System_ID;
107} ECMPIDSTYPE;
108
109ECMPIDSTYPE ECMpids[20];
110int ECMpidcount=0;
111
112unsigned short dvbapi_get_single_ecm(int caid, int pid, unsigned char filt, unsigned char mask)
113{
114 unsigned char buf[BUFSIZE];
115 int dmx_fd, len;
116
117 struct dmx_sct_filter_params sFP;
118
119 memset(&sFP, 0, sizeof(sFP));
120
121 memset(buf,0,BUFSIZE);
122
123
124
125 sFP.pid = pid;
126 sFP.timeout = 1000;
127 sFP.flags = DMX_ONESHOT | DMX_CHECK_CRC | DMX_IMMEDIATE_START;
128 sFP.filter.filter[0] = filt;
129 sFP.filter.mask[0] = mask;
130
131 if ((dmx_fd = open(DMXDEV, O_RDWR)) < 0)
132 return 0;
133
134 if (ioctl(dmx_fd, DMX_SET_FILTER, &sFP) < 0)
135 return 0;
136
137 len=read(dmx_fd, buf, BUFSIZE);
138
139 close(dmx_fd);
140
141 ECM_REQUEST *er;
142
143 if (!(er=get_ecmtask()))
144 return 0;
145
146 er->srvid = prg_nr;
147 er->caid = caid;
148 er->pid=pid;
149 //er->prid = provid; //FIXME
150
151 er->l=len;
152 memcpy(er->ecm, buf, er->l);
153
154 get_cw(er);
155
156 return 0;
157}
158
159unsigned short dvbapi_parse_cat(unsigned short ca_system_id)
160{
161 unsigned char buf[BUFSIZE];
162 unsigned short i, emmpid;
163 int dmx_fd, len;
164
165 struct dmx_sct_filter_params sFP;
166
167 memset(&sFP, 0, sizeof(sFP));
168
169 memset(buf,0,BUFSIZE);
170
171 sFP.filter.filter[0] = 0x01;
172 sFP.filter.mask[0] = 0xFF;
173 sFP.flags = DMX_ONESHOT | DMX_CHECK_CRC | DMX_IMMEDIATE_START;
174 sFP.pid = 0x0001;
175 sFP.timeout = 3000; //3secs
176
177 if ((dmx_fd = open(DMXDEV, O_RDWR)) < 0)
178 return 0;
179
180 if (ioctl(dmx_fd, DMX_SET_FILTER, &sFP) < 0)
181 return 0;
182
183 len=read(dmx_fd, buf, BUFSIZE);
184
185 close(dmx_fd);
186
187 for (i = 8; i < (((buf[1] & 0x0F) << 8) | buf[2]) - 1; i += buf[i + 1] + 2)
188 {
189 if ((buf[i] == 0x09) && ((((buf[i + 2] & 0x1F) << 8) | buf[i + 3]) == ca_system_id))
190 {
191 emmpid=(((buf[i + 4] & 0x1F) << 8) | buf[i + 5]);
192 return emmpid;
193 }
194 }
195
196 return 0;
197}
198
199int dvbapi_stop_filter(void)
200{
201 //cs_log("Stopping filtering...");
202
203 if (ioctl(dmxfd_ecm,DMX_STOP)<0)
204 return 0;
205
206 if (ioctl(dmxfd_emm,DMX_STOP)<0)
207 return 0;
208
209 return 1;
210}
211
212unsigned short dvbapi_parse_ecm(unsigned char *buf, int len)
213{
214 unsigned short provid;
215
216 provid=(buf[3]<<8)|buf[4];
217 cs_debug("Read %d bytes\tTable-id: %02x\tCA section length: %d\tProvider ID: %04x", len, buf[0], len ,provid);
218
219 //calen=((buf[1]<<8)+buf[2])&0x0fff;
220
221 /*
222 provid=b2i(2, buf+3);
223
224 i=(buf[4]==0xD2) ? buf[5] + 2 : 0; // skip d2 nano
225 if ((buf[5+i]==3) && ((buf[4+i]==0x90) || (buf[4+i]==0x40)))
226 provid=(b2i(3, buf+6+i) & 0xFFFFF0);
227
228 //cs_log("PROVIDER: %04x", provid);
229 */
230
231 if (len>0) {
232 ECM_REQUEST *er;
233
234 if (!(er=get_ecmtask()))
235 return 0;
236
237 er->srvid = prg_nr;
238 er->caid = global_caid;
239 //er->prid = provid; //FIXME
240
241 er->l=len;
242 memcpy(er->ecm, buf, er->l);
243
244 get_cw(er);
245 }
246
247 return(provid);
248}
249
250int dvbapi_set_filter(int fd, int pid, unsigned char filt, unsigned char mask)
251{
252 struct dmx_sct_filter_params sFP;
253 cs_debug("Set filter pid:%d, value:%d...",pid, filt);
254
255 memset(&sFP,0,sizeof(sFP));
256
257 sFP.pid = pid;
258 sFP.timeout = 3000; //wait max 3 seconds for ECM message, should be repeated every 500ms
259 sFP.flags = DMX_CHECK_CRC | DMX_IMMEDIATE_START;
260 sFP.filter.filter[0] = filt;
261 sFP.filter.mask[0] = mask;
262
263 if (ioctl(fd, DMX_SET_FILTER, &sFP) < 0)
264 {
265 perror(" Status");
266 return 0;
267 }
268
269 return 1;
270}
271
272void dvbapi_stop_descramble()
273{
274 dvbapi_stop_filter();
275
276 /*
277 if (global_capid != 0) {
278 // unset pid?? (not working)
279 ca_pid_t ca_pid;
280 memset(&ca_pid,0,sizeof(ca_pid));
281 ca_pid.pid = global_capid;
282 ca_pid.index = -1;
283 //if (ioctl(camfd, CA_SET_PID, &ca_pid)==-1) perror("Error Remove SET_PID");
284 }
285 */
286
287 global_capid=0;
288 global_caid=0;
289 global_emmpid=0;
290}
291
292void dvbapi_start_descramble(int caid, int capid) {
293
294 cs_log("Softcam: Start descrambling CAID: %04x", caid);
295
296 if (!dvbapi_set_filter(dmxfd_ecm,capid,0x80,0xF0)) //filter on ECM pid and 0x80 or 0x81 (mask 0xF0)
297 cs_log("Error ECM filtering");
298
299 global_capid=capid;
300 global_caid=caid;
301
302 /*
303 * get emm pid and start filter
304 * TODO: prase_cat blocks thread */
305
306 if (cfg->dvbapi_au==1) {
307 short emmpid;
308 emmpid=dvbapi_parse_cat(caid);
309
310 cs_log("EMMPid: %04x", emmpid);
311 dvbapi_set_filter(dmxfd_emm,emmpid,0x80,0xF0);
312 global_emmpid=emmpid;
313 }
314
315 ca_pid_t ca_pid;
316 memset(&ca_pid,0,sizeof(ca_pid));
317 ca_pid.pid = capid;
318 ca_pid.index = 0;
319 if (ioctl(camfd, CA_SET_PID, &ca_pid)==-1)
320 cs_log("Softcam: Error SET_PID");
321}
322
323// from tuxbox camd
324int dvbapi_parse_capmt(unsigned char *buffer, const unsigned int length)
325
326{
327 unsigned short i, j;
328 ca_pmt *pmt;
329 int n;
330
331 cs_dump(buffer, length, "capmt:");
332 pmt = (ca_pmt *) malloc(sizeof(ca_pmt));
333
334 pmt->ca_pmt_list_management = buffer[0];
335 pmt->program_number = (buffer[1] << 8) | buffer[2];
336 prg_nr=pmt->program_number;
337
338 pmt->program_info_length = ((buffer[4] & 0x0F) << 8) | buffer[5];
339
340 cs_log("program number: %04x", pmt->program_number);
341 cs_debug("program_info_length: %d", pmt->program_info_length);
342
343 switch (pmt->ca_pmt_list_management)
344 {
345 case 0x01:
346 //FIXME?? (first)
347 break;
348 case 0x03:
349 //default (only)
350 break;
351 default:
352 //FIXME?? (unknown)
353 break;
354 }
355
356 ECMpidcount=0;
357
358 //CA_PIDS fr alle Streams
359 if (pmt->program_info_length != 0)
360 {
361 pmt->program_info = (ca_pmt_program_info *) malloc(sizeof(ca_pmt_program_info));
362 pmt->program_info->ca_pmt_cmd_id = buffer[6];
363 //cs_debug("ca_pmt_id: %04x", pmt->program_info->ca_pmt_cmd_id);
364 pmt->program_info->descriptor = (ca_descriptor *) malloc(sizeof(ca_descriptor));
365
366 for (i = 0; i < pmt->program_info_length - 1; i += pmt->program_info->descriptor->descriptor_length + 2)
367 {
368 pmt->program_info->descriptor->descriptor_length = buffer[i + 8];
369 pmt->program_info->descriptor->ca_system_id = (buffer[i + 9] << 8) | buffer[i + 10];
370 pmt->program_info->descriptor->ca_pid = ((buffer[i + 11] & 0x1F) << 8)| buffer[i + 12];
371
372 cs_debug("typ: %02x ca_system_id: %04x\t ca_pid: %04x\tca_descriptor_length %d", buffer[i + 7], pmt->program_info->descriptor->ca_system_id, pmt->program_info->descriptor->ca_pid,pmt->program_info->descriptor->descriptor_length);
373
374 if (buffer[i + 7] == 0x09) {
375 ECMpids[ECMpidcount].CA_PID=pmt->program_info->descriptor->ca_pid; //add the PID
376 ECMpids[ECMpidcount].CA_System_ID=pmt->program_info->descriptor->ca_system_id; //add the system id
377 ECMpidcount++;
378 }
379 }
380
381 free(pmt->program_info->descriptor);
382 free(pmt->program_info);
383 }
384
385
386 //CA_PIDs fr einzelne Streams
387 //
388 pmt->es_info = (ca_pmt_es_info *) malloc(sizeof(ca_pmt_es_info));
389
390 for (i = pmt->program_info_length + 6; i < length; i += pmt->es_info->es_info_length + 5)
391 {
392
393 pmt->es_info->stream_type = buffer[i];
394 pmt->es_info->elementary_pid = ((buffer[i + 1] & 0x1F) << 8) | buffer[i + 2];
395 pmt->es_info->es_info_length = ((buffer[i + 3] & 0x0F) << 8) | buffer[i + 4];
396
397 cs_debug("stream_type: %02x\telementary_pid: %04x\tes_info_length: %04x", pmt->es_info->stream_type, pmt->es_info->elementary_pid, pmt->es_info->es_info_length);
398
399 if (pmt->es_info->es_info_length != 0)
400 {
401 pmt->es_info->program_info = (ca_pmt_program_info *) malloc(sizeof(ca_pmt_program_info));
402
403 pmt->es_info->program_info->ca_pmt_cmd_id = buffer[i + 5];
404 pmt->es_info->program_info->descriptor = (ca_descriptor *)malloc(sizeof(ca_descriptor));
405
406 for (j = 0; j < pmt->es_info->es_info_length - 1; j += pmt->es_info->program_info->descriptor->descriptor_length + 2)
407 {
408 pmt->es_info->program_info->descriptor->descriptor_length = buffer[i + j + 7];
409 pmt->es_info->program_info->descriptor->ca_system_id = (buffer[i + j + 8] << 8) | buffer[i + j + 9];
410 pmt->es_info->program_info->descriptor->ca_pid = ((buffer[i + j + 10] & 0x1F) << 8) | buffer[i + j + 11];
411
412 cs_debug("typ: %02x\tca_system_id: %04x\t ca_pid: %04x", buffer[i + j + 6], pmt->es_info->program_info->descriptor->ca_system_id, pmt->es_info->program_info->descriptor->ca_pid);
413
414 if (buffer[i + j + 6] == 0x09) {
415 ECMpids[ECMpidcount].CA_PID=pmt->program_info->descriptor->ca_pid; //add the PID
416 ECMpids[ECMpidcount].CA_System_ID=pmt->program_info->descriptor->ca_system_id; //add the system id
417 ECMpidcount++;
418 }
419 }
420
421 free(pmt->es_info->program_info->descriptor);
422 free(pmt->es_info->program_info);
423 }
424 }
425
426 free(pmt->es_info);
427 free(pmt);
428
429 dvbapi_stop_descramble();
430
431 cs_log("Softcam: Found %d ECMpids in PMT", ECMpidcount);
432
433 for (n=0; n<ECMpidcount; n++) {
434
435 cs_debug("CA_System_ID: %04x CA_PID: %04x", ECMpids[n].CA_System_ID, ECMpids[n].CA_PID);
436
437 if (global_caid!=0) continue;
438
439 dvbapi_get_single_ecm(ECMpids[n].CA_System_ID,ECMpids[n].CA_PID,0x80,0xF0);
440 sleep(3);
441 }
442
443 return 0;
444}
445
446void dvbapi_handlesockmsg (unsigned char *buffer, ssize_t len)
447{
448 int i;
449 unsigned int val;
450 unsigned int size;
451 //cs_dump(buffer, len, "handlesockmsg:");
452
453 if (buffer[0] != 0x9F) {
454 cs_log("handlesockmsg() unknown socket command: %02x", buffer[0]);
455 return;
456 }
457
458 if (buffer[1] != 0x80) {
459 cs_log("handlesockmsg() unknown apdu tag");
460 return;
461 }
462
463
464 if (buffer[3] & 0x80) {
465 val = 0;
466 size = buffer[3] & 0x7F;
467 for (i = 0; i < size; i++)
468 val = (val << 8) | buffer[i + 1 + 3];
469 size++;
470 } else
471 {
472 val = buffer[3] & 0x7F;
473 size = 1;
474 }
475
476 if (buffer[2] == 0x30) // ca_info_enq
477 cs_debug("ca_info!!");
478 else if (buffer[2] == 0x32) // ca_pmt
479 {
480 if ((3 + size + val) == len)
481 dvbapi_parse_capmt(buffer + 3 + size, val);
482 else
483 cs_log("handlesockmsg() ca_pmt invalid length");
484 }
485 else if (buffer[2] == 0x3f)
486 {
487 //9F 80 3f 04 83 02 00 00
488 //zap?
489 //cs_debug("zap!");
490 } else
491 {
492 cs_log("client: handlesockmsg() unknown command");
493 cs_dump(buffer, len, "unknown command:");
494 }
495}
496
497static int dvbapi_init_listenfd() {
498
499 int clilen;
500 struct sockaddr_un servaddr;
501
502 memset(&servaddr, 0, sizeof(struct sockaddr_un));
503 servaddr.sun_family = AF_UNIX;
504 strcpy(servaddr.sun_path, cfg->dvbapi_socket);
505 clilen = sizeof(servaddr.sun_family) + strlen(servaddr.sun_path);
506
507 if ((unlink(cfg->dvbapi_socket) < 0) && (errno != ENOENT))
508 return 0;
509 if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
510 return 0;
511 if (bind(listenfd, (struct sockaddr *) &servaddr, clilen) < 0)
512 return 0;
513 if (listen(listenfd, 5) < 0)
514 return 0;
515
516 return 1;
517}
518
519void *thread_check_zap(void *arg) {
520 unsigned char buffer[BUFSIZE];
521 struct sockaddr_un servaddr;
522 ssize_t len;
523 int connfd,clilen;
524
525 while(1)
526 {
527 sleep(1); // check every second
528 //cs_log("check zap");
529
530
531
532 connfd = accept(listenfd, (struct sockaddr *)&servaddr, (socklen_t *)&clilen);
533
534 if (connfd <= 0) //socket not available
535 break;
536
537 len = read(connfd, buffer, sizeof(buffer));
538
539 if (len < 3) {
540 cs_debug("Client: camd.socket: too short message received");
541 break;
542 }
543
544 // if message begins with an apdu_tag and is longer than three bytes
545 if ((buffer[0] == 0x9F) && ((buffer[1] >> 7) == 0x01) && ((buffer[2] >> 7) == 0x00)) {
546 if (memcmp(buffer, buffer_cache_capmt, 8) != 0) {
547 memcpy(buffer_cache_capmt, buffer, 8);
548 dvbapi_handlesockmsg(buffer, len);
549 }
550 }
551
552 close(connfd);
553
554 }
555 return 0;
556}
557
558void *thread_check_dmx(void *arg) {
559
560 struct pollfd pfd2[2];
561 int rc,len,i;
562 unsigned char buffer[BUFSIZE];
563
564 pfd2[0].fd = dmxfd_ecm;
565 pfd2[0].events = (POLLIN | POLLPRI);
566 pfd2[1].fd = dmxfd_emm;
567 pfd2[1].events = (POLLIN | POLLPRI);
568
569 while(1)
570 {
571
572 rc=poll(pfd2, 2, -1);
573
574 if (global_capid == 0) {
575 dvbapi_stop_filter();
576 break;
577 }
578
579 for (i = 0; i < 2; i++) {
580 if (pfd2[i].revents & (POLLIN | POLLPRI)) {
581 if (pfd2[i].fd == dmxfd_ecm) {
582 if ((len = read(dmxfd_ecm, buffer, BUFSIZE)) <= 0)
583 break;
584
585 if (len != (((buffer[1] & 0xf) << 8) | buffer[2]) + 3) //invaild CAT length
586 break;
587
588 if (buffer[0] == 0x80 | buffer[0] == 0x81)
589 {
590 if (memcmp(buffer, buffer_cache_dmx, 12) != 0) {
591 memcpy(buffer_cache_dmx, buffer, 12);
592 if (!dvbapi_parse_ecm(buffer,len)) { cs_log("Error while parsing ECM"); }
593 }
594 }
595
596 }
597
598 if (pfd2[i].fd == dmxfd_emm) {
599 if ((len = read(dmxfd_emm, buffer, BUFSIZE)) <= 0)
600 break;
601
602 if (len != (((buffer[1] & 0xf) << 8) | buffer[2]) + 3) //invaild CAT length
603 break;
604
605 /*
606 //nagra only???
607 int emmtype;
608 if( (buffer[0]==0x82) ) emmtype = 0; // U
609 if( (buffer[0]==0x83) && (buffer[7]==0x10) ) emmtype = 1; // S
610 if( (buffer[0]==0x83) && (buffer[7]==0x00) ) emmtype = 2; // G
611
612
613 */
614 cs_log("EMM Type: 0x%02x", buffer[0]);
615
616 //force emm output
617 reader[ridx].logemm=9999;
618
619 memset(&epg, 0, sizeof(epg));
620
621 epg.caid[0] = (uchar)(global_caid>>8);
622 epg.caid[1] = (uchar)(global_caid);
623 if (reader[client[cs_idx].au].caid[0]!=b2i(2,epg.caid)) cs_log("caid %04x", b2i(2,epg.caid));
624 //memcpy(epg.provid, prov, 4);
625
626 epg.l=len;
627 memcpy(epg.emm, buffer, epg.l);
628 memcpy(epg.hexserial, reader[client[cs_idx].au].hexserial, 8);
629
630 do_emm(&epg);
631
632 }
633 }
634 }
635
636 }
637 return 0;
638}
639
640int dvbapi_main_local()
641{
642 struct pollfd pfd2[1];
643 int i,rc;
644 pthread_t p1, p2;
645
646
647 if (cfg->dvbapi_demux[0]==0)
648 strncpy(cfg->dvbapi_demux, DMXDEV, sizeof(cfg->dvbapi_demux)-1);
649
650 if (cfg->dvbapi_ca[0]==0)
651 strncpy(cfg->dvbapi_ca, CADEV, sizeof(cfg->dvbapi_ca)-1);
652
653 if (cfg->dvbapi_socket[0]==0)
654 strncpy(cfg->dvbapi_socket, CAMDSOCKET, sizeof(cfg->dvbapi_socket)-1);
655
656 if (cfg->dvbapi_usr[0]==0) {
657 //
658 }
659
660 for (i=0;i<20;i++) //clean ECMpids array
661 {
662 ECMpids[i].CA_PID = 0;
663 ECMpids[i].CA_System_ID = 0;
664 }
665
666
667 if ((dmxfd_ecm = open(cfg->dvbapi_demux, O_RDWR)) < 0) {
668 cs_log("Could not open dmx device");
669 return 1;
670 }
671
672 if ((dmxfd_emm = open(cfg->dvbapi_demux, O_RDWR)) < 0) {
673 cs_log("Could not open dmx device");
674 return 1;
675 }
676
677 if ((camfd = open(cfg->dvbapi_ca, O_RDWR)) < 0) {
678 cs_log("Could not open ca device");
679 return 1;
680 }
681
682 if (!dvbapi_init_listenfd()) return 1;
683
684 pfd2[0].fd = fd_m2c;
685 pfd2[0].events = (POLLIN | POLLPRI);
686
687 memset(buffer_cache_capmt,0 ,12);
688 memset(buffer_cache_dmx,0 ,12);
689
690 pthread_create (&p1, NULL, thread_check_zap, NULL);
691 pthread_create (&p2, NULL, thread_check_dmx, NULL);
692
693 pfd=dmxfd_ecm;
694
695 while (1) {
696 if (master_pid!=getppid()) {
697 cs_log("master died");
698 cs_exit(0);
699 }
700
701 rc=poll(pfd2, 1, 500);
702
703 if (rc<0)
704 break;
705
706 if (pfd2[0].revents & (POLLIN | POLLPRI)) {
707 chk_dcw(fd_m2c);
708 }
709
710 }
711 return 0;
712}
713
714static void dvbapi_send_dcw(ECM_REQUEST *er) {
715 unsigned char cw_0[8], cw_1[8];
716
717 memcpy(cw_0, er->cw, 8);
718 memcpy(cw_1, er->cw+8, 8);
719
720 ca_descr_t ca_descr;
721 memset(&ca_descr,0,sizeof(ca_descr));
722
723
724 if (er->rc==0 && global_caid==0)
725 {
726 dvbapi_start_descramble(er->caid, er->pid);
727 }
728
729 if (memcmp(cw_0,lastcw0,8))
730 {
731 ca_descr.index = 0;
732 ca_descr.parity = 0;
733 memcpy(lastcw0,cw_0,8);
734 memcpy(ca_descr.cw,cw_0,8);
735 if (ioctl(camfd,CA_SET_DESCR,&ca_descr) < 0) perror("CA_SET_DESCR");
736 }
737
738 if (memcmp(cw_1,lastcw1,8))
739 {
740 ca_descr.index = 0;
741 ca_descr.parity = 1;
742 memcpy(lastcw1,cw_1,8);
743 memcpy(ca_descr.cw,cw_1,8);
744 if (ioctl(camfd,CA_SET_DESCR,&ca_descr) < 0) perror("CA_SET_DESCR");
745 }
746
747}
748
749static void dvbapi_handler(int idx) {
750 static struct s_auth *account=0;
751
752 if (cfg->dvbapi_enabled != 1) {
753 cs_log("client disabled");
754 return;
755 }
756
757 cs_log("client loaded fd=%d", idx);
758
759 switch(cs_fork(0, idx))
760 {
761 case 0: //master
762 case -1:
763 return;
764 default:
765 wait4master();
766 }
767
768 int ok=0;
769
770 if( !account )
771 {
772 client[cs_idx].usr[0]=0;
773 for (ok=0, account=cfg->account; (account) && (!ok); account=account->next)
774 if( (ok=!strcmp(cfg->dvbapi_usr, account->usr)) )
775 break;
776 }
777
778 cs_auth_client(ok ? account : (struct s_auth *)(-1), "unknown");
779
780 dvbapi_main_local();
781
782 cs_log("Module client error");
783 cs_exit(0);
784
785 return;
786
787}
788
789/*
790 * protocol structure
791 */
792
793void module_dvbapi(struct s_module *ph)
794{
795 strcpy(ph->desc, "dvbapi");
796 ph->type=MOD_CONN_SERIAL;
797 ph->multi=0;
798 ph->watchdog=0;
799 ph->s_handler=dvbapi_handler;
800 ph->send_dcw=dvbapi_send_dcw;
801}
802
803void module_dvbapi(struct s_module *ph) {}
804
805#endif // HAVE_DVBAPI
Note: See TracBrowser for help on using the repository browser.