source: branches/smartreader/module-dvbapi.c@ 1002

Last change on this file since 1002 was 1002, checked in by rorothetroll, 13 years ago

resync with trunk.
module-dvbapi.c : add some ifdef OS_LINUX as this code work ONLY ON LINUX !!!!!... ca we not break all please !!

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