source: trunk/module-dvbapi.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

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