source: branches/monitor-improvement/module-dvbapi.c@ 1189

Last change on this file since 1189 was 1189, checked in by alno, 12 years ago

WebIf:

  • Merging revisions 1180-1185 of trunk
File size: 28.6 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#define BUFSIZE 1024
36#define MAX_DEMUX 5
37#define MAX_CAID 50
38#define TAB_SIZE 30
39#define ECM_PIDS 20
40
41static int listenfd = -1;
42
43typedef struct ECMPIDS
44{
45 unsigned short CA_PID;
46 unsigned short CA_System_ID;
47 unsigned short EMM_PID;
48} ECMPIDSTYPE;
49
50typedef struct demux_s
51{
52 int demux_index;
53 int demux_ecm_fd;
54 int demux_emm_fd;
55 int cadev_index;
56 int ca_fd;
57 int active;
58 int ECMpidcount;
59 ECMPIDSTYPE ECMpids[ECM_PIDS];
60 unsigned int program_number;
61 unsigned int ca_system_id;
62 unsigned int ca_pid;
63 unsigned int provider_id;
64 unsigned int emm_pid;
65 int STREAMpidcount;
66 short STREAMpids[ECM_PIDS];
67 unsigned char buffer_cache_dmx[12];
68 unsigned char lastcw0[8];
69 unsigned char lastcw1[8];
70} DEMUXTYPE;
71#define DMX_FILTER_SIZE 16
72
73//dvbapi 1
74typedef struct dmxFilter
75{
76 uint8_t filter[DMX_FILTER_SIZE];
77 uint8_t mask[DMX_FILTER_SIZE];
78} dmxFilter_t;
79
80struct dmxSctFilterParams
81{
82 uint16_t pid;
83 dmxFilter_t filter;
84 uint32_t timeout;
85 uint32_t flags;
86#define DMX_CHECK_CRC 1
87#define DMX_ONESHOT 2
88#define DMX_IMMEDIATE_START 4
89#define DMX_BUCKET 0x1000 /* added in 2005.05.18 */
90#define DMX_KERNEL_CLIENT 0x8000
91};
92
93#define DMX_START1 _IOW('o',41,int)
94#define DMX_STOP1 _IOW('o',42,int)
95#define DMX_SET_FILTER1 _IOW('o',43,struct dmxSctFilterParams *)
96
97
98//dbox2+ufs
99typedef struct dmx_filter
100{
101 uint8_t filter[DMX_FILTER_SIZE];
102 uint8_t mask[DMX_FILTER_SIZE];
103 uint8_t mode[DMX_FILTER_SIZE];
104} dmx_filter_t;
105
106
107struct dmx_sct_filter_params
108{
109 uint16_t pid;
110 dmx_filter_t filter;
111 uint32_t timeout;
112 uint32_t flags;
113#define DMX_CHECK_CRC 1
114#define DMX_ONESHOT 2
115#define DMX_IMMEDIATE_START 4
116#define DMX_KERNEL_CLIENT 0x8000
117};
118
119typedef struct ca_descr {
120 unsigned int index;
121 unsigned int parity; /* 0 == even, 1 == odd */
122 unsigned char cw[8];
123} ca_descr_t;
124
125typedef struct ca_pid {
126 unsigned int pid;
127 int index; /* -1 == disable*/
128} ca_pid_t;
129
130#define DMX_START _IO('o', 41)
131#define DMX_STOP _IO('o', 42)
132#define DMX_SET_FILTER _IOW('o', 43, struct dmx_sct_filter_params)
133
134#define CA_SET_DESCR _IOW('o', 134, ca_descr_t)
135#define CA_SET_PID _IOW('o', 135, ca_pid_t)
136
137DEMUXTYPE demux[MAX_DEMUX];
138
139unsigned short global_caid_list[MAX_CAID];
140unsigned short prioritytab[TAB_SIZE], ignoretab[TAB_SIZE];
141
142#define BOX_COUNT 2
143struct box_devices
144{
145 char ca_device_path[32];
146 char demux_device_path[32];
147 char cam_socket_path[32];
148};
149
150struct box_devices devices[BOX_COUNT] = {
151 /* dreambox (dvb-api-3)*/ { "/dev/dvb/adapter0/ca%d", "/dev/dvb/adapter0/demux%d", "/var/tmp/camd.socket" },
152 /* dreambox (dvb-api-1)*/ { "/dev/dvb/card0/ca%d", "/dev/dvb/card0/demux%d", "/var/tmp/camd.socket" }
153};
154
155int selected_box=-1;
156int selected_api=-1;
157
158int dvbapi_set_filter(int dmx_fd, int api, unsigned short pid, unsigned char filt, unsigned char mask, int timeout)
159{
160 int command,ret=-1;
161
162 cs_debug("dvbapi: set filter pid:%04x, value:%04x",pid, filt);
163
164 switch(api)
165 {
166 case 0:
167 //dvbapi 3
168 command=0;
169 struct dmx_sct_filter_params sFP2;
170
171 memset(&sFP2,0,sizeof(sFP2));
172
173 sFP2.pid = pid;
174 sFP2.timeout = timeout;
175 sFP2.flags = DMX_IMMEDIATE_START;
176 sFP2.filter.filter[0] = filt;
177 sFP2.filter.mask[0] = mask;
178 ret=ioctl(dmx_fd, DMX_SET_FILTER, &sFP2);
179
180 break;
181 case 1:
182 //dvbapi 1
183 command=0;
184 struct dmxSctFilterParams sFP1;
185
186 memset(&sFP1,0,sizeof(sFP1));
187
188 sFP1.pid = pid;
189 sFP1.timeout = timeout;
190 sFP1.flags = DMX_IMMEDIATE_START;
191 sFP1.filter.filter[0] = filt;
192 sFP1.filter.mask[0] = mask;
193 ret=ioctl(dmx_fd, DMX_SET_FILTER1, &sFP1);
194
195 break;
196 default:
197 break;
198 }
199
200 if (ret < 0)
201 cs_debug("dvbapi: could not start demux filter (Errno: %d)", errno);
202
203 return ret;
204}
205
206
207int dvbapi_detect_api()
208{
209 int num_apis=2;
210 int i,devnum=-1;
211 int apinum=-1;
212 int dmx_fd=0;
213
214 char device_path[128];
215
216 for (i=0;i<BOX_COUNT;i++)
217 {
218 sprintf(device_path, devices[i].demux_device_path, 0);
219 if ((dmx_fd = open(device_path, O_RDWR)) > 0) {
220 devnum=i;
221 break;
222 }
223 }
224
225 if (dmx_fd < 0) return 0;
226
227 int command,ret=0;
228
229 for (i=0;i<num_apis;i++)
230 {
231 ret=dvbapi_set_filter(dmx_fd, i, 0x0001, 0x01, 0xFF, 1);
232
233 if (ret >= 0)
234 {
235 apinum=i;
236 break;
237 }
238 }
239 close(dmx_fd);
240
241 selected_box=devnum;
242 selected_api=apinum;
243 cs_debug("dvbapi: Detected %s Api: %d", device_path, apinum);
244
245 return 1;
246}
247
248int dvbapi_read_device(int dmx_fd, unsigned char *buf, int length, int debug)
249{
250 int len;
251 len=read(dmx_fd, buf, length);
252
253 if (len==-1)
254 cs_log("dvbapi: read error %d", errno);
255
256 if (debug==1)
257 cs_debug("dvbapi: Read %d bytes from demux", len);
258
259 return len;
260}
261
262int dvbapi_open_device(int index_demux, int type)
263{
264 int dmx_fd,i;
265 int ca_offset=0;
266 char device_path[128];
267
268 if (type==0)
269 sprintf(device_path, devices[selected_box].demux_device_path, demux[index_demux].demux_index);
270 else
271 {
272 if (strcmp(cfg->dvbapi_boxtype, "ufs910")==0 || strcmp(cfg->dvbapi_boxtype, "dbox2")==0)
273 ca_offset=1;
274
275 sprintf(device_path, devices[selected_box].ca_device_path, demux[index_demux].cadev_index+ca_offset);
276 }
277
278 if ((dmx_fd = open(device_path, O_RDWR)) < 0) {
279 if (type==1 && errno==16) // ca device already open
280 for (i=0;i<MAX_DEMUX;i++)
281 if (demux[i].cadev_index==demux[index_demux].cadev_index && demux[i].ca_fd>0)
282 dmx_fd=demux[i].ca_fd;
283
284 if (dmx_fd<=0)
285 cs_debug("dvbapi: error opening device %s (Errno: %d)", device_path, errno);
286 }
287
288 cs_debug("dvbapi: DEVICE open (%s)", device_path);
289 return dmx_fd;
290}
291
292int dvbapi_stop_filter(int demux_index, int type)
293{
294 int dmx_fd;
295
296 if (type==0) {
297 dmx_fd=demux[demux_index].demux_ecm_fd;
298 } else {
299 dmx_fd=demux[demux_index].demux_emm_fd;
300 }
301
302 ioctl(dmx_fd,DMX_STOP);
303 return 1;
304}
305
306unsigned long dvbapi_get_provid(int demux_index, unsigned short pid)
307{
308 unsigned char buf[BUFSIZE];
309 int dmx_fd, len;
310
311 dmx_fd=demux[demux_index].demux_emm_fd;
312
313 dvbapi_set_filter(dmx_fd, selected_api, pid, 0x80, 0xF0, 8000);
314
315 len=dvbapi_read_device(dmx_fd, buf, BUFSIZE, 1);
316
317 if (len > 0) {
318 unsigned long provid = (buf[10] << 8) | buf[11];
319 return provid;
320 }
321
322 return 0;
323}
324
325unsigned short dvbapi_get_single_ecm(int demux_index, unsigned short caid, unsigned short pid, unsigned long provid)
326{
327 unsigned char buf[BUFSIZE];
328 int dmx_fd, len;
329
330 dmx_fd=demux[demux_index].demux_ecm_fd;
331
332 dvbapi_set_filter(dmx_fd, selected_api, pid, 0x80, 0xF0, 2000);
333
334 len=dvbapi_read_device(dmx_fd, buf, BUFSIZE, 1);
335
336 if (len > 0) {
337 ECM_REQUEST *er;
338
339 if (!(er=get_ecmtask()))
340 return 0;
341
342 er->srvid = demux[demux_index].program_number;
343 er->caid = caid;
344 er->pid = pid;
345 er->prid = provid;
346
347 er->l=len;
348 memcpy(er->ecm, buf, er->l);
349
350 get_cw(er);
351
352 memcpy(demux[demux_index].buffer_cache_dmx, buf, 12);
353 }
354 return 0;
355}
356
357void dvbapi_parse_cat(int demux_index)
358{
359 unsigned char buf[BUFSIZE];
360 unsigned short i, j;
361 int dmx_fd, len;
362
363 dmx_fd=demux[demux_index].demux_ecm_fd;
364
365 dvbapi_set_filter(dmx_fd, selected_api, 0x0001, 0x01, 0xFF, 2000);
366
367 len=dvbapi_read_device(dmx_fd, buf, BUFSIZE, 1);
368
369 if (len<=0)
370 return;
371
372 cs_ddump(buf, len, "cat:");
373
374 for (i = 8; i < (((buf[1] & 0x0F) << 8) | buf[2]) - 1; i += buf[i + 1] + 2)
375 {
376 if (buf[i] != 0x09) continue;
377 unsigned short cat_sys_id=(((buf[i + 2] & 0x1F) << 8) | buf[i + 3]);
378 unsigned short emm_pid=(((buf[i + 4] & 0x1F) << 8) | buf[i + 5]);
379 cs_debug("cat: ca_system_id: %04x\temm_pid %04x", cat_sys_id, emm_pid);
380 for (j=0;j<demux[demux_index].ECMpidcount;j++) {
381 if (demux[demux_index].ECMpids[j].CA_System_ID==(((buf[i + 2] & 0x1F) << 8) | buf[i + 3])) {
382 demux[demux_index].ECMpids[j].EMM_PID=emm_pid;
383 break;
384 }
385 }
386 }
387
388 return;
389}
390
391void dvbapi_stop_descrambling(int demux_id)
392{
393 int i;
394
395 cs_log("dvbapi: Stop descrambling CAID: %04x", demux[demux_id].ca_system_id);
396
397 demux[demux_id].ca_system_id=0;
398 demux[demux_id].ca_pid=0;
399 demux[demux_id].emm_pid=0;
400 demux[demux_id].provider_id=0;
401 demux[demux_id].demux_index=-1;
402 demux[demux_id].program_number=0;
403
404 if (demux[demux_id].demux_ecm_fd>0) {
405 ioctl(demux[demux_id].demux_ecm_fd,DMX_STOP);
406 close(demux[demux_id].demux_ecm_fd);
407 cs_debug("dvbapi: closing ecm dmx device");
408 demux[demux_id].demux_ecm_fd=0;
409 }
410
411 if (demux[demux_id].demux_emm_fd>0) {
412 ioctl(demux[demux_id].demux_emm_fd,DMX_STOP);
413 close(demux[demux_id].demux_emm_fd);
414 cs_debug("dvbapi: closing emm dmx device");
415 demux[demux_id].demux_emm_fd=0;
416 }
417
418 if (demux[demux_id].ca_fd>0) {
419 for (i=0;i<demux[demux_id].STREAMpidcount;i++)
420 {
421 ca_pid_t ca_pid2;
422 memset(&ca_pid2,0,sizeof(ca_pid2));
423 ca_pid2.pid = demux[demux_id].STREAMpids[i];
424 ca_pid2.index = -1;
425 if (ioctl(demux[demux_id].ca_fd, CA_SET_PID, &ca_pid2)==-1)
426 cs_debug("dvbapi: Error Stream SET_PID");
427 }
428
429 ca_descr_t ca_descr;
430 memset(&ca_descr,0,sizeof(ca_descr));
431 memset(ca_descr.cw, 0 ,8);
432
433 ca_descr.index = demux_id;
434 ca_descr.parity = 0;
435
436 if (ioctl(demux[demux_id].ca_fd, CA_SET_DESCR, &ca_descr) < 0)
437 cs_debug("dvbapi: Error CA_SET_DESCR");
438
439 ca_descr.index = demux_id;
440 ca_descr.parity = 1;
441
442 if (ioctl(demux[demux_id].ca_fd, CA_SET_DESCR, &ca_descr) < 0)
443 cs_debug("dvbapi: Error CA_SET_DESCR");
444
445 int needed=0;
446 for (i=0;i<MAX_DEMUX;i++) {
447 if (demux[demux_id].ca_fd==demux[i].ca_fd && i != demux_id)
448 needed=1;
449 }
450 if (needed==0) {
451 close(demux[demux_id].ca_fd);
452 cs_debug("dvbapi: closing ca device");
453 }
454 demux[demux_id].ca_fd=0;
455 }
456
457 return;
458}
459
460void dvbapi_stop_descrambling_all(int demux_index)
461{
462 int j;
463 for (j=0;j<MAX_DEMUX;j++) {
464 if (demux[j].demux_index != demux_index)
465 continue;
466
467 dvbapi_stop_descrambling(j);
468 }
469
470 return;
471}
472
473void dvbapi_start_descrambling(int demux_index, unsigned short caid, unsigned short capid, unsigned long provider_id)
474{
475 int i;
476
477 cs_log("dvbapi: Start descrambling CAID: %04x", caid);
478
479 demux[demux_index].ca_pid=capid;
480 demux[demux_index].ca_system_id=caid;
481 demux[demux_index].provider_id=provider_id;
482
483
484 int camfd=dvbapi_open_device(demux_index,1);
485 if (camfd<=0) {
486 return;
487 }
488
489 demux[demux_index].ca_fd=camfd;
490
491 for (i=0;i<demux[demux_index].STREAMpidcount;i++)
492 {
493 ca_pid_t ca_pid2;
494 memset(&ca_pid2,0,sizeof(ca_pid2));
495 ca_pid2.pid = demux[demux_index].STREAMpids[i];
496 ca_pid2.index = -1;
497 if (ioctl(camfd, CA_SET_PID, &ca_pid2)==-1)
498 cs_debug("dvbapi: Error unset Stream SET_PID");
499
500 memset(&ca_pid2,0,sizeof(ca_pid2));
501 ca_pid2.pid = demux[demux_index].STREAMpids[i];
502 ca_pid2.index = demux_index;
503 if (ioctl(camfd, CA_SET_PID, &ca_pid2)==-1)
504 cs_debug("dvbapi: Error Stream SET_PID");
505 }
506
507}
508
509void dvbapi_try_descrambling (int demux_index)
510{
511 int n;
512 unsigned int program_number;
513
514 program_number=demux[demux_index].program_number;
515 for (n=0; n<demux[demux_index].ECMpidcount; n++) {
516
517 if (demux[demux_index].ca_system_id!=0) // got valid cw -> stop trying
518 break;
519
520 if (program_number!=demux[demux_index].program_number) //channel change -> stop trying
521 break;
522
523 dvbapi_stop_filter(demux_index,0);
524 dvbapi_stop_filter(demux_index,1);
525
526 cs_debug("dvbapi: trying CA_System_ID: %04x CA_PID: %04x EEM_PID: %04x", demux[demux_index].ECMpids[n].CA_System_ID, demux[demux_index].ECMpids[n].CA_PID, demux[demux_index].ECMpids[n].EMM_PID);
527
528 //grep emm provid
529 unsigned short provid=0;
530 if (cfg->dvbapi_au==1)
531 {
532 if (demux[demux_index].ECMpids[n].EMM_PID>0)
533 provid=dvbapi_get_provid(demux_index, demux[demux_index].ECMpids[n].EMM_PID);
534 }
535
536 //cs_log("Provider ID: %04x", provid);
537
538 //grep ecm
539 dvbapi_get_single_ecm(demux_index, demux[demux_index].ECMpids[n].CA_System_ID, demux[demux_index].ECMpids[n].CA_PID, provid);
540
541 sleep(3); //try next if no cw for .. secs
542 }
543}
544
545void *thread_descrambling(void *di)
546{
547 int demux_index=(int*)di;
548 int dmx1_fd,dmx2_fd,n=30,k=0;
549 unsigned int program_number;
550
551 cs_log("dvbapi: Start descrambling Thread %d", demux_index);
552
553 dmx1_fd = dvbapi_open_device(demux_index,0); //ECM,CAT
554 dmx2_fd = dvbapi_open_device(demux_index,0); //EMM
555
556 demux[demux_index].demux_ecm_fd=dmx1_fd;
557 demux[demux_index].demux_emm_fd=dmx2_fd;
558
559 dvbapi_parse_cat(demux_index);
560
561 program_number=demux[demux_index].program_number;
562
563 while(1)
564 {
565 if (demux[demux_index].ca_system_id!=0) // got valid cw -> stop trying
566 break;
567
568 if (program_number!=demux[demux_index].program_number) //channel change -> new thread
569 return 0;
570
571 if (n>=30)
572 {
573 if (demux[demux_index].ca_system_id==0)
574 dvbapi_try_descrambling(demux_index);
575 n=0;
576 k++;
577 continue;
578 }
579 n++;
580
581 if (k==5) // give up
582 return 0;
583
584 sleep(10);
585 }
586
587
588 struct pollfd pfd2[MAX_DEMUX*2];
589 int rc,len,i,pfdcount;
590 unsigned char buffer[BUFSIZE];
591
592 while(1)
593 {
594
595 pfdcount=0;
596
597 if (program_number!=demux[demux_index].program_number || demux[demux_index].ca_system_id==0) //channel change -> new thread
598 break;
599
600 if (demux[demux_index].demux_ecm_fd>0) {
601 pfd2[pfdcount].fd = demux[demux_index].demux_ecm_fd;
602 pfd2[pfdcount].events = (POLLIN | POLLPRI);
603 pfdcount++;
604 } else break;
605 if (demux[demux_index].demux_emm_fd>0) {
606 pfd2[pfdcount].fd = demux[demux_index].demux_emm_fd;
607 pfd2[pfdcount].events = (POLLIN | POLLPRI);
608 pfdcount++;
609 } else break;
610
611
612 rc=poll(pfd2, pfdcount, 1000);
613
614 for (i = 0; i < pfdcount; i++) {
615 if (pfd2[i].revents & (POLLIN | POLLPRI)) {
616
617 if ((len=dvbapi_read_device(pfd2[i].fd, buffer, BUFSIZE, 0)) <= 0)
618 continue;
619
620 if (pfd2[i].fd==demux[demux_index].demux_ecm_fd) {
621 //ECM
622
623 if (len != (((buffer[1] & 0xf) << 8) | buffer[2]) + 3) //invaild CAT length
624 continue;
625
626 if (buffer[0] == 0x80 || buffer[0] == 0x81)
627 {
628 if (memcmp(buffer, demux[demux_index].buffer_cache_dmx, 12) != 0) {
629 memcpy(demux[demux_index].buffer_cache_dmx, buffer, 12);
630 cs_debug("Read %d bytes\tTable-id: %02x\tCA section length: %d", len, buffer[0], len);
631
632 if (len>0) {
633 ECM_REQUEST *er;
634
635 if (!(er=get_ecmtask()))
636 continue;
637
638 er->srvid = demux[demux_index].program_number;
639 er->caid = demux[demux_index].ca_system_id;
640 er->prid = demux[demux_index].provider_id;
641
642 er->l=len;
643 memcpy(er->ecm, buffer, er->l);
644
645 get_cw(er);
646 }
647 }
648 }
649 }
650 if (pfd2[i].fd==demux[demux_index].demux_emm_fd) {
651 //EMM
652
653 if (cfg->dvbapi_au!=1)
654 continue;
655
656 cs_debug("EMM Type: 0x%02x", buffer[0]);
657
658 cs_ddump(buffer, len, "emm:");
659
660 //force emm output
661 reader[ridx].logemm=9999;
662
663 memset(&epg, 0, sizeof(epg));
664
665 epg.caid[0] = (uchar)(demux[demux_index].ca_system_id>>8);
666 epg.caid[1] = (uchar)(demux[demux_index].ca_system_id);
667
668 epg.provid[2] = (uchar)(demux[demux_index].provider_id>>8);
669 epg.provid[3] = (uchar)(demux[demux_index].provider_id);
670
671 epg.l=len;
672 memcpy(epg.emm, buffer, epg.l);
673 memcpy(epg.hexserial, reader[client[cs_idx].au].hexserial, 8);
674
675 do_emm(&epg);
676 }
677 }
678 }
679 }
680
681 cs_log("dvbapi: Stop descrambling Thread %d", demux_index);
682
683 return 0;
684}
685
686int dvbapi_check_array(unsigned short *array, int len, unsigned short match)
687{
688 int i;
689 for (i=0; i<len; i++) {
690 if (array[i]==match) {
691 return 1;
692 }
693 }
694 return 0;
695}
696
697void dvbapi_resort_ecmpids(int demux_index)
698{
699 ECMPIDSTYPE tmppids[ECM_PIDS];
700 ECMPIDSTYPE tmppids2[ECM_PIDS];
701
702 int tmppidcount=0,tmppid2count=0,n;
703
704 int i,k,j;
705
706 for (i=0;i<MAX_CAID;i++)
707 global_caid_list[i]=0;
708
709 k=0;
710 for (i=0;i<CS_MAXREADER;i++) {
711 for (j=0;j<16;j++) {
712 if (reader[i].caid[j] != 0) {
713 if (k+1>=MAX_CAID) break;
714 global_caid_list[k]=reader[i].caid[j];
715 k++;
716
717 }
718 }
719 }
720 for (n=0; n<demux[demux_index].ECMpidcount; n++) {
721 if (dvbapi_check_array(ignoretab, TAB_SIZE, demux[demux_index].ECMpids[n].CA_System_ID)) {
722 cs_debug("-> ignore %04x", demux[demux_index].ECMpids[n].CA_System_ID);
723 } else if (dvbapi_check_array(global_caid_list, MAX_CAID, demux[demux_index].ECMpids[n].CA_System_ID)) {
724 cs_debug("-> caid list %04x", demux[demux_index].ECMpids[n].CA_System_ID);
725 tmppids[tmppidcount]=demux[demux_index].ECMpids[n];
726 tmppidcount++;
727 } else if (dvbapi_check_array(prioritytab, TAB_SIZE, demux[demux_index].ECMpids[n].CA_System_ID)) {
728 cs_debug("-> priority %04x", demux[demux_index].ECMpids[n].CA_System_ID);
729 tmppids[tmppidcount]=demux[demux_index].ECMpids[n];
730 tmppidcount++;
731 } else {
732 tmppids2[tmppid2count]=demux[demux_index].ECMpids[n];
733 tmppid2count++;
734 }
735 }
736
737 for (n=0;n<tmppid2count;n++) {
738 tmppids[tmppidcount]=tmppids2[n];
739 tmppidcount++;
740 }
741
742 for (n=0; n<tmppidcount; n++) {
743 demux[demux_index].ECMpids[n]=tmppids[n];
744 }
745
746 demux[demux_index].ECMpidcount=tmppidcount;
747 cs_debug("dvbapi: ECMpidscount is now %d", demux[demux_index].ECMpidcount);
748
749 return;
750}
751
752// from tuxbox camd
753int dvbapi_parse_capmt(unsigned char *buffer, unsigned int length)
754{
755 int i, j, u, n, added;
756 int ca_mask=0x01, demux_index2=0x00;
757
758 int ca_pmt_list_management = buffer[0];
759 unsigned int program_number = (buffer[1] << 8) | buffer[2];
760 int program_info_length = ((buffer[4] & 0x0F) << 8) | buffer[5];
761
762 switch (ca_pmt_list_management)
763 {
764 case 0x01:
765 //(first)
766 break;
767 case 0x03:
768 //default (only)
769 break;
770 case 0x04:
771 //(add)
772 break;
773 default:
774 //FIXME?? (unknown)
775 break;
776 }
777
778 if (buffer[17]==0x82 && buffer[18]==0x02) {
779 //enigma2
780 ca_mask = buffer[19];
781 demux_index2 = buffer[20];
782 } else {
783 //neutrino workaround
784 dvbapi_stop_descrambling_all(0);
785 }
786
787 for (i=0;i<MAX_DEMUX;i++) {
788 if (demux[i].demux_index==demux_index2) {
789 if (demux[i].program_number==((buffer[1] << 8) | buffer[2])) { // already descrambling prog on this device
790 if (demux[i].active==1) {
791 //remove any inactive program
792 for (u=0;u<MAX_DEMUX;u++) {
793 if (demux[u].demux_index==demux_index2 && demux[u].active==0)
794 dvbapi_stop_descrambling(u);
795 demux[u].active=0;
796 }
797
798 } else
799 demux[i].active=1;
800 return 0;
801 }
802 }
803 }
804
805 //get free id
806 int demux_id=-1;
807 for (i=0;i<MAX_DEMUX;i++) {
808 if (demux[i].program_number==0)
809 {
810 demux_id=i;
811 break;
812 }
813 }
814
815 if (demux_id<0) {
816 cs_log("dvbapi: error no free id (MAX_DEMUX)");
817 return 0;
818 }
819
820 cs_ddump(buffer, length, "capmt:");
821 cs_log("dvbapi: new program number: %04x", program_number);
822 //cs_debug("program_info_length: %d", program_info_length);
823
824 demux[demux_id].program_number=((buffer[1] << 8) | buffer[2]);
825 demux[demux_id].demux_index=demux_index2;
826 demux[demux_id].ECMpidcount=0;
827 demux[demux_id].STREAMpidcount=0;
828 demux[demux_id].active=1;
829 demux[demux_id].cadev_index=demux_index2;
830
831 for (i=0;i<8;i++) {
832 if (ca_mask & (1 << i)) {
833 demux[demux_id].cadev_index=i;
834 break;
835 }
836 }
837
838 cs_debug("dvbapi: demux index: %d ca index: %d", demux[demux_id].demux_index, demux[demux_id].cadev_index);
839
840 //CA_PIDS for all streams
841 if (program_info_length != 0)
842 {
843 int ca_pmt_cmd_id = buffer[6];
844 cs_debug("ca_pmt_id: %02x", ca_pmt_cmd_id);
845 int descriptor_length=0;
846 for (i = 0; i < program_info_length - 1; i += descriptor_length + 2)
847 {
848 descriptor_length = buffer[i + 8];
849 int ca_system_id = (buffer[i + 9] << 8) | buffer[i + 10];
850 int ca_pid = ((buffer[i + 11] & 0x1F) << 8)| buffer[i + 12];
851
852 cs_debug("typ: %02x ca_system_id: %04x\t ca_pid: %04x\tca_descriptor_length %d", buffer[i + 7], ca_system_id, ca_pid, descriptor_length);
853
854 if (buffer[i + 7] == 0x09) {
855 demux[demux_id].ECMpids[demux[demux_id].ECMpidcount].CA_PID=ca_pid;
856 demux[demux_id].ECMpids[demux[demux_id].ECMpidcount].CA_System_ID=ca_system_id;
857 demux[demux_id].ECMpids[demux[demux_id].ECMpidcount].EMM_PID=0;
858 demux[demux_id].ECMpidcount++;
859 }
860 }
861 }
862
863 //CA_PIDs for a single stream
864 unsigned int es_info_length=0;
865 for (i = program_info_length + 6; i < length; i += es_info_length + 5)
866 {
867 int stream_type = buffer[i];
868 unsigned short elementary_pid = ((buffer[i + 1] & 0x1F) << 8) | buffer[i + 2];
869 es_info_length = ((buffer[i + 3] & 0x0F) << 8) | buffer[i + 4];
870
871 cs_debug("stream_type: %02x\telementary_pid: %04x\tes_info_length: %04x", stream_type, elementary_pid, es_info_length);
872
873 demux[demux_id].STREAMpids[demux[demux_id].STREAMpidcount]=elementary_pid;
874 demux[demux_id].STREAMpidcount++;
875
876 if (es_info_length != 0)
877 {
878 int ca_pmt_cmd_id = buffer[i + 5];
879 cs_debug("dvbapi: ca_pmt_cmd_id 0x%02x", ca_pmt_cmd_id);
880 unsigned int descriptor_length=0;
881 for (j = 0; j < es_info_length - 1; j += descriptor_length + 2)
882 {
883 descriptor_length = buffer[i + j + 7];
884 int descriptor_ca_system_id = (buffer[i + j + 8] << 8) | buffer[i + j + 9];
885 int descriptor_ca_pid = ((buffer[i + j + 10] & 0x1F) << 8) | buffer[i + j + 11];
886
887 cs_debug("typ: %02x\tca_system_id: %04x\t ca_pid: %04x", buffer[i + j + 6], descriptor_ca_system_id, descriptor_ca_pid);
888
889 if (buffer[i + j + 6] == 0x09) {
890 added=0;
891 for (n=0;n<demux[demux_id].ECMpidcount;n++) {
892 if (demux[demux_id].ECMpids[n].CA_System_ID==descriptor_ca_system_id)
893 added=1;
894 }
895 if (added==0) {
896 demux[demux_id].ECMpids[demux[demux_id].ECMpidcount].CA_PID=descriptor_ca_pid;
897 demux[demux_id].ECMpids[demux[demux_id].ECMpidcount].CA_System_ID=descriptor_ca_system_id;
898 demux[demux_id].ECMpids[demux[demux_id].ECMpidcount].EMM_PID=0;
899 demux[demux_id].ECMpidcount++;
900 }
901 }
902 }
903 }
904 }
905
906 pthread_t p3;
907
908 cs_log("dvbapi: Found %d ECMpids in PMT", demux[demux_id].ECMpidcount);
909 cs_debug("dvbapi: Found %d STREAMpids in PMT", demux[demux_id].STREAMpidcount);
910
911 if (demux[demux_id].ECMpidcount>0) {
912 dvbapi_resort_ecmpids(demux_id);
913 if (demux[demux_id].ECMpidcount>0)
914 pthread_create (&p3, NULL, thread_descrambling, (void *)demux_id);
915 }
916
917
918 return 0;
919}
920
921
922void dvbapi_handlesockmsg (unsigned char *buffer, ssize_t len)
923{
924 unsigned int val, size, i;
925
926 //cs_dump(buffer, len, "handlesockmsg:");
927
928 if (buffer[0] != 0x9F || buffer[1] != 0x80) {
929 cs_log("dvbapi: unknown socket command: %02x", buffer[0]);
930 return;
931 }
932
933 if (buffer[3] & 0x80) {
934 val = 0;
935 size = buffer[3] & 0x7F;
936 for (i = 0; i < size; i++)
937 val = (val << 8) | buffer[i + 1 + 3];
938 size++;
939 } else
940 {
941 val = buffer[3] & 0x7F;
942 size = 1;
943 }
944
945 switch(buffer[2])
946 {
947 case 0x30:
948 cs_debug("ca_info!!");
949 break;
950 case 0x32:
951 if ((3 + size + val) == len)
952 dvbapi_parse_capmt(buffer + 3 + size, val);
953 else {
954 cs_log("dvbapi: ca_pmt invalid length");
955 cs_dump(buffer, len, "invalid length:");
956 }
957 break;
958 case 0x3f:
959 //9F 80 3f 04 83 02 00 <demux index>
960 cs_ddump(buffer, len, "capmt 3f:");
961 int demux_index=buffer[7];
962 dvbapi_stop_descrambling_all(demux_index);
963 break;
964 default:
965 cs_log("dvbapi: handlesockmsg() unknown command");
966 cs_dump(buffer, len, "unknown command:");
967 break;
968 }
969}
970
971int dvbapi_init_listenfd() {
972
973 int clilen;
974 struct sockaddr_un servaddr;
975
976 memset(&servaddr, 0, sizeof(struct sockaddr_un));
977 servaddr.sun_family = AF_UNIX;
978 strcpy(servaddr.sun_path, devices[selected_box].cam_socket_path);
979 clilen = sizeof(servaddr.sun_family) + strlen(servaddr.sun_path);
980
981 if ((unlink(devices[selected_box].cam_socket_path) < 0) && (errno != ENOENT))
982 return 0;
983 if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
984 return 0;
985 if (bind(listenfd, (struct sockaddr *) &servaddr, clilen) < 0)
986 return 0;
987 if (listen(listenfd, 5) < 0)
988 return 0;
989
990 return 1;
991}
992
993void *thread_check_zap(void *arg) {
994 unsigned char buffer[BUFSIZE];
995 struct sockaddr_un servaddr;
996 ssize_t len;
997 int connfd,clilen;
998
999 while(1)
1000 {
1001 sleep(1); // check every second
1002 //cs_debug("dvbapi: check zap");
1003
1004 connfd = accept(listenfd, (struct sockaddr *)&servaddr, (socklen_t *)&clilen);
1005
1006 if (connfd <= 0) { //socket not available
1007 cs_debug("dvbapi: socket not available");
1008 break;
1009 }
1010
1011 len = read(connfd, buffer, sizeof(buffer));
1012
1013 if (len < 3) {
1014 cs_debug("dvbapi: camd.socket: too short message received");
1015 continue;
1016 }
1017
1018 // if message begins with an apdu_tag and is longer than three bytes
1019
1020 if ((buffer[0] == 0x9F) && ((buffer[1] >> 7) == 0x01) && ((buffer[2] >> 7) == 0x00)) {
1021 dvbapi_handlesockmsg(buffer, len);
1022 } else {
1023 cs_debug("dvbapi: invaild capmt");
1024 }
1025
1026 close(connfd);
1027
1028 }
1029
1030 cs_log("dvbapi: check_zap() aborted");
1031 return 0;
1032}
1033
1034void dvbapi_cleanup(int sig_num)
1035{
1036 /* cleanup */
1037 if (strcmp(cfg->dvbapi_boxtype, "ufs910")==0) {
1038 //prevent ufs910 from crashing when old cw set
1039 dvbapi_stop_descrambling_all(0);
1040 dvbapi_stop_descrambling_all(1);
1041 }
1042
1043 exit(0);
1044}
1045
1046int dvbapi_main_local()
1047{
1048 struct pollfd pfd2[1];
1049 int i,rc;
1050 pthread_t p1;
1051
1052 signal(SIGTERM, dvbapi_cleanup);
1053 signal(SIGINT, dvbapi_cleanup);
1054
1055 if (cfg->dvbapi_usr[0]==0) {
1056 //
1057 }
1058
1059 if (cfg->dvbapi_boxtype[0]==0) {
1060 strncpy(cfg->dvbapi_boxtype, "dreambox", sizeof(cfg->dvbapi_boxtype)-1);
1061 cs_log("dvbapi: boxtype not set. Assume boxtype=%s.", cfg->dvbapi_boxtype);
1062 } else
1063 cs_log("dvbapi: boxtype=%s.", cfg->dvbapi_boxtype);
1064
1065 for (i=0;i<MAX_DEMUX;i++)
1066 {
1067 demux[i].program_number=0;
1068 demux[i].demux_ecm_fd=0;
1069 demux[i].demux_emm_fd=0;
1070 demux[i].ca_system_id=0;
1071 demux[i].ca_pid=0;
1072 demux[i].emm_pid=0;
1073 demux[i].cadev_index=-1;
1074 demux[i].ca_fd=0;
1075 demux[i].demux_index=-1;
1076
1077 memset(demux[i].buffer_cache_dmx,0 ,12);
1078 }
1079
1080 dvbapi_detect_api();
1081
1082 if (selected_box == -1 || selected_api==-1) {
1083 cs_log("dvbapi: could not detect api version");
1084 return 1;
1085 }
1086
1087 if (!dvbapi_init_listenfd())
1088 {
1089 cs_log("dvbapi: could not init camd.socket.");
1090 return 1;
1091 }
1092
1093 char *ptr1, *ptr3;
1094 //priority
1095 for (i=0, ptr1=strtok(cfg->dvbapi_priority, ","); (i<20) && (ptr1); ptr1=strtok(NULL, ","))
1096 {
1097 unsigned long caid, prov;
1098 if( (ptr3=strchr(trim(ptr1), ':')) )
1099 *ptr3++='\0';
1100 else
1101 ptr3="";
1102
1103 if (((caid=a2i(ptr1, 2))|(prov=a2i(ptr3, 3))) < 0x10000)
1104 {
1105 prioritytab[i]=caid;
1106 i++;
1107 }
1108 }
1109 //ignore
1110 for (i=0, ptr1=strtok(cfg->dvbapi_ignore, ","); (i<20) && (ptr1); ptr1=strtok(NULL, ","))
1111 {
1112 unsigned long caid, prov;
1113 if( (ptr3=strchr(trim(ptr1), ':')) )
1114 *ptr3++='\0';
1115 else
1116 ptr3="";
1117
1118 if (((caid=a2i(ptr1, 2))|(prov=a2i(ptr3, 3))) < 0x10000)
1119 {
1120 ignoretab[i]=caid;
1121 i++;
1122 }
1123 }
1124
1125 pfd2[0].fd = fd_m2c;
1126 pfd2[0].events = (POLLIN | POLLPRI);
1127
1128 pthread_create (&p1, NULL, thread_check_zap, NULL);
1129
1130 struct timeb tp;
1131 cs_ftime(&tp);
1132 tp.time+=500;
1133
1134 while (1) {
1135 if (master_pid!=getppid())
1136 cs_exit(0);
1137
1138
1139 chk_pending(tp);
1140
1141 rc=poll(pfd2, 1, 1000);
1142
1143 if (rc<0)
1144 break;
1145
1146 if (pfd2[0].revents & (POLLIN | POLLPRI)) {
1147 chk_dcw(fd_m2c);
1148
1149 }
1150
1151 }
1152 return 0;
1153}
1154
1155
1156void dvbapi_send_dcw(ECM_REQUEST *er)
1157{
1158 unsigned char cw_0[8], cw_1[8];
1159 int i;
1160
1161 cs_debug("dvbapi: ECM rc: %d", er->rc);
1162
1163 memcpy(cw_0, er->cw, 8);
1164 memcpy(cw_1, er->cw+8, 8);
1165
1166 for (i=0;i<MAX_DEMUX;i++)
1167 {
1168 if (demux[i].program_number==er->srvid)
1169 {
1170
1171 if (er->rc<=2 && demux[i].ca_system_id==0 && er->caid!=0) {
1172 dvbapi_start_descrambling(i, er->caid, er->pid, er->prid);
1173 }
1174
1175 if (er->rc>3) {
1176 cs_debug("dvbapi: cw not found");
1177 return;
1178 }
1179
1180 ca_descr_t ca_descr;
1181 memset(&ca_descr,0,sizeof(ca_descr));
1182
1183 if (demux[i].ca_fd<=0)
1184 {
1185 cs_log("dvbapi: could not write cw.");
1186 return;
1187 }
1188
1189 if (memcmp(cw_0,demux[i].lastcw0,8))
1190 {
1191 ca_descr.index = i;
1192 ca_descr.parity = 0;
1193 memcpy(demux[i].lastcw0,cw_0,8);
1194 memcpy(ca_descr.cw,cw_0,8);
1195 cs_debug("dvbapi: write cw1 index: %d", i);
1196 if (ioctl(demux[i].ca_fd, CA_SET_DESCR, &ca_descr) < 0)
1197 cs_debug("dvbapi: Error CA_SET_DESCR");
1198 }
1199
1200 if (memcmp(cw_1,demux[i].lastcw1,8))
1201 {
1202 ca_descr.index = i;
1203 ca_descr.parity = 1;
1204 memcpy(demux[i].lastcw1,cw_1,8);
1205 memcpy(ca_descr.cw,cw_1,8);
1206 cs_debug("dvbapi: write cw2 index: %d", i);
1207 if (ioctl(demux[i].ca_fd, CA_SET_DESCR, &ca_descr) < 0)
1208 cs_debug("dvbapi: Error CA_SET_DESCR");
1209 }
1210 }
1211 }
1212}
1213
1214static void dvbapi_handler(int idx)
1215{
1216 static struct s_auth *account=0;
1217
1218 if (cfg->dvbapi_enabled != 1) {
1219 cs_log("dvbapi disabled");
1220 return;
1221 }
1222
1223 //cs_log("dvbapi loaded fd=%d", idx);
1224
1225 switch(cs_fork(0, idx))
1226 {
1227 case 0: //master
1228 case -1:
1229 return;
1230 default:
1231 wait4master();
1232 }
1233
1234 int ok=0;
1235
1236 if( !account )
1237 {
1238 client[cs_idx].usr[0]=0;
1239 for (ok=0, account=cfg->account; (account) && (!ok); account=account->next)
1240 if( (ok=!strcmp(cfg->dvbapi_usr, account->usr)) )
1241 break;
1242 }
1243
1244 cs_auth_client(ok ? account : (struct s_auth *)(-1), "unknown");
1245
1246 dvbapi_main_local();
1247
1248 cs_log("Module dvbapi error");
1249 cs_exit(0);
1250
1251 return;
1252}
1253
1254
1255
1256/*
1257 * protocol structure
1258 */
1259
1260void module_dvbapi(struct s_module *ph)
1261{
1262 strcpy(ph->desc, "dvbapi");
1263 ph->type=MOD_CONN_SERIAL;
1264 ph->multi=1;
1265 ph->watchdog=0;
1266 ph->s_handler=dvbapi_handler;
1267 ph->send_dcw=dvbapi_send_dcw;
1268}
1269#endif // HAVE_DVBAPI
Note: See TracBrowser for help on using the repository browser.