source: trunk/module-dvbapi.c@ 3172

Last change on this file since 3172 was 3172, checked in by _network, 10 years ago

remove global mbuf

File size: 49.3 KB
Line 
1#include "globals.h"
2
3#ifdef HAVE_DVBAPI
4
5#include "module-dvbapi.h"
6
7#ifdef AZBOX
8#include "openxcas/openxcas_api.h"
9#include "openxcas/openxcas_message.h"
10
11int openxcas_provid, openxcas_seq, openxcas_filter_idx, openxcas_stream_id, openxcas_cipher_idx, openxcas_busy;
12unsigned char openxcas_cw[16];
13unsigned short openxcas_sid, openxcas_caid, openxcas_ecm_pid, openxcas_video_pid, openxcas_audio_pid, openxcas_data_pid;
14
15void azbox_openxcas_ecm_callback(int stream_id, unsigned int sequence, int cipher_index, unsigned int caid, unsigned char *ecm_data, int l, unsigned short pid);
16void azbox_openxcas_ex_callback(int stream_id, unsigned int seq, int idx, unsigned int pid, unsigned char *ecm_data, int l);
17void azbox_send_dcw(ECM_REQUEST *er);
18void azbox_main();
19#endif
20
21extern struct s_reader * reader;
22
23const char *boxdesc[] = { "none", "dreambox", "duckbox", "ufs910", "dbox2", "ipbox", "ipbox-pmt", "dm7000" };
24
25const struct box_devices devices[BOX_COUNT] = {
26 /* QboxHD (dvb-api-3)*/ { "/tmp/virtual_adapter/ca%d", "/tmp/virtual_adapter/demux%d", "/tmp/camd.socket" },
27 /* dreambox (dvb-api-3)*/ { "/dev/dvb/adapter0/ca%d", "/dev/dvb/adapter0/demux%d", "/tmp/camd.socket" },
28 /* dreambox (dvb-api-1)*/ { "/dev/dvb/card0/ca%d", "/dev/dvb/card0/demux%d", "/tmp/camd.socket" },
29 /* sh4 (stapi)*/ { "/dev/stapi/stpti4_ioctl", "/dev/stapi/stpti4_ioctl", "/tmp/camd.socket" }
30};
31
32int selected_box=-1;
33int selected_api=-1;
34int disable_pmt_files=0;
35int dir_fd=-1, pausecam=0;
36unsigned short global_caid_list[MAX_CAID];
37DEMUXTYPE demux[MAX_DEMUX];
38int ca_fd[8];
39
40int dvbapi_set_filter(int demux_id, int api, unsigned short pid, uchar *filt, uchar *mask, int timeout, int pidindex, int count, int type) {
41#ifdef AZBOX
42 openxcas_caid = demux[demux_id].ECMpids[pidindex].CAID;
43 openxcas_ecm_pid = pid;
44
45 return 1;
46#endif
47 int ret=-1,n=-1,i;
48
49 for (i=0; i<MAX_FILTER && demux[demux_id].demux_fd[i].fd>0; i++);
50
51 if (i>=MAX_FILTER) {
52 cs_log("no free filter");
53 return -1;
54 }
55 n=i;
56
57 demux[demux_id].demux_fd[n].pidindex = pidindex;
58 demux[demux_id].demux_fd[n].pid = pid;
59 demux[demux_id].demux_fd[n].type = type;
60 demux[demux_id].demux_fd[n].count = count;
61
62 switch(api) {
63 case DVBAPI_3:
64 demux[demux_id].demux_fd[n].fd = dvbapi_open_device(0, demux[demux_id].demux_index);
65 struct dmx_sct_filter_params sFP2;
66
67 memset(&sFP2,0,sizeof(sFP2));
68
69 sFP2.pid = pid;
70 sFP2.timeout = timeout;
71 sFP2.flags = DMX_IMMEDIATE_START;
72 memcpy(sFP2.filter.filter,filt,16);
73 memcpy(sFP2.filter.mask,mask,16);
74 ret=ioctl(demux[demux_id].demux_fd[n].fd, DMX_SET_FILTER, &sFP2);
75
76 break;
77 case DVBAPI_1:
78 demux[demux_id].demux_fd[n].fd = dvbapi_open_device(0, demux[demux_id].demux_index);
79 struct dmxSctFilterParams sFP1;
80
81 memset(&sFP1,0,sizeof(sFP1));
82
83 sFP1.pid = pid;
84 sFP1.timeout = timeout;
85 sFP1.flags = DMX_IMMEDIATE_START;
86 memcpy(sFP1.filter.filter,filt,16);
87 memcpy(sFP1.filter.mask,mask,16);
88 ret=ioctl(demux[demux_id].demux_fd[n].fd, DMX_SET_FILTER1, &sFP1);
89
90 break;
91#ifdef WITH_STAPI
92 case STAPI:
93 demux[demux_id].demux_fd[n].fd = 1;
94 ret=stapi_set_filter(demux_id, pid, filt, mask, n);
95
96 break;
97#endif
98 default:
99 break;
100 }
101
102 if (ret < 0)
103 cs_debug("could not start demux filter (Errno: %d)", errno);
104
105 return ret;
106}
107
108int dvbapi_check_array(unsigned short *array, int len, unsigned short match) {
109 int i;
110 for (i=0; i<len; i++) {
111 if (array[i]==match) {
112 return i;
113 }
114 }
115 return -1;
116}
117
118int dvbapi_detect_api() {
119 int num_apis=2, i,devnum=-1, dmx_fd=0, ret=-1;
120 uchar filter[32];
121 char device_path[128];
122
123 for (i=0;i<BOX_COUNT;i++) {
124 sprintf(device_path, devices[i].demux_device_path, 0);
125 if ((dmx_fd = open(device_path, O_RDWR)) > 0) {
126 devnum=i;
127 break;
128 }
129 }
130
131 if (dmx_fd < 0) return 0;
132 close(dmx_fd);
133 selected_box = devnum;
134
135#ifdef WITH_STAPI
136 if (devnum==3) {
137 if (stapi_open()==FALSE) {
138 cs_log("stapi: setting up stapi failed.");
139 return 0;
140 }
141
142 selected_api=STAPI;
143 selected_box=3;
144 close(dmx_fd);
145 return 1;
146 }
147#endif
148 memset(filter,0,32);
149
150 filter[0]=0x01;
151 filter[16]=0xFF;
152
153 for (i=0;i<num_apis;i++) {
154 ret = dvbapi_set_filter(0, i, 0x0001, filter, filter+16, 1, 0, 0, TYPE_ECM);
155
156 if (ret >= 0) {
157 selected_api=i;
158 dvbapi_stop_filter(0, TYPE_ECM);
159 break;
160 }
161 }
162
163 if (ret < 0) return 0;
164
165 cs_debug("Detected %s Api: %d", device_path, selected_api);
166
167 return 1;
168}
169
170int dvbapi_read_device(int dmx_fd, unsigned char *buf, int length) {
171 int len, rc;
172 struct pollfd pfd[1];
173
174 pfd[0].fd = dmx_fd;
175 pfd[0].events = (POLLIN | POLLPRI);
176
177 rc = poll(pfd, 1, 7000);
178 if (rc<1) {
179 cs_log("read on %d timed out", dmx_fd);
180 return -1;
181 }
182
183 len = read(dmx_fd, buf, length);
184
185 if (len==-1)
186 cs_log("read error %d on fd %d", errno, dmx_fd);
187
188 return len;
189}
190
191int dvbapi_open_device(int type, int num) {
192 int dmx_fd;
193 int ca_offset=0;
194 char device_path[128];
195
196 if (type==0)
197 sprintf(device_path, devices[selected_box].demux_device_path, num);
198 else {
199 if (cfg->dvbapi_boxtype==BOXTYPE_DUCKBOX || cfg->dvbapi_boxtype==BOXTYPE_DBOX2 || cfg->dvbapi_boxtype==BOXTYPE_UFS910)
200 ca_offset=1;
201
202 sprintf(device_path, devices[selected_box].ca_device_path, num+ca_offset);
203 }
204
205 if ((dmx_fd = open(device_path, O_RDWR)) < 0) {
206 cs_debug("error opening device %s (Errno: %d)", device_path, errno);
207 return -1;
208 }
209
210 cs_debug("DEVICE open (%s) fd %d", device_path, dmx_fd);
211 return dmx_fd;
212}
213
214int dvbapi_stop_filter(int demux_index, int type) {
215 int g;
216
217 for (g=0;g<MAX_FILTER;g++) {
218 if (demux[demux_index].demux_fd[g].type==type) {
219 dvbapi_stop_filternum(demux_index, g);
220 }
221 }
222
223 return 1;
224}
225
226int dvbapi_stop_filternum(int demux_index, int num) {
227 int ret=-1;
228 if (demux[demux_index].demux_fd[num].fd>0) {
229#ifdef WITH_STAPI
230 ret=stapi_remove_filter(demux_index, num);
231#else
232 ret=ioctl(demux[demux_index].demux_fd[num].fd,DMX_STOP);
233 close(demux[demux_index].demux_fd[num].fd);
234#endif
235 demux[demux_index].demux_fd[num].fd=0;
236 }
237 return ret;
238}
239
240void dvbapi_start_filter(int demux_id, int pidindex, unsigned short pid, uchar table, uchar mask, int timeout, int type) {
241 uchar filter[32];
242
243 cs_debug("set filter pid: %04x", pid);
244
245 memset(filter,0,32);
246
247 filter[0]=table;
248 filter[16]=mask;
249
250 dvbapi_set_filter(demux_id, selected_api, pid, filter, filter+16, timeout, pidindex, 0, type);
251}
252
253void dvbapi_start_emm_filter(int demux_index) {
254 int j;
255 uchar nullserial[8];
256 char *typtext[]={"UNKNOWN", "UNIQUE", "SHARED", "GLOBAL"};
257
258 if (demux[demux_index].pidindex==-1) return;
259
260 if (demux[demux_index].ECMpids[demux[demux_index].pidindex].EMM_PID==0 || !demux[demux_index].rdr)
261 return;
262
263 memset(nullserial,0,8);
264
265 if (!memcmp(demux[demux_index].rdr->hexserial, nullserial, 8)) {
266 //cs_debug("hexserial not set %s", cs_hexdump(1, demux[demux_index].rdr->hexserial, 8));
267 return;
268 }
269
270 if (demux[demux_index].emm_filter==1 && !memcmp(demux[demux_index].rdr->hexserial, demux[demux_index].hexserial, 8)) {
271 return;
272 }
273
274 if (memcmp(demux[demux_index].rdr->hexserial, demux[demux_index].hexserial, 8)) {
275 dvbapi_stop_filter(demux_index, TYPE_EMM);
276 }
277
278 if (demux[demux_index].rdr->card_system==0)
279 demux[demux_index].rdr->card_system=get_cardsystem(demux[demux_index].ECMpids[demux[demux_index].pidindex].CAID);
280
281 uchar dmx_filter[256];
282 memset(dmx_filter, 0, sizeof(dmx_filter));
283
284 get_emm_filter(demux[demux_index].rdr, dmx_filter);
285
286 int filter_count=dmx_filter[1];
287
288 for (j=1;j<=filter_count && j < 8;j++) {
289 int startpos=2+(34*(j-1));
290
291 if (dmx_filter[startpos+1] != 0x00)
292 continue;
293
294 uchar filter[32];
295 memcpy(filter, dmx_filter+startpos+2, 32);
296 int emmtype=dmx_filter[startpos];
297 int count=dmx_filter[startpos+1];
298
299 cs_debug_mask(D_EMM, "dvbapi: starting emm filter %s, pid: 0x%04X", typtext[emmtype], demux[demux_index].ECMpids[demux[demux_index].pidindex].EMM_PID);
300 cs_ddump_mask(D_EMM, filter, 32, "demux filter:");
301 dvbapi_set_filter(demux_index, selected_api, demux[demux_index].ECMpids[demux[demux_index].pidindex].EMM_PID, filter, filter+16, 0, demux[demux_index].pidindex, count, TYPE_EMM);
302 }
303
304 memcpy(demux[demux_index].hexserial, demux[demux_index].rdr->hexserial, 8);
305 demux[demux_index].emm_filter=1;
306}
307
308void dvbapi_add_ecmpid(int demux_id, ushort caid, ushort ecmpid, ulong provid, int chid) {
309 int n,added=0;
310
311 if (demux[demux_id].ECMpidcount>=ECM_PIDS)
312 return;
313
314 for (n=0;n<demux[demux_id].ECMpidcount;n++) {
315 if (demux[demux_id].ECMpids[n].CAID == caid && demux[demux_id].ECMpids[n].ECM_PID == ecmpid && demux[demux_id].ECMpids[n].irdeto_chid == chid)
316 added=1;
317 }
318
319 if (added==0) {
320 demux[demux_id].ECMpids[demux[demux_id].ECMpidcount].ECM_PID = ecmpid;
321 demux[demux_id].ECMpids[demux[demux_id].ECMpidcount].CAID = caid;
322 demux[demux_id].ECMpids[demux[demux_id].ECMpidcount].PROVID = provid;
323 demux[demux_id].ECMpids[demux[demux_id].ECMpidcount].irdeto_chid = chid;
324 cs_log("[ADD PID %d] CAID: %04X\tECM_PID: %04X\tPROVID: %06X", demux[demux_id].ECMpidcount, caid, ecmpid, provid);
325 demux[demux_id].ECMpidcount++;
326 }
327}
328
329void dvbapi_add_emmpid(int demux_id, ushort caid, ushort emmpid, ulong provid) {
330 int j;
331 for (j=0;j<demux[demux_id].ECMpidcount;j++) {
332 if (demux[demux_id].ECMpids[j].CAID==caid && (demux[demux_id].ECMpids[j].PROVID == provid || provid == 0)) {
333 demux[demux_id].ECMpids[j].EMM_PID=emmpid;
334 cs_debug("[ADD EMMPID %d] CAID: %04X\tEMM_PID: %04X\tPROVID: %06X", j, caid, emmpid, provid);
335 }
336 }
337}
338
339void dvbapi_parse_cat(int demux_id, uchar *buf, int len) {
340 unsigned short i, k;
341
342 cs_ddump(buf, len, "cat:");
343
344 for (i = 8; i < (((buf[1] & 0x0F) << 8) | buf[2]) - 1; i += buf[i + 1] + 2) {
345 if (buf[i] != 0x09) continue;
346 unsigned short caid=(((buf[i + 2] & 0x1F) << 8) | buf[i + 3]);
347 unsigned short emm_pid=(((buf[i + 4] & 0x1F) << 8) | buf[i + 5]);
348 ulong emm_provider = 0;
349
350 switch (caid >> 8) {
351 case 0x01:
352 dvbapi_add_emmpid(demux_id, caid, emm_pid, 0);
353 cs_debug("[cat] CAID: %04x\tEMM_PID: %04x", caid, emm_pid);
354 for (k = i+7; k < i+buf[i+1]+2; k += 4) {
355 emm_provider = (buf[k+2] << 8| buf[k+3]);
356 emm_pid = (buf[k] & 0x0F) << 8 | buf[k+1];
357 cs_debug("[cat] CAID: %04X\tEMM_PID: %04X\tPROVID: %06X", caid, emm_pid, emm_provider);
358 dvbapi_add_emmpid(demux_id, caid, emm_pid, emm_provider);
359 }
360 break;
361 case 0x05:
362 for (k = i+6; k < i+buf[i+1]+2; k += buf[k+1]+2) {
363 if (buf[k]==0x14) {
364 emm_provider = buf[k+2] << 16 | (buf[k+3] << 8| (buf[k+4] & 0xF0));
365 cs_debug("[cat] CAID: %04x\tEMM_PID: %04x\tPROVID: %06X", caid, emm_pid, emm_provider);
366 dvbapi_add_emmpid(demux_id, caid, emm_pid, emm_provider);
367 }
368 }
369 break;
370 case 0x18:
371 emm_provider = (buf[i+1] == 0x07) ? (buf[i+6] << 16 | (buf[i+7] << 8| (buf[i+8]))) : 0;
372 cs_debug("[cat] CAID: %04x\tEMM_PID: %04x\tPROVID: %06X", caid, emm_pid, emm_provider);
373 dvbapi_add_emmpid(demux_id, caid, emm_pid, emm_provider);
374 break;
375 default:
376 cs_debug("[cat] CAID: %04x\tEMM_PID: %04x", caid, emm_pid);
377 dvbapi_add_emmpid(demux_id, caid, emm_pid, 0);
378 break;
379 }
380 }
381 return;
382}
383
384void dvbapi_set_pid(int demux_id, int num, int index) {
385 int i;
386 switch(selected_api) {
387#ifdef WITH_STAPI
388 case STAPI:
389 stapi_set_pid(demux_id,num,index);
390 break;
391#endif
392 default:
393 for (i=0;i<8;i++) {
394 if (demux[demux_id].ca_mask & (1 << i)) {
395 if (ca_fd[i]>0) {
396 ca_pid_t ca_pid2;
397 memset(&ca_pid2,0,sizeof(ca_pid2));
398 ca_pid2.pid = demux[demux_id].STREAMpids[num];
399 ca_pid2.index = index;
400 if (ioctl(ca_fd[i], CA_SET_PID, &ca_pid2)==-1)
401 cs_debug("Error Stream SET_PID");
402 }
403 }
404 }
405 break;
406 }
407 return;
408}
409
410void dvbapi_stop_descrambling(int demux_id) {
411 int i;
412
413 cs_debug("stop descrambling (demux_id: %d)", demux_id);
414
415 dvbapi_stop_filter(demux_id, TYPE_ECM);
416 dvbapi_stop_filter(demux_id, TYPE_EMM);
417
418 for (i=0;i<demux[demux_id].STREAMpidcount;i++) {
419 dvbapi_set_pid(demux_id, i, -1);
420 }
421
422 memset(&demux[demux_id], 0 ,sizeof(DEMUXTYPE));
423 demux[demux_id].pidindex=-1;
424
425 unlink(ECMINFO_FILE);
426
427 return;
428}
429
430void dvbapi_start_descrambling(int demux_id) {
431 int i;
432 cs_log("Start descrambling PID #%d (CAID: %04X)", demux[demux_id].curindex, demux[demux_id].ECMpids[demux[demux_id].curindex].CAID);
433
434 demux[demux_id].pidindex=demux[demux_id].curindex;
435
436 for (i=0;i<demux[demux_id].STREAMpidcount;i++)
437 dvbapi_set_pid(demux_id, i, demux_id);
438
439 if (cfg->dvbapi_au==1)
440 dvbapi_start_filter(demux_id, demux[demux_id].pidindex, 0x001, 0x01, 0xFF, 0, TYPE_EMM); //CAT
441}
442
443void dvbapi_process_emm (int demux_index, int filter_num, unsigned char *buffer, unsigned int len) {
444 EMM_PACKET epg;
445 static uchar emm_global[512];
446 static int emm_global_len = 0;
447 int pos, emm_len = 0, k;
448 uchar emmbuf[512];
449
450 if (demux[demux_index].pidindex==-1) return;
451
452 ulong provider = demux[demux_index].ECMpids[demux[demux_index].pidindex].PROVID;
453 ulong emm_provid;
454 switch (demux[demux_index].ECMpids[demux[demux_index].pidindex].CAID >> 8) {
455 case 0x05:
456 if (len>500) return;
457 switch(buffer[0]) {
458 case 0x88:
459 // emm-u
460 break;
461
462 case 0x8a:
463 case 0x8b:
464 // emm-g
465 return;
466 break;
467
468 case 0x8c:
469 case 0x8d:
470 // emm-s part 1
471 if (!memcmp(emm_global, buffer, len))
472 return;
473
474 if (buffer[3] == 0x90 && buffer[4] == 0x03) {
475 emm_provid = buffer[5] << 16 | buffer[6] << 8 | (buffer[7] & 0xFE);
476 } else {
477 return;
478 }
479
480 if (emm_provid!=provider)
481 return;
482
483 //cs_log("viaccess global emm_provid: %06X provid: %06X", emm_provid, provider);
484
485 // copy first part of the emm-s
486 memcpy(emm_global, buffer, len);
487 emm_global_len=len;
488 //cs_ddump(buffer, len, "viaccess global emm:");
489 return;
490
491 case 0x8e:
492 // emm-s part 2
493 if (!emm_global_len) return;
494
495 if (buffer[6]!=0x00) return;
496
497 memcpy(emmbuf, buffer, 7);
498 pos=7;
499
500 for (k=3; k<emm_global[2]+2 && k<emm_global_len; k += emm_global[k+1]+2) {
501 if (emm_global[k]!=0x90) continue;
502 memcpy(emmbuf+pos, emm_global+k, emm_global[k+1]+2);
503 pos += emm_global[k+1]+2;
504 }
505
506 memcpy(emmbuf+pos, "\x9E\x20", 2);
507 memcpy(emmbuf+pos+2, buffer+7, 32);
508 pos+=34;
509
510 int found=0;
511 for (k=8; k<emm_global[2]+2 && k<emm_global_len; k += emm_global[k+1]+2) {
512 if (emm_global[k] == 0xA1 || emm_global[k] == 0xA8 || emm_global[k] == 0xA9 || emm_global[k] == 0xB6) {
513 memcpy(emmbuf+pos, emm_global+k, emm_global[k+1]+2);
514 pos += emm_global[k+1]+2;
515 found=1;
516 }
517 }
518 if (found==0) return;
519
520 memcpy(emmbuf+pos, "\xF0\x08", 2);
521 memcpy(emmbuf+pos+2, buffer+39, 8);
522 pos+=10;
523
524 emm_len=pos;
525 emmbuf[2]=emm_len-3;
526 cs_ddump(buffer, len, "original emm:");
527 memcpy(buffer, emmbuf, emm_len);
528 len=emm_len;
529 break;
530 }
531 break;
532 case 0x0d:
533 if (len>500) return;
534 switch (buffer[0]) {
535 case 0x86:
536 if (!memcmp(emm_global, buffer, len)) return;
537 //cs_log("provider %06X - %02X", provider , buffer[7]);
538 memcpy(emm_global, buffer, len);
539 emm_global_len=len;
540 cs_ddump(buffer, len, "cryptoworks global emm:");
541 return;
542 case 0x84:
543 if (!emm_global_len) return;
544
545 if (buffer[18] == 0x86) return;
546
547 memcpy(emmbuf, buffer, 18);
548 pos=18;
549 for (k=5; k<emm_global[2]+2 && k<emm_global_len; k += emm_global[k+1]+2) {
550 memcpy(emmbuf+pos, emm_global+k, emm_global[k+1]+2);
551 pos += emm_global[k+1]+2;
552 }
553 memcpy(emmbuf+pos, buffer+18, len-18);
554 emm_len=pos+(len-18);
555 emmbuf[2]=emm_len-3;
556 emmbuf[11]=emm_len-3-9;
557 cs_ddump(buffer, len, "original emm:");
558 memcpy(buffer, emmbuf, emm_len);
559 len=emm_len;
560
561 break;
562 }
563 break;
564 }
565
566
567 cs_ddump(buffer, len, "emm from fd %d:", demux[demux_index].demux_fd[filter_num].fd);
568
569 memset(&epg, 0, sizeof(epg));
570 epg.caid[0] = (uchar)(demux[demux_index].ECMpids[demux[demux_index].pidindex].CAID>>8);
571 epg.caid[1] = (uchar)(demux[demux_index].ECMpids[demux[demux_index].pidindex].CAID);
572
573 unsigned long provid = (buffer[10] << 8) | buffer[11];
574 int pid = dvbapi_check_array(cfg->dvbapi_prioritytab.caid, CS_MAXCAIDTAB, demux[demux_index].ECMpids[demux[demux_index].pidindex].CAID);
575 if (pid>=0) {
576 if (cfg->dvbapi_prioritytab.mask[pid]>0)
577 provid = (cfg->dvbapi_prioritytab.cmap[pid] << 8 | cfg->dvbapi_prioritytab.mask[pid]);
578 }
579
580 epg.provid[1] = (uchar)(provid>>16);
581 epg.provid[2] = (uchar)(provid>>8);
582 epg.provid[3] = (uchar)(provid);
583
584 epg.l=len;
585 memcpy(epg.emm, buffer, epg.l);
586
587 do_emm(&epg);
588}
589
590void dvbapi_resort_ecmpids(int demux_index) {
591 int n,i,k=0,j;
592
593 memset(global_caid_list, 0, sizeof global_caid_list);
594
595 for (i=0;i<CS_MAXREADER;i++) {
596 for (j=0;j<CS_MAXREADERCAID;j++) {
597 if (reader[i].caid[j] != 0 && !(reader[i].typ & R_IS_NETWORK)) {
598 if (k+1>=MAX_CAID) break;
599 global_caid_list[k++]=reader[i].caid[j];
600 }
601 }
602 }
603
604 demux[demux_index].max_status=0;
605 for (n=0; n<demux[demux_index].ECMpidcount; n++) {
606 demux[demux_index].ECMpids[n].status=0;
607
608 for (i=0;i<CS_MAXCAIDTAB;i++) {
609 ulong provid = (cfg->dvbapi_ignoretab.cmap[i] << 8 | cfg->dvbapi_ignoretab.mask[i]);
610 if (cfg->dvbapi_ignoretab.caid[i] == demux[demux_index].ECMpids[n].CAID && (provid == demux[demux_index].ECMpids[n].PROVID || provid == 0)) {
611 demux[demux_index].ECMpids[n].status=-1; //ignore
612 cs_debug("[IGNORE PID %d] %04X:%06X", n, demux[demux_index].ECMpids[n].CAID, demux[demux_index].ECMpids[n].PROVID);
613 }
614 }
615
616 for (i=0;i<CS_MAXCAIDTAB;i++) {
617 ulong provid = (cfg->dvbapi_prioritytab.cmap[i] << 8 | cfg->dvbapi_prioritytab.mask[i]);
618 if (cfg->dvbapi_prioritytab.caid[i] == demux[demux_index].ECMpids[n].CAID && (provid == demux[demux_index].ECMpids[n].PROVID || provid == 0 || demux[demux_index].ECMpids[n].PROVID == 0)) {
619 demux[demux_index].ECMpids[n].status = i+1; //priority
620 demux[demux_index].max_status = (i+1 > demux[demux_index].max_status) ? i+1 : demux[demux_index].max_status;
621 cs_debug("[PRIORITIZE PID %d] %04X:%06X (position: %d)", n, demux[demux_index].ECMpids[n].CAID, demux[demux_index].ECMpids[n].PROVID, demux[demux_index].ECMpids[n].status);
622 }
623 }
624
625 if (!client[cs_idx].sidtabok && !client[cs_idx].sidtabno) continue;
626
627 int nr;
628 SIDTAB *sidtab;
629 ECM_REQUEST er;
630 er.caid = demux[demux_index].ECMpids[n].CAID;
631 er.prid = demux[demux_index].ECMpids[n].PROVID;
632 er.srvid = demux[demux_index].program_number;
633
634 for (nr=0, sidtab=cfg->sidtab; sidtab; sidtab=sidtab->next, nr++) {
635 if (sidtab->num_caid | sidtab->num_provid | sidtab->num_srvid) {
636 if ((client[cs_idx].sidtabno&(1<<nr)) && (chk_srvid_match(&er, sidtab))) {
637 demux[demux_index].ECMpids[n].status = -1; //ignore
638 cs_debug("[IGNORE PID %d] %04X:%06X (service %s) pos %d", n, demux[demux_index].ECMpids[n].CAID, demux[demux_index].ECMpids[n].PROVID, sidtab->label, nr);
639 }
640 if ((client[cs_idx].sidtabok&(1<<nr)) && (chk_srvid_match(&er, sidtab))) {
641 demux[demux_index].ECMpids[n].status = nr+1; //priority
642 demux[demux_index].max_status = (nr+1 > demux[demux_index].max_status) ? nr+1 : demux[demux_index].max_status;
643 cs_debug("[PRIORITIZE PID %d] %04X:%06X (service: %s position: %d)", n, demux[demux_index].ECMpids[n].CAID, demux[demux_index].ECMpids[n].PROVID, sidtab->label, demux[demux_index].ECMpids[n].status);
644 }
645 }
646 }
647 }
648
649 return;
650}
651
652
653void dvbapi_parse_descriptor(int demux_id, unsigned int info_length, unsigned char *buffer) {
654 //int ca_pmt_cmd_id = buffer[i + 5];
655 unsigned int descriptor_length=0;
656 unsigned int j,u;
657
658 if (info_length<1)
659 return;
660
661 if (buffer[0]==0x01) {
662 buffer=buffer+1;
663 info_length--;
664 }
665
666 for (j = 0; j < info_length; j += descriptor_length + 2) {
667 descriptor_length = buffer[j+1];
668 int descriptor_ca_system_id = (buffer[j+2] << 8) | buffer[j+3];
669 int descriptor_ca_pid = ((buffer[j+4] & 0x1F) << 8) | buffer[j+5];
670 int descriptor_ca_provider = 0;
671
672 if (demux[demux_id].ECMpidcount>=ECM_PIDS)
673 break;
674
675 cs_debug("[pmt] type: %02x\tlength: %d", buffer[j], descriptor_length);
676
677 if (buffer[j] != 0x09) continue;
678
679 if (descriptor_ca_system_id >> 8 == 0x01) {
680 for (u=2; u<descriptor_length; u+=15) {
681 descriptor_ca_pid = ((buffer[j+2+u] & 0x1F) << 8) | buffer[j+2+u+1];
682 descriptor_ca_provider = (buffer[j+2+u+2] << 8) | buffer[j+2+u+3];
683 dvbapi_add_ecmpid(demux_id, descriptor_ca_system_id, descriptor_ca_pid, descriptor_ca_provider, 0);
684 }
685 } else {
686 if (descriptor_ca_system_id >> 8 == 0x05 && descriptor_length == 0x0F && buffer[j+12] == 0x14)
687 descriptor_ca_provider = buffer[j+14] << 16 | (buffer[j+15] << 8| (buffer[j+16] & 0xF0));
688
689 if (descriptor_ca_system_id >> 8 == 0x18 && descriptor_length == 0x07)
690 descriptor_ca_provider = buffer[j+6] << 16 | (buffer[j+7] << 8| (buffer[j+8]));
691
692 dvbapi_add_ecmpid(demux_id, descriptor_ca_system_id, descriptor_ca_pid, descriptor_ca_provider, 0);
693 }
694 }
695}
696
697void dvbapi_try_next_caid(int demux_id) {
698 int num=-1, n, j;
699
700 if (demux[demux_id].tries > 2) {
701 cs_log("can't decode channel");
702 dvbapi_stop_filter(demux_id, TYPE_ECM);
703 return;
704 }
705
706 for (j = 1; j <= demux[demux_id].max_status && num == -1; j++) {
707 for (n=0; n<demux[demux_id].ECMpidcount; n++) {
708 if (demux[demux_id].ECMpids[n].checked == 0 && demux[demux_id].ECMpids[n].status == j) {
709 num=n;
710 break;
711 }
712 }
713 }
714
715 if (num == -1) {
716 j = 0;
717 for (n=0; n<demux[demux_id].ECMpidcount; n++) {
718 if (demux[demux_id].ECMpids[n].checked == 0 && demux[demux_id].ECMpids[n].status == j) {
719 num=n;
720 break;
721 }
722 }
723 }
724
725 if (num == -1) {
726 demux[demux_id].tries++;
727 cs_log("try pids again #%d", demux[demux_id].tries);
728 for (n=0; n<demux[demux_id].ECMpidcount; n++) {
729 demux[demux_id].ECMpids[n].checked=0;
730 }
731 dvbapi_try_next_caid(demux_id);
732 return;
733 }
734
735 dvbapi_stop_filter(demux_id, TYPE_ECM);
736
737 cs_debug("[TRY PID %d] CAID: %04X PROVID: %06X CA_PID: %04X", num, demux[demux_id].ECMpids[num].CAID, demux[demux_id].ECMpids[num].PROVID, demux[demux_id].ECMpids[num].ECM_PID);
738#ifdef AZBOX
739 openxcas_provid = demux[demux_id].ECMpids[num].PROVID;
740 openxcas_caid = demux[demux_id].ECMpids[num].CAID;
741 openxcas_ecm_pid = demux[demux_id].ECMpids[num].ECM_PID;
742#endif
743 demux[demux_id].curindex=num;
744
745 //grep ecm
746 dvbapi_start_filter(demux_id, num, demux[demux_id].ECMpids[num].ECM_PID, 0x80, 0xF0, 3000, TYPE_ECM); //ECM
747 demux[demux_id].ECMpids[num].checked=1;
748}
749
750int dvbapi_parse_capmt(unsigned char *buffer, unsigned int length, int connfd) {
751 unsigned int i, demux_id;
752 unsigned short ca_mask=0x01, demux_index=0x00;
753
754 //int ca_pmt_list_management = buffer[0];
755 unsigned int program_number = (buffer[1] << 8) | buffer[2];
756 unsigned int program_info_length = ((buffer[4] & 0x0F) << 8) | buffer[5];
757
758 if (buffer[17]==0x82 && buffer[18]==0x02) {
759 //enigma2
760 ca_mask = buffer[19];
761 demux_index = buffer[20];
762 }
763
764 cs_ddump(buffer, length, "capmt:");
765
766 for (i = 0; i < MAX_DEMUX; i++) {
767 if (demux[i].demux_index == demux_index && demux[i].program_number == program_number) {
768 return -1; //same pmt on same demux, exit
769 }
770 }
771
772 for (demux_id=0; demux_id<MAX_DEMUX && demux[demux_id].program_number>0; demux_id++);
773
774 if (demux_id>=MAX_DEMUX) {
775 cs_log("error no free id (MAX_DEMUX)");
776 return -1;
777 }
778
779 if (cfg->dvbapi_boxtype == BOXTYPE_IPBOX_PMT) {
780 ca_mask = demux_id + 1;
781 demux_index = demux_id;
782 }
783
784 dvbapi_stop_filter(demux_id, TYPE_ECM);
785 dvbapi_stop_filter(demux_id, TYPE_EMM);
786
787 memset(&demux[demux_id], 0, sizeof(demux[demux_id]));
788 demux[demux_id].program_number=((buffer[1] << 8) | buffer[2]);
789 demux[demux_id].demux_index=demux_index;
790 demux[demux_id].ca_mask=ca_mask;
791 demux[demux_id].socket_fd=connfd;
792 demux[demux_id].rdr=NULL;
793 demux[demux_id].pidindex=-1;
794
795 cs_debug("id: %d\tdemux_index: %d\tca_mask: %02x\tprogram_info_length: %d", demux_id, demux[demux_id].demux_index, demux[demux_id].ca_mask, program_info_length);
796
797 if (program_info_length > 1 && program_info_length < length)
798 dvbapi_parse_descriptor(demux_id, program_info_length-1, buffer+7);
799
800 unsigned int es_info_length=0;
801 for (i = program_info_length + 6; i < length; i += es_info_length + 5) {
802 int stream_type = buffer[i];
803 unsigned short elementary_pid = ((buffer[i + 1] & 0x1F) << 8) | buffer[i + 2];
804 es_info_length = ((buffer[i + 3] & 0x0F) << 8) | buffer[i + 4];
805
806 cs_debug("[pmt] stream_type: %02x\tpid: %04x\tlength: %d", stream_type, elementary_pid, es_info_length);
807
808 if (demux[demux_id].STREAMpidcount >= ECM_PIDS)
809 break;
810
811 demux[demux_id].STREAMpids[demux[demux_id].STREAMpidcount++]=elementary_pid;
812
813 if (es_info_length != 0 && es_info_length < length) {
814 //int offset = (cfg->dvbapi_boxtype == BOXTYPE_IPBOX_PMT) ? i - 1 : i;
815 dvbapi_parse_descriptor(demux_id, es_info_length, buffer+i+5);
816 }
817 }
818 cs_debug("Found %d ECMpids and %d STREAMpids in PMT", demux[demux_id].ECMpidcount, demux[demux_id].STREAMpidcount);
819
820 char *name = get_servicename(demux[demux_id].program_number, demux[demux_id].ECMpidcount>0 ? demux[demux_id].ECMpids[0].CAID : 0);
821 cs_log("new program number: %04X (%s)", program_number, name);
822
823#ifdef AZBOX
824 openxcas_sid = program_number;
825#endif
826
827 if (demux[demux_id].ECMpidcount>0) {
828 dvbapi_resort_ecmpids(demux_id);
829
830#ifdef WITH_STAPI
831 demux[demux_id].demux_index=stapi_get_device(demux_id, demux[demux_id].STREAMpids[0]);
832#endif
833 if (demux[demux_id].ECMpidcount>0)
834 dvbapi_try_next_caid(demux_id);
835 } else {
836 // set channel srvid+caid
837 client[cs_idx].last_srvid = demux[demux_id].program_number;
838 client[cs_idx].last_caid = 0;
839 // reset idle-Time
840 client[cs_idx].last=time((time_t)0);
841 }
842
843 return demux_id;
844}
845
846
847void dvbapi_handlesockmsg (unsigned char *buffer, unsigned int len, int connfd) {
848 unsigned int val=0, size=0, i, k;
849
850 //cs_dump(buffer, len, "handlesockmsg:");
851 for (k = 0; k < len; k += 3 + size + val) {
852 if (buffer[0+k] != 0x9F || buffer[1+k] != 0x80) {
853 cs_log("unknown socket command: %02x", buffer[0+k]);
854 return;
855 }
856
857 if (k>0) {
858 cs_log("Unsupported capmt. Please report");
859 cs_dump(buffer, len, "capmt:");
860 }
861
862 if (buffer[3+k] & 0x80) {
863 val = 0;
864 size = buffer[3+k] & 0x7F;
865 for (i = 0; i < size; i++)
866 val = (val << 8) | buffer[i + 1 + 3 + k];
867 size++;
868 } else {
869 val = buffer[3+k] & 0x7F;
870 size = 1;
871 }
872 switch(buffer[2+k]) {
873 case 0x32:
874 dvbapi_parse_capmt(buffer + size + 3 + k, val, connfd);
875 break;
876 case 0x3f:
877 //9F 80 3f 04 83 02 00 <demux index>
878 cs_ddump(buffer, len, "capmt 3f:");
879 // ipbox fix
880 if (cfg->dvbapi_boxtype==BOXTYPE_IPBOX) {
881 int demux_index=buffer[7+k];
882 for (i = 0; i < MAX_DEMUX; i++) {
883 if (demux[i].demux_index == demux_index) {
884 dvbapi_stop_descrambling(i);
885 break;
886 }
887 }
888 // check do we have any demux running on this fd
889 short execlose = 1;
890 for (i = 0; i < MAX_DEMUX; i++) {
891 if (demux[i].socket_fd == connfd) {
892 execlose = 0;
893 break;
894 }
895 }
896 if (execlose) close(connfd);
897 } else {
898 close(connfd);
899 }
900 break;
901 default:
902 cs_log("handlesockmsg() unknown command");
903 cs_dump(buffer, len, "unknown command:");
904 break;
905 }
906 }
907}
908
909int dvbapi_init_listenfd() {
910 int clilen,listenfd;
911 struct sockaddr_un servaddr;
912
913 memset(&servaddr, 0, sizeof(struct sockaddr_un));
914 servaddr.sun_family = AF_UNIX;
915 strcpy(servaddr.sun_path, devices[selected_box].cam_socket_path);
916 clilen = sizeof(servaddr.sun_family) + strlen(servaddr.sun_path);
917
918 if ((unlink(devices[selected_box].cam_socket_path) < 0) && (errno != ENOENT))
919 return 0;
920 if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
921 return 0;
922 if (bind(listenfd, (struct sockaddr *) &servaddr, clilen) < 0)
923 return 0;
924 if (listen(listenfd, 5) < 0)
925 return 0;
926
927 return listenfd;
928}
929
930void dvbapi_chk_caidtab(char *caidasc, CAIDTAB *ctab) {
931 char *ptr1, *ptr3;
932 int i;
933
934 for (i=0, ptr1=strtok(caidasc, ","); (i<CS_MAXCAIDTAB) && (ptr1); ptr1=strtok(NULL, ",")) {
935 unsigned long caid, prov;
936 if( (ptr3=strchr(trim(ptr1), ':')) )
937 *ptr3++='\0';
938 else
939 ptr3="";
940
941 if (((caid=a2i(ptr1, 2))|(prov=a2i(ptr3, 3)))) {
942 ctab->caid[i]=caid;
943 ctab->cmap[i]=prov >> 8;
944 ctab->mask[i++]=prov;
945 }
946 }
947}
948
949pthread_mutex_t event_handler_lock;
950
951void event_handler(int signal) {
952 struct stat pmt_info;
953 char dest[1024];
954 DIR *dirp;
955 struct dirent *dp;
956 int i, pmt_fd;
957 uchar mbuf[1024];
958
959 signal=signal; //avoid compiler warnings
960 pthread_mutex_lock(&event_handler_lock);
961
962 int standby_fd = open(STANDBY_FILE, O_RDONLY);
963 pausecam = (standby_fd > 0) ? 1 : 0;
964 if (standby_fd) close(standby_fd);
965
966 if (cfg->dvbapi_boxtype==BOXTYPE_IPBOX || cfg->dvbapi_pmtmode == 1) {
967 pthread_mutex_unlock(&event_handler_lock);
968 return;
969 }
970
971 for (i=0;i<MAX_DEMUX;i++) {
972 if (demux[i].pmt_file[0] != 0) {
973 sprintf(dest, "%s%s", TMPDIR, demux[i].pmt_file);
974 pmt_fd = open(dest, O_RDONLY);
975 if(pmt_fd>0) {
976 if (fstat(pmt_fd, &pmt_info) != 0) {
977 close(pmt_fd);
978 continue;
979 }
980
981 if (pmt_info.st_mtime != demux[i].pmt_time) {
982 cs_log("stoping demux for pmt file %s", dest);
983 dvbapi_stop_descrambling(i);
984 }
985
986 close(pmt_fd);
987 continue;
988 } else {
989 cs_log("stoping demux for pmt file %s", dest);
990 dvbapi_stop_descrambling(i);
991 }
992 }
993 }
994
995 if (disable_pmt_files) {
996 pthread_mutex_unlock(&event_handler_lock);
997 return;
998 }
999
1000 dirp = opendir(TMPDIR);
1001 if (!dirp) {
1002 cs_log("opendir errno %d", errno);
1003 pthread_mutex_unlock(&event_handler_lock);
1004 return;
1005 }
1006
1007 while ((dp = readdir(dirp))) {
1008 if (strlen(dp->d_name) < 7)
1009 continue;
1010 if (strncmp(dp->d_name, "pmt", 3)!=0 || strncmp(dp->d_name+strlen(dp->d_name)-4, ".tmp", 4)!=0)
1011 continue;
1012
1013 sprintf(dest, "%s%s", TMPDIR, dp->d_name);
1014 pmt_fd = open(dest, O_RDONLY);
1015 if (pmt_fd < 0)
1016 continue;
1017
1018 if (fstat(pmt_fd, &pmt_info) != 0)
1019 { close(pmt_fd); continue; }
1020
1021 int found=0;
1022 for (i=0;i<MAX_DEMUX;i++) {
1023 if (strcmp(demux[i].pmt_file, dp->d_name)==0) {
1024 if (pmt_info.st_mtime == demux[i].pmt_time) {
1025 found=1;
1026 continue;
1027 }
1028 dvbapi_stop_descrambling(i);
1029 }
1030 }
1031 if (found)
1032 { close(pmt_fd); continue; }
1033
1034 cs_log("found pmt file %s", dest);
1035 cs_sleepms(100);
1036
1037 unsigned int len = read(pmt_fd,mbuf,sizeof(mbuf));
1038 close(pmt_fd);
1039
1040 if (len < 1) {
1041 cs_log("pmt file %s have invalid len!", dest);
1042 continue;
1043 }
1044
1045 int pmt_id;
1046#ifdef QBOXHD
1047 uint j1,j2;
1048 // QboxHD pmt.tmp is the full capmt written as a string of hex values
1049 // pmt.tmp must be longer than 3 bytes (6 hex chars) and even length
1050 if ((len<6) || ((len%2) != 0) || ((len/2)>sizeof(dest))) {
1051 cs_log("error parsing QboxHD pmt.tmp, incorrect length");
1052 continue;
1053 }
1054
1055 for(j2=0,j1=0;j2<len;j2+=2,j1++) {
1056 if (sscanf((char*)mbuf+j2, "%02X", dest+j1) != 1) {
1057 cs_log("error parsing QboxHD pmt.tmp, data not valid in position %d",j2);
1058 pthread_mutex_unlock(&event_handler_lock);
1059 return;
1060 }
1061 }
1062
1063 cs_ddump(dest,len/2,"QboxHD pmt.tmp:");
1064
1065 pmt_id = dvbapi_parse_capmt(dest+4, (len/2)-4, -1);
1066#else
1067 if (len>sizeof(dest)) {
1068 cs_log("event_handler() dest buffer is to small for pmt data!");
1069 continue;
1070 }
1071 cs_ddump(mbuf,len,"pmt:");
1072
1073 memcpy(dest, "\x00\xFF\xFF\x00\x00\x13\x00", 7);
1074
1075 dest[1] = mbuf[3];
1076 dest[2] = mbuf[4];
1077 dest[5] = mbuf[11]+1;
1078
1079 memcpy(dest + 7, mbuf + 12, len - 12 - 4);
1080
1081 pmt_id = dvbapi_parse_capmt((uchar*)dest, 7 + len - 12 - 4, -1);
1082#endif
1083 strcpy(demux[pmt_id].pmt_file, dp->d_name);
1084 demux[pmt_id].pmt_time = pmt_info.st_mtime;
1085
1086 if (cfg->dvbapi_pmtmode == 3) {
1087 disable_pmt_files=1;
1088 break;
1089 }
1090 }
1091 closedir(dirp);
1092 pthread_mutex_unlock(&event_handler_lock);
1093}
1094
1095void dvbapi_process_input(int demux_id, int filter_num, uchar *buffer, int len) {
1096
1097 if (demux[demux_id].demux_fd[filter_num].type==TYPE_ECM) {
1098 if (len != (((buffer[1] & 0xf) << 8) | buffer[2]) + 3) //invaild CAT length
1099 return;
1100
1101 if (buffer[0] != 0x80 && buffer[0] != 0x81)
1102 return;
1103
1104 unsigned short caid = demux[demux_id].ECMpids[demux[demux_id].demux_fd[filter_num].pidindex].CAID;
1105 unsigned long provid = demux[demux_id].ECMpids[demux[demux_id].demux_fd[filter_num].pidindex].PROVID;
1106
1107 if ((caid >> 8) == 0x06) {
1108 int i;
1109 //80 70 39 53 04 05 00 88
1110 if (buffer[5]>10) return;
1111 if (demux[demux_id].irdeto_numchids != buffer[5]) {
1112 cs_log("IRDETO ECM CHIDs: %d", buffer[5]);
1113 //TODO: remove no longer used chids
1114 for (i=1;i<=buffer[5];i++) {
1115 dvbapi_add_ecmpid(demux_id, caid, demux[demux_id].ECMpids[demux[demux_id].demux_fd[filter_num].pidindex].ECM_PID, provid, i);
1116 }
1117 demux[demux_id].irdeto_numchids = buffer[5];
1118 //demux[demux_id].irdeto_curchid = 0;
1119 }
1120 if (buffer[4] != demux[demux_id].ECMpids[demux[demux_id].demux_fd[filter_num].pidindex].irdeto_chid) {
1121 //wait for the correct chid
1122 return;
1123 }
1124 }
1125
1126 if (demux[demux_id].ECMpids[demux[demux_id].demux_fd[filter_num].pidindex].table == buffer[0])
1127 return;
1128
1129 demux[demux_id].ECMpids[demux[demux_id].demux_fd[filter_num].pidindex].table = buffer[0];
1130
1131 int pid = dvbapi_check_array(cfg->dvbapi_prioritytab.caid, CS_MAXCAIDTAB, caid);
1132 if (pid>=0 && provid == 0) {
1133 if (cfg->dvbapi_prioritytab.mask[pid]>0)
1134 provid = (cfg->dvbapi_prioritytab.cmap[pid] << 8 | cfg->dvbapi_prioritytab.mask[pid]);
1135 }
1136
1137 if (!provid)
1138 provid = chk_provid(buffer, caid);
1139
1140 if (cfg->dvbapi_au==1)
1141 dvbapi_start_emm_filter(demux_id);
1142
1143 ECM_REQUEST *er;
1144 if (!(er=get_ecmtask()))
1145 return;
1146
1147 er->srvid = demux[demux_id].program_number;
1148 er->caid = caid;
1149 er->pid = demux[demux_id].ECMpids[demux[demux_id].demux_fd[filter_num].pidindex].ECM_PID;
1150 er->prid = provid;
1151
1152 er->l=len;
1153 memcpy(er->ecm, buffer, er->l);
1154
1155 cs_debug("request cw for caid %04X provid %06X srvid %04X pid %04X chid %02X", er->caid, er->prid, er->srvid, er->pid, (caid >> 8) == 0x06 ? buffer[7] : 0);
1156 get_cw(er);
1157 }
1158
1159 if (demux[demux_id].demux_fd[filter_num].type==TYPE_EMM) {
1160 if (buffer[0]==0x01) { //CAT
1161 cs_debug("receiving cat");
1162 dvbapi_parse_cat(demux_id, buffer, len);
1163
1164 dvbapi_stop_filternum(demux_id, filter_num);
1165 return;
1166 }
1167 dvbapi_process_emm(demux_id, filter_num, buffer, len);
1168 }
1169
1170 if (demux[demux_id].demux_fd[filter_num].count==1) {
1171 //stop filter
1172 dvbapi_stop_filternum(demux_id, filter_num);
1173 }
1174 if (demux[demux_id].demux_fd[filter_num].count>1) {
1175 demux[demux_id].demux_fd[filter_num].count--;
1176 }
1177}
1178
1179void dvbapi_main_local(void *idx) {
1180 int cidx=(int)idx;
1181 client[cidx].thread=pthread_self();
1182
1183 int maxpfdsize=(MAX_DEMUX*MAX_FILTER)+MAX_DEMUX+2;
1184 struct pollfd pfd2[maxpfdsize];
1185 int i,rc,pfdcount,g,connfd,clilen,j;
1186 int ids[maxpfdsize], fdn[maxpfdsize], type[maxpfdsize];
1187 struct timeb tp;
1188 struct sockaddr_un servaddr;
1189 ssize_t len=0;
1190 uchar mbuf[1024];
1191
1192 struct s_auth *account=0;
1193 int ok=0;
1194 if (!account) {
1195 client[cs_idx].usr[0]=0;
1196 for (ok=0, account=cfg->account; (account) && (!ok); account=account->next)
1197 if( (ok=!strcmp(cfg->dvbapi_usr, account->usr)) )
1198 break;
1199 }
1200
1201 cs_auth_client(ok ? account : (struct s_auth *)(-1), "dvbapi");
1202
1203
1204 for (i=0;i<MAX_DEMUX;i++) {
1205 memset(&demux[i], 0, sizeof(demux[i]));
1206 demux[i].pidindex=-1;
1207 demux[i].rdr=NULL;
1208 }
1209 memset(ca_fd, 0, sizeof(ca_fd));
1210
1211 dvbapi_detect_api();
1212
1213 if (selected_box == -1 || selected_api==-1) {
1214 cs_log("could not detect api version");
1215 return;
1216 }
1217
1218 if (cfg->dvbapi_pmtmode == 1)
1219 disable_pmt_files=1;
1220
1221 int listenfd = -1;
1222 if (cfg->dvbapi_boxtype != BOXTYPE_IPBOX_PMT && cfg->dvbapi_pmtmode != 2) {
1223 listenfd = dvbapi_init_listenfd();
1224 if (listenfd < 1) {
1225 cs_log("could not init camd.socket.");
1226 return;
1227 }
1228 }
1229
1230 struct sigaction signal_action;
1231 signal_action.sa_handler = event_handler;
1232 sigemptyset(&signal_action.sa_mask);
1233 signal_action.sa_flags = SA_RESTART;
1234 sigaction(SIGRTMIN + 1, &signal_action, NULL);
1235
1236 pthread_mutexattr_t attr;
1237 pthread_mutexattr_init(&attr);
1238 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
1239 pthread_mutex_init(&event_handler_lock, &attr);
1240
1241 dir_fd = open(TMPDIR, O_RDONLY);
1242 if (dir_fd >= 0) {
1243 fcntl(dir_fd, F_SETSIG, SIGRTMIN + 1);
1244 fcntl(dir_fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_DELETE | DN_MULTISHOT);
1245 event_handler(SIGRTMIN + 1);
1246 }
1247
1248 cs_ftime(&tp);
1249 tp.time+=500;
1250
1251 pfd2[0].fd = client[cs_idx].fd_m2c_c;
1252 pfd2[0].events = (POLLIN | POLLPRI);
1253 type[0]=0;
1254
1255 pfd2[1].fd = listenfd;
1256 pfd2[1].events = (POLLIN | POLLPRI);
1257 type[1]=1;
1258
1259 while (1) {
1260 pfdcount = (listenfd > -1) ? 2 : 1;
1261
1262 chk_pending(tp);
1263
1264 if (pausecam==1) {
1265 cs_sleepms(500);
1266 continue;
1267 }
1268
1269 for (i=0;i<MAX_DEMUX;i++) {
1270 for (g=0;g<MAX_FILTER;g++) {
1271 if (demux[i].demux_fd[g].fd>0 && selected_api != STAPI) {
1272 pfd2[pfdcount].fd = demux[i].demux_fd[g].fd;
1273 pfd2[pfdcount].events = (POLLIN | POLLPRI);
1274 ids[pfdcount]=i;
1275 fdn[pfdcount]=g;
1276 type[pfdcount++]=0;
1277 }
1278 }
1279
1280 if (demux[i].socket_fd>0) {
1281 rc=0;
1282 if (cfg->dvbapi_boxtype==BOXTYPE_IPBOX) {
1283 for (j = 0; j < pfdcount; j++) {
1284 if (pfd2[j].fd == demux[i].socket_fd) {
1285 rc=1;
1286 break;
1287 }
1288 }
1289 if (rc==1) continue;
1290 }
1291
1292 pfd2[pfdcount].fd=demux[i].socket_fd;
1293 pfd2[pfdcount].events = (POLLIN | POLLPRI | POLLHUP);
1294 ids[pfdcount]=i;
1295 type[pfdcount++]=1;
1296 }
1297 }
1298
1299 rc = poll(pfd2, pfdcount, 500);
1300 if (rc<1) continue;
1301
1302 for (i = 0; i < pfdcount; i++) {
1303 if (pfd2[i].revents > 3)
1304 cs_debug("event %d on fd %d", pfd2[i].revents, pfd2[i].fd);
1305
1306 if (pfd2[i].revents & (POLLHUP | POLLNVAL)) {
1307 if (type[i]==1) {
1308 for (j=0;j<MAX_DEMUX;j++) {
1309 if (demux[j].socket_fd==pfd2[i].fd) {
1310 dvbapi_stop_descrambling(j);
1311 }
1312 }
1313 close(pfd2[i].fd);
1314 continue;
1315 }
1316 if (pfd2[i].fd==client[cs_idx].fd_m2c_c) {
1317 cs_exit(0);
1318 }
1319 }
1320 if (pfd2[i].revents & (POLLIN | POLLPRI)) {
1321 if (pfd2[i].fd==client[cs_idx].fd_m2c_c) {
1322 chk_dcw(client[cs_idx].fd_m2c_c);
1323 continue;
1324 }
1325
1326 if (type[i]==1) {
1327 if (pfd2[i].fd==listenfd) {
1328 connfd = accept(listenfd, (struct sockaddr *)&servaddr, (socklen_t *)&clilen);
1329 cs_debug("new socket connection fd: %d", connfd);
1330
1331 disable_pmt_files=1;
1332
1333 if (connfd <= 0) {
1334 cs_log("accept() returns error %d, fd event %d", errno, pfd2[i].revents);
1335 continue;
1336 }
1337 } else {
1338 cs_debug("PMT Update on socket %d. Please report.", pfd2[i].fd);
1339 dvbapi_stop_descrambling(ids[i]);
1340 connfd = pfd2[i].fd;
1341 }
1342
1343 len = read(connfd, mbuf, sizeof(mbuf));
1344
1345 if (len < 3) {
1346 cs_debug("camd.socket: too short message received");
1347 continue;
1348 }
1349
1350 dvbapi_handlesockmsg(mbuf, len, connfd);
1351 } else { // type==0
1352 int demux_index=ids[i];
1353 int n=fdn[i];
1354
1355 if ((len=dvbapi_read_device(pfd2[i].fd, mbuf, sizeof(mbuf))) <= 0) {
1356 if (demux[demux_index].pidindex==-1) {
1357 dvbapi_try_next_caid(demux_index);
1358 }
1359 continue;
1360 }
1361
1362 if (pfd2[i].fd==(int)demux[demux_index].demux_fd[n].fd) {
1363 dvbapi_process_input(demux_index,n,mbuf,len);
1364 }
1365 }
1366 }
1367 }
1368 }
1369 return;
1370}
1371
1372void dvbapi_write_cw(int demux_id, uchar *cw) {
1373 int n;
1374 unsigned char nullcw[8];
1375 memset(nullcw, 0, 8);
1376 ca_descr_t ca_descr;
1377 memset(&ca_descr,0,sizeof(ca_descr));
1378
1379 for (n=0;n<2;n++) {
1380 if (memcmp(cw+(n*8),demux[demux_id].lastcw[n],8)!=0 && memcmp(cw+(n*8),nullcw,8)!=0) {
1381 ca_descr.index = demux_id;
1382 ca_descr.parity = n;
1383 memcpy(demux[demux_id].lastcw[n],cw+(n*8),8);
1384 memcpy(ca_descr.cw,cw+(n*8),8);
1385
1386 int i;
1387 for (i=0;i<8;i++) {
1388 if (demux[demux_id].ca_mask & (1 << i)) {
1389
1390 //cs_log("mask %02X write to %d", demux[demux_id].ca_mask, i);
1391 cs_debug("write cw%d index: %d (ca%d)", n, demux_id, i);
1392
1393 if (ca_fd[i]<=0) {
1394 ca_fd[i]=dvbapi_open_device(1, i);
1395 if (ca_fd[i]<=0)
1396 return;
1397 }
1398
1399 if (ioctl(ca_fd[i], CA_SET_DESCR, &ca_descr) < 0)
1400 cs_debug("Error CA_SET_DESCR");
1401 }
1402 }
1403 }
1404 }
1405}
1406
1407void dvbapi_send_dcw(ECM_REQUEST *er) {
1408#ifdef AZBOX
1409 azbox_send_dcw(er);
1410 return;
1411#endif
1412 int i;
1413
1414 for (i=0;i<MAX_DEMUX;i++) {
1415 if (demux[i].program_number==er->srvid) {
1416 demux[i].rdr=&reader[er->reader[0]];
1417
1418 if (er->rc<=3 && demux[i].pidindex==-1 && er->caid!=0) {
1419 dvbapi_start_descrambling(i);
1420 }
1421
1422 if (er->rc==4 && cfg->dvbapi_au==1 && dvbapi_check_array(global_caid_list, MAX_CAID, er->caid)>=0 && er->caid!=0x0500 && er->caid!=0x0100) {
1423 //local card and not found -> maybe card need emm
1424 dvbapi_start_descrambling(i);
1425 }
1426
1427 if (er->rc>3 && demux[i].pidindex==-1) {
1428 dvbapi_try_next_caid(i);
1429 return;
1430 }
1431
1432 if (er->rc>3) {
1433 cs_debug("cw not found");
1434 return;
1435 }
1436
1437 int dindex = dvbapi_check_array(cfg->dvbapi_delaytab.caid, CS_MAXCAIDTAB, er->caid);
1438 if (dindex>=0) {
1439 char tmp1[5];
1440 sprintf(tmp1, "%04X", cfg->dvbapi_delaytab.mask[dindex]);
1441 int cw_delay = strtol(tmp1, '\0', 10);
1442 if (cw_delay<1000) {
1443 cs_debug("wait %d ms", cw_delay);
1444 cs_sleepms(cw_delay);
1445 }
1446 }
1447
1448
1449#ifdef WITH_STAPI
1450 stapi_write_cw(i, er->cw);
1451#else
1452 dvbapi_write_cw(i, er->cw);
1453#endif
1454 // reset idle-Time
1455 client[cs_idx].last=time((time_t)0);
1456
1457 FILE *ecmtxt;
1458 ecmtxt = fopen(ECMINFO_FILE, "w");
1459 if(ecmtxt != NULL) {
1460 fprintf(ecmtxt, "caid: 0x%04X\npid: 0x%04X\nprov: 0x%06X\n", er->caid, er->pid, (uint) er->prid);
1461 fprintf(ecmtxt, "reader: %s\n", reader[er->reader[0]].label);
1462 if (reader[er->reader[0]].typ & R_IS_CASCADING)
1463 fprintf(ecmtxt, "from: %s\n", reader[er->reader[0]].device);
1464 else
1465 fprintf(ecmtxt, "from: local\n");
1466 fprintf(ecmtxt, "protocol: %s\n", reader[er->reader[0]].ph.desc);
1467 fprintf(ecmtxt, "hops: %d\n", reader[er->reader[0]].cc_currenthops);
1468 fprintf(ecmtxt, "ecm time: %.3f\n", (float) client[cs_idx].cwlastresptime/1000);
1469 fprintf(ecmtxt, "cw0: %s\n", cs_hexdump(1,demux[i].lastcw[0],8));
1470 fprintf(ecmtxt, "cw1: %s\n", cs_hexdump(1,demux[i].lastcw[1],8));
1471 fclose(ecmtxt);
1472 ecmtxt = NULL;
1473 }
1474 }
1475 }
1476}
1477
1478static void dvbapi_handler(int ctyp) {
1479 //cs_log("dvbapi loaded fd=%d", idx);
1480 if (cfg->dvbapi_enabled == 1) {
1481 int i=cs_fork(0, ctyp);
1482 client[i].typ='c';
1483 client[i].ip=0;
1484 client[i].ctyp=ctyp;
1485#ifdef AZBOX
1486 pthread_create(&client[i].thread, NULL, (void *)azbox_main, (void*) i);
1487#else
1488 pthread_create(&client[i].thread, NULL, (void *)dvbapi_main_local, (void*) i);
1489#endif
1490 pthread_detach(client[i].thread);
1491 }
1492
1493 return;
1494}
1495
1496
1497#ifdef AZBOX
1498void azbox_openxcas_ecm_callback(int stream_id, unsigned int seq, int cipher_index, unsigned int caid, unsigned char *ecm_data, int l, unsigned short pid) {
1499 cs_debug("openxcas: ecm callback received");
1500
1501 openxcas_stream_id = stream_id;
1502 //openxcas_seq = seq;
1503 //openxcas_caid = caid;
1504 openxcas_ecm_pid = pid;
1505 openxcas_busy = 1;
1506
1507 ECM_REQUEST *er;
1508 if (!(er=get_ecmtask()))
1509 return;
1510
1511 er->srvid = openxcas_sid;
1512 er->caid = openxcas_caid;
1513 er->pid = openxcas_ecm_pid;
1514 er->prid = openxcas_provid;
1515
1516 er->l=l;
1517 memcpy(er->ecm, ecm_data, er->l);
1518
1519 cs_debug("request cw for caid %04X provid %06X srvid %04X pid %04X", er->caid, er->prid, er->srvid, er->pid);
1520 get_cw(er);
1521
1522 //openxcas_stop_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM);
1523 //openxcas_remove_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM);
1524
1525 openxcas_cipher_idx = cipher_index;
1526
1527 struct timeb tp;
1528 cs_ftime(&tp);
1529 tp.time+=500;
1530
1531 struct pollfd pfd;
1532 pfd.fd = client[cs_idx].fd_m2c_c;
1533 pfd.events = POLLIN | POLLPRI;
1534/*
1535 while(1) {
1536 chk_pending(tp);
1537
1538 if (poll(&pfd, 1, 10) < 0)
1539 continue;
1540
1541 if (pfd.revents & (POLLHUP | POLLNVAL)) {
1542 cs_debug("openxcas: ecm/cw error");
1543 break;
1544 }
1545
1546 if (pfd.revents & (POLLIN | POLLPRI)) {
1547 chk_dcw(client[cs_idx].fd_m2c_c);
1548 break;
1549 }
1550 }*/
1551}
1552
1553
1554void azbox_openxcas_ex_callback(int stream_id, unsigned int seq, int idx, unsigned int pid, unsigned char *ecm_data, int l) {
1555 cs_debug("openxcas: ex callback received");
1556
1557 openxcas_stream_id = stream_id;
1558 openxcas_ecm_pid = pid;
1559 openxcas_cipher_idx = idx; // is this really cipher_idx?
1560
1561 ECM_REQUEST *er;
1562 if (!(er=get_ecmtask()))
1563 return;
1564
1565 er->srvid = openxcas_sid;
1566 er->caid = openxcas_caid;
1567 er->pid = openxcas_ecm_pid;
1568 er->prid = openxcas_provid;
1569
1570 er->l=l;
1571 memcpy(er->ecm, ecm_data, er->l);
1572
1573 cs_debug("request cw for caid %04X provid %06X srvid %04X pid %04X", er->caid, er->prid, er->srvid, er->pid);
1574 get_cw(er);
1575
1576 if (openxcas_stop_filter_ex(stream_id, seq, openxcas_filter_idx) < 0)
1577 cs_log("openxcas: unable to stop ex filter");
1578 else
1579 cs_debug("openxcas: ex filter stopped");
1580
1581 struct timeb tp;
1582 cs_ftime(&tp);
1583 tp.time+=500;
1584
1585 chk_pending(tp);
1586 chk_dcw(client[cs_idx].fd_m2c_c);
1587
1588 unsigned char mask[12];
1589 unsigned char comp[12];
1590 memset(&mask, 0x00, sizeof(mask));
1591 memset(&comp, 0x00, sizeof(comp));
1592
1593 mask[0] = 0xff;
1594 comp[0] = ecm_data[0] ^ 1;
1595
1596 if ((openxcas_filter_idx = openxcas_start_filter_ex(stream_id, seq, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ex_callback)) < 0)
1597 cs_log("openxcas: unable to start ex filter");
1598 else
1599 cs_debug("openxcas: ex filter started, pid = %x", openxcas_ecm_pid);
1600}
1601
1602void azbox_main(void *idx) {
1603 int cidx=(int)idx;
1604 client[cidx].thread=pthread_self();
1605 struct timeb tp;
1606 cs_ftime(&tp);
1607 tp.time+=500;
1608
1609 openxcas_msg_t msg;
1610 int ret;
1611 while ((ret = openxcas_get_message(&msg, 0)) >= 0) {
1612 cs_sleepms(10);
1613
1614 chk_pending(tp);
1615
1616 if (ret) {
1617 openxcas_stream_id = msg.stream_id;
1618 openxcas_seq = msg.sequence;
1619
1620 switch(msg.cmd) {
1621 case OPENXCAS_SELECT_CHANNEL:
1622 cs_debug("openxcas: msg: OPENXCAS_SELECT_CHANNEL");
1623
1624 // parse channel info
1625 struct stOpenXCASChannel chan;
1626 memcpy(&chan, msg.buf, msg.buf_len);
1627
1628 cs_log("openxcas: channel change: sid = %x, vpid = %x. apid = %x", chan.service_id, chan.v_pid, chan.a_pid);
1629
1630 openxcas_video_pid = chan.v_pid;
1631 openxcas_audio_pid = chan.a_pid;
1632 openxcas_data_pid = chan.d_pid;
1633 break;
1634 case OPENXCAS_START_PMT_ECM:
1635 cs_debug("openxcas: msg: OPENXCAS_START_PMT_ECM");
1636
1637 // parse pmt
1638 uchar *dest = malloc(msg.buf_len + 7 - 12 - 4);
1639
1640 memcpy(dest, "\x00\xFF\xFF\x00\x00\x13\x00", 7);
1641
1642 dest[1] = msg.buf[3];
1643 dest[2] = msg.buf[4];
1644 dest[5] = msg.buf[11]+1;
1645
1646 memcpy(dest + 7, msg.buf + 12, msg.buf_len - 12 - 4);
1647
1648 dvbapi_parse_capmt(dest, 7 + msg.buf_len - 12 - 4, -1);
1649 free(dest);
1650
1651 unsigned char mask[12];
1652 unsigned char comp[12];
1653 memset(&mask, 0x00, sizeof(mask));
1654 memset(&comp, 0x00, sizeof(comp));
1655
1656 mask[0] = 0xfe;
1657 comp[0] = 0x80;
1658
1659 if ((ret = openxcas_add_filter(msg.stream_id, OPENXCAS_FILTER_ECM, 0, 0xffff, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ecm_callback)) < 0)
1660 cs_log("openxcas: unable to add ecm filter");
1661 else
1662 cs_debug("openxcas: ecm filter added, pid = %x, caid = %x", openxcas_ecm_pid, 0);
1663
1664 if (openxcas_start_filter(msg.stream_id, msg.sequence, OPENXCAS_FILTER_ECM) < 0)
1665 cs_log("openxcas: unable to start ecm filter");
1666 else
1667 cs_debug("openxcas: ecm filter started");
1668
1669 if (!openxcas_create_cipher_ex(msg.stream_id, openxcas_seq, 0, openxcas_ecm_pid, openxcas_video_pid, 0xffff, openxcas_audio_pid, 0xffff, 0xffff, 0xffff))
1670 cs_log("openxcas: failed to create cipher ex");
1671 else
1672 cs_debug("openxcas: cipher created");
1673 break;
1674 case OPENXCAS_STOP_PMT_ECM:
1675 cs_debug("openxcas: msg: OPENXCAS_STOP_PMT_ECM");
1676 openxcas_stop_filter(msg.stream_id, OPENXCAS_FILTER_ECM);
1677 openxcas_remove_filter(msg.stream_id, OPENXCAS_FILTER_ECM);
1678 openxcas_stop_filter_ex(msg.stream_id, msg.sequence, openxcas_filter_idx);
1679 openxcas_destory_cipher_ex(msg.stream_id, msg.sequence);
1680 memset(&demux, 0, sizeof(demux));
1681 break;
1682 case OPENXCAS_ECM_CALLBACK:
1683 cs_debug("openxcas: msg: OPENXCAS_ECM_CALLBACK");
1684 struct stOpenXCAS_Data data;
1685 memcpy(&data, msg.buf, msg.buf_len);
1686 if (!openxcas_busy)
1687 openxcas_filter_callback(msg.stream_id, msg.sequence, OPENXCAS_FILTER_ECM, &data);
1688 break;
1689 case OPENXCAS_PID_FILTER_CALLBACK:
1690 cs_debug("openxcas: msg: OPENXCAS_PID_FILTER_CALLBACK");
1691 openxcas_filter_callback_ex(msg.stream_id, msg.sequence, (struct stOpenXCAS_Data *)msg.buf);
1692 break;
1693 case OPENXCAS_QUIT:
1694 cs_debug("openxcas: msg: OPENXCAS_QUIT");
1695 openxcas_close();
1696 cs_log("openxcas: exited");
1697 return;
1698 break;
1699 case OPENXCAS_UKNOWN_MSG:
1700 default:
1701 cs_debug("openxcas: msg: OPENXCAS_UKNOWN_MSG (%d)", msg.cmd);
1702 //cs_ddump(&msg, sizeof(msg), "msg dump:");
1703 break;
1704 }
1705 }
1706 }
1707 cs_log("openxcas: invalid message");
1708 return;
1709}
1710
1711void azbox_send_dcw(ECM_REQUEST *er) {
1712 cs_debug("openxcas: send_dcw");
1713
1714 openxcas_busy = 0;
1715
1716 int i;
1717 for (i=0; i < MAX_DEMUX; i++) {
1718 if (er->rc > 3) {
1719 cs_debug("cw not found");
1720
1721 if (demux[i].pidindex==-1)
1722 dvbapi_try_next_caid(i);
1723
1724 openxcas_stop_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM);
1725 openxcas_remove_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM);
1726
1727 unsigned char mask[12];
1728 unsigned char comp[12];
1729 memset(&mask, 0x00, sizeof(mask));
1730 memset(&comp, 0x00, sizeof(comp));
1731
1732 mask[0] = 0xfe;
1733 comp[0] = 0x80;
1734
1735 if (openxcas_add_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM, 0, 0xffff, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ecm_callback) < 0) {
1736 cs_log("openxcas: unable to add ecm filter (0)");
1737 if (openxcas_add_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM, openxcas_caid, 0xffff, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ecm_callback) < 0)
1738 cs_log("openxcas: unable to add ecm filter (%04x)", openxcas_caid);
1739 else
1740 cs_debug("openxcas: ecm filter added, pid = %x, caid = %x", openxcas_ecm_pid, openxcas_caid);
1741 } else
1742 cs_debug("openxcas: ecm filter added, pid = %x, caid = %x", openxcas_ecm_pid, 0);
1743
1744 if (openxcas_start_filter(openxcas_stream_id, openxcas_seq, OPENXCAS_FILTER_ECM) < 0)
1745 cs_log("openxcas: unable to start ecm filter");
1746 else
1747 cs_debug("openxcas: ecm filter started");
1748
1749 return;
1750 }
1751 }
1752
1753 unsigned char nullcw[8];
1754 memset(nullcw, 0, 8);
1755
1756 int n;
1757 for (n=0;n<2;n++) {
1758 if (memcmp(er->cw + (n * 8), demux[0].lastcw[n], 8) && memcmp(er->cw + (n * 8), nullcw, 8)) {
1759 memcpy(demux[0].lastcw[n], er->cw + (n * 8), 8);
1760 memcpy(openxcas_cw + (n * 8), er->cw + (n * 8), 8);
1761 }
1762 }
1763
1764 if (openxcas_set_key(openxcas_stream_id, openxcas_seq, 0, openxcas_cipher_idx, openxcas_cw, openxcas_cw + 8) != 1)
1765 cs_log("openxcas: set cw failed");
1766 else
1767 cs_ddump(openxcas_cw, 16, "openxcas: write cws to descrambler");
1768}
1769#endif
1770/*
1771 * protocol structure
1772 */
1773
1774void module_dvbapi(struct s_module *ph)
1775{
1776 strcpy(ph->desc, "dvbapi");
1777 ph->type=MOD_CONN_SERIAL;
1778 ph->multi=1;
1779 ph->watchdog=0;
1780 ph->s_handler=dvbapi_handler;
1781 ph->send_dcw=dvbapi_send_dcw;
1782}
1783#endif // HAVE_DVBAPI
Note: See TracBrowser for help on using the repository browser.