source: trunk/module-dvbapi-stapi.c@ 8439

Last change on this file since 8439 was 8439, checked in by gf, 9 years ago

webif/dvbapi: Do not prefix log messages comming from WebIf with "dvbapi: ".

module-dvbapi.h redefines cs_log() to include "dvbapi: " prefix.

Since module-webif.c includes module-dvbapi.h all cs_log lines coming
from webif were wrongly were prefixed with "dvbapi: ".

  • Property svn:eol-style set to LF
File size: 14.4 KB
Line 
1#include "globals.h"
2
3#if defined(HAVE_DVBAPI) && defined(WITH_STAPI)
4
5#define DVBAPI_LOG_PREFIX 1
6#include "module-dvbapi.h"
7#include "module-dvbapi-stapi.h"
8#include "oscam-client.h"
9#include "oscam-files.h"
10#include "oscam-string.h"
11#include "oscam-time.h"
12
13// These variables are declared in module-dvbapi.c
14extern int32_t disable_pmt_files;
15extern struct s_dvbapi_priority *dvbapi_priority;
16extern DEMUXTYPE demux[MAX_DEMUX];
17
18static int32_t stapi_on = 0;
19static pthread_mutex_t filter_lock;
20static struct STDEVICE dev_list[PTINUM];
21
22void stapi_off(void) {
23 int32_t i;
24
25 pthread_mutex_lock(&filter_lock);
26
27 cs_log("stapi shutdown");
28
29 disable_pmt_files=1;
30 stapi_on=0;
31
32 for (i=0;i<MAX_DEMUX;i++)
33 dvbapi_stop_descrambling(i);
34
35 for (i=0;i<PTINUM;i++) {
36 if (dev_list[i].SessionHandle>0) {
37 if (dev_list[i].SignalHandle > 0) {
38 oscam_stapi_SignalAbort(dev_list[i].SignalHandle);
39 }
40 pthread_cancel(dev_list[i].thread);
41 }
42 }
43
44 pthread_mutex_unlock(&filter_lock);
45 sleep(2);
46 return;
47}
48
49int32_t stapi_open(void) {
50 uint32_t ErrorCode;
51
52 DIR *dirp;
53 struct dirent entry, *dp = NULL;
54 struct stat buf;
55 int32_t i;
56 char pfad[80];
57 stapi_on=1;
58 int32_t stapi_priority=0;
59
60 dirp = opendir(PROCDIR);
61 if (!dirp) {
62 cs_log("opendir failed (errno=%d %s)", errno, strerror(errno));
63 return 0;
64 }
65
66 memset(dev_list, 0, sizeof(struct STDEVICE)*PTINUM);
67
68 if (dvbapi_priority) {
69 struct s_dvbapi_priority *p;
70 for (p=dvbapi_priority; p != NULL; p=p->next) {
71 if (p->type=='s') {
72 stapi_priority=1;
73 break;
74 }
75 }
76 }
77
78 if (!stapi_priority) {
79 cs_log("WARNING: no PTI devices defined, stapi disabled");
80 return 0;
81 }
82
83 oscam_stapi_CheckVersion();
84
85 i=0;
86 while (!cs_readdir_r(dirp, &entry, &dp)) {
87 if (!dp) break;
88
89 snprintf(pfad, sizeof(pfad), "%s%s", PROCDIR, dp->d_name);
90 if (stat(pfad,&buf) != 0)
91 continue;
92
93 if (!(buf.st_mode & S_IFDIR && strncmp(dp->d_name, ".", 1)!=0))
94 continue;
95
96 int32_t do_open=0;
97 struct s_dvbapi_priority *p;
98
99 for (p=dvbapi_priority; p != NULL; p=p->next) {
100 if (p->type!='s') continue;
101 if(strcmp(dp->d_name, p->devname)==0) {
102 do_open=1;
103 break;
104 }
105 }
106
107 if (!do_open) {
108 cs_log("PTI: %s skipped", dp->d_name);
109 continue;
110 }
111
112 ErrorCode= oscam_stapi_Open(dp->d_name, &dev_list[i].SessionHandle);
113 if (ErrorCode != 0) {
114 cs_log("STPTI_Open ErrorCode: %d", ErrorCode);
115 continue;
116 }
117
118 //debug
119 //oscam_stapi_Capability(dp->d_name);
120
121 cs_strncpy(dev_list[i].name,dp->d_name, sizeof(dev_list[i].name));
122 cs_log("PTI: %s open %d", dp->d_name, i);
123
124 ErrorCode = oscam_stapi_SignalAllocate(dev_list[i].SessionHandle, &dev_list[i].SignalHandle);
125 if (ErrorCode != 0)
126 cs_log("SignalAllocate: ErrorCode: %d SignalHandle: %x", ErrorCode, dev_list[i].SignalHandle);
127
128 i++;
129 if (i>=PTINUM) break;
130 }
131 closedir(dirp);
132
133 if (i==0) return 0;
134
135 pthread_mutex_init(&filter_lock, NULL);
136
137 for (i=0;i<PTINUM;i++) {
138 if (dev_list[i].SessionHandle==0)
139 continue;
140
141 struct read_thread_param *para;
142 if (!cs_malloc(&para, sizeof(struct read_thread_param)))
143 return 0;
144 para->id=i;
145 para->cli=cur_client();
146
147 int32_t ret = pthread_create(&dev_list[i].thread, NULL, stapi_read_thread, (void *)para);
148 if(ret){
149 cs_log("ERROR: can't create stapi read thread (errno=%d %s)", ret, strerror(ret));
150 return 0;
151 } else
152 pthread_detach(dev_list[i].thread);
153 }
154
155 atexit(stapi_off);
156
157 cs_log("liboscam_stapi v.%s initialized", oscam_stapi_LibVersion());
158 return 1;
159}
160
161int32_t stapi_set_filter(int32_t demux_id, uint16_t pid, uchar *filter, uchar *mask, int32_t num, char *pmtfile) {
162 int32_t i;
163 uint16_t pids[1] = { pid };
164 struct s_dvbapi_priority *p;
165
166 if (!pmtfile) return 0;
167
168 cs_debug_mask(D_DVBAPI, "pmt file %s demux_id %d", pmtfile, demux_id);
169
170 for (p=dvbapi_priority; p != NULL; p=p->next) {
171 if (p->type!='s') continue;
172 if (strcmp(pmtfile, p->pmtfile)!=0)
173 continue;
174
175 for (i=0;i<PTINUM;i++) {
176 if(strcmp(dev_list[i].name, p->devname)==0 && p->disablefilter==0) {
177 cs_debug_mask(D_DVBAPI, "set stapi filter on %s for pid %04X", dev_list[i].name, pids[0]);
178 stapi_do_set_filter(demux_id, &dev_list[i].demux_fd[demux_id][num], pids, 1, filter, mask, i);
179 }
180 }
181 }
182
183 cs_debug_mask(D_DVBAPI, "filter #%d set (pid %04X)", num, pid);
184 return 1;
185}
186
187int32_t stapi_remove_filter(int32_t demux_id, int32_t num, char *pmtfile) {
188 int32_t i;
189 struct s_dvbapi_priority *p;
190
191 if (!pmtfile) return 0;
192
193 for (p=dvbapi_priority; p != NULL; p=p->next) {
194 if (p->type!='s') continue;
195 if (strcmp(pmtfile, p->pmtfile)!=0)
196 continue;
197
198 for (i=0;i<PTINUM;i++) {
199 if(strcmp(dev_list[i].name, p->devname)==0 && p->disablefilter==0) {
200 stapi_do_remove_filter(demux_id, &dev_list[i].demux_fd[demux_id][num], i);
201 }
202 }
203 }
204
205 cs_debug_mask(D_DVBAPI, "filter #%d removed", num);
206 return 1;
207}
208
209uint32_t check_slot(int32_t dev_id, uint32_t checkslot, FILTERTYPE *skipfilter) {
210 int32_t d,f,l;
211 for (d=0; d<MAX_DEMUX; d++) {
212 for (f=0; f<MAX_FILTER; f++) {
213 if (skipfilter && &dev_list[dev_id].demux_fd[d][f] == skipfilter)
214 continue;
215 for (l=0; l<dev_list[dev_id].demux_fd[d][f].NumSlots; l++) {
216 if (checkslot == dev_list[dev_id].demux_fd[d][f].SlotHandle[l]) {
217 return dev_list[dev_id].demux_fd[d][f].BufferHandle[l];
218 }
219 }
220 }
221 }
222 return 0;
223}
224
225
226int32_t stapi_do_set_filter(int32_t demux_id, FILTERTYPE *filter, uint16_t *pids, int32_t pidcount, uchar *filt, uchar *mask, int32_t dev_id) {
227 uint32_t FilterAssociateError=0;
228 int32_t k, ret=0;
229
230 filter->fd = 0;
231 filter->BufferHandle[0] = 0;
232 filter->SlotHandle[0] = 0;
233
234 if (dev_list[dev_id].SessionHandle==0) return 0;
235
236 uint32_t FilterAllocateError = oscam_stapi_FilterAllocate(dev_list[dev_id].SessionHandle, &filter->fd);
237
238 if (FilterAllocateError != 0) {
239 cs_log("FilterAllocate problem");
240 filter->fd=0;
241 return 0;
242 }
243
244 for (k=0;k<pidcount;k++) {
245 uint16_t pid = pids[k];
246
247 uint32_t QuerySlot = oscam_stapi_PidQuery(dev_list[dev_id].name, pid);
248 int32_t SlotInit=1;
249
250 if (QuerySlot != 0) {
251 uint32_t checkslot = check_slot(dev_id, QuerySlot, NULL);
252 if (checkslot>0) {
253 filter->SlotHandle[k] = QuerySlot;
254 filter->BufferHandle[k] = checkslot;
255 SlotInit=0;
256 } else {
257 cs_log("overtake: clear pid: %d", oscam_stapi_SlotClearPid(QuerySlot));
258 SlotInit=1;
259 }
260 }
261
262 if (SlotInit==1) {
263 ret = oscam_stapi_SlotInit(dev_list[dev_id].SessionHandle, dev_list[dev_id].SignalHandle, &filter->BufferHandle[k], &filter->SlotHandle[k], pid);
264 }
265
266 FilterAssociateError = oscam_stapi_FilterAssociate(filter->fd, filter->SlotHandle[k]);
267 filter->NumSlots++;
268 }
269
270 uint32_t FilterSetError = oscam_stapi_FilterSet(filter->fd, filt, mask);
271
272 if (ret || FilterAllocateError || FilterAssociateError || FilterSetError) {
273 cs_log("set_filter: dev: %d FAl: %d FAs: %d FS: %d",
274 dev_id, FilterAllocateError, FilterAssociateError, FilterSetError);
275 stapi_do_remove_filter(demux_id, filter, dev_id);
276 return 0;
277 } else {
278 return 1;
279 }
280}
281
282int32_t stapi_do_remove_filter(int32_t UNUSED(demux_id), FILTERTYPE *filter, int32_t dev_id) {
283 if (filter->fd==0) return 0;
284
285 uint32_t BufferDeallocateError=0, SlotDeallocateError=0;
286
287 if (dev_list[dev_id].SessionHandle==0) return 0;
288
289 int32_t k;
290 for (k=0;k<filter->NumSlots;k++) {
291 uint32_t checkslot = check_slot(dev_id, filter->SlotHandle[k], filter);
292
293 if (checkslot==0) {
294 BufferDeallocateError = oscam_stapi_BufferDeallocate(filter->BufferHandle[k]);
295 SlotDeallocateError = oscam_stapi_SlotDeallocate(filter->SlotHandle[k]);
296 }
297 }
298 uint32_t FilterDeallocateError = oscam_stapi_FilterDeallocate(filter->fd);
299
300 memset(filter, 0, sizeof(FILTERTYPE));
301
302 if (BufferDeallocateError||SlotDeallocateError||FilterDeallocateError) {
303 cs_log("remove_filter: dev: %d BD: %d SD: %d FDe: %d",
304 dev_id, BufferDeallocateError, SlotDeallocateError, FilterDeallocateError);
305 return 0;
306 } else {
307 return 1;
308 }
309}
310
311void stapi_cleanup_thread(void *dev){
312 int32_t dev_index = (int)dev;
313
314 int32_t ErrorCode;
315 ErrorCode = oscam_stapi_Close(dev_list[dev_index].SessionHandle);
316
317 printf("liboscam_stapi: PTI %s closed - %d\n", dev_list[dev_index].name, ErrorCode);
318 dev_list[dev_index].SessionHandle=0;
319}
320
321void *stapi_read_thread(void *sparam) {
322 int32_t dev_index, ErrorCode, i, j, CRCValid;
323 uint32_t QueryBufferHandle = 0, DataSize = 0;
324 uchar buf[BUFFLEN];
325
326 struct read_thread_param *para = sparam;
327 dev_index = para->id;
328
329 pthread_setspecific(getclient, para->cli);
330 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
331 pthread_cleanup_push(stapi_cleanup_thread, (void*) dev_index);
332
333 int32_t error_count = 0;
334
335 while (1) {
336 QueryBufferHandle = 0;
337 ErrorCode = oscam_stapi_SignalWaitBuffer(dev_list[dev_index].SignalHandle, &QueryBufferHandle, 1000);
338
339 switch (ErrorCode) {
340 case 0: // NO_ERROR:
341 break;
342 case 852042: // ERROR_SIGNAL_ABORTED
343 cs_log("Caught abort signal");
344 pthread_exit(NULL);
345 break;
346 case 11: // ERROR_TIMEOUT:
347 //cs_log("timeout %d", dev_index);
348 //TODO: if pidindex == -1 try next
349 continue;
350 break;
351 default:
352 if (QueryBufferHandle != 0) {
353 cs_log("SignalWaitBuffer error: %d", ErrorCode);
354 oscam_stapi_BufferFlush(QueryBufferHandle);
355 continue;
356 }
357 cs_log("SignalWaitBuffer: index %d ErrorCode: %d - QueryBuffer: %x", dev_index, ErrorCode, QueryBufferHandle);
358 error_count++;
359 if (error_count>10) {
360 cs_log("Too many errors in reader thread %d, quitting.", dev_index);
361 pthread_exit(NULL);
362 }
363 continue;
364 break;
365 }
366
367 uint32_t NumFilterMatches = 0;
368 int32_t demux_id = 0, filter_num = 0;
369 DataSize = 0;
370 uint32_t k;
371
372 uint32_t MatchedFilterList[10];
373 ErrorCode = oscam_stapi_BufferReadSection(QueryBufferHandle, MatchedFilterList, 10, &NumFilterMatches, &CRCValid, buf, BUFFLEN, &DataSize);
374
375 if (ErrorCode != 0) {
376 cs_log("BufferRead: index: %d ErrorCode: %d", dev_index, ErrorCode);
377 cs_sleepms(1000);
378 continue;
379 }
380
381 if (DataSize<=0)
382 continue;
383
384 pthread_mutex_lock(&filter_lock); // don't use cs_lock() here; multiple threads using same s_client struct
385 for(k=0;k<NumFilterMatches;k++) {
386 for (i=0;i<MAX_DEMUX;i++) {
387 for (j=0;j<MAX_FILTER;j++) {
388 if (dev_list[dev_index].demux_fd[i][j].fd == MatchedFilterList[k]) {
389 demux_id=i;
390 filter_num=j;
391
392 dvbapi_process_input(demux_id, filter_num, buf, DataSize);
393 }
394 }
395 }
396 }
397 pthread_mutex_unlock(&filter_lock);
398 }
399 pthread_cleanup_pop(0);
400}
401
402#define ASSOCIATE 1
403#define DISASSOCIATE 0
404
405#define DE_START 0
406#define DE_STOP 1
407
408void stapi_DescramblerAssociate(int32_t demux_id, uint16_t pid, int32_t mode, int32_t n) {
409 uint32_t Slot=0;
410 int32_t ErrorCode=0;
411
412 if (dev_list[n].SessionHandle==0) return;
413
414 Slot = oscam_stapi_PidQuery(dev_list[n].name, pid);
415 if (!Slot) return;
416
417 if (demux[demux_id].DescramblerHandle[n]==0) return;
418
419 if (mode == ASSOCIATE) {
420 int32_t k;
421 for (k=0;k<SLOTNUM;k++) {
422 if (demux[demux_id].slot_assc[n][k]==Slot) {
423 return;
424 }
425 }
426
427 ErrorCode = oscam_stapi_DescramblerAssociate(demux[demux_id].DescramblerHandle[n], Slot);
428 cs_debug_mask(D_DVBAPI, "set pid %04x on %s", pid, dev_list[n].name);
429
430 if (ErrorCode != 0)
431 cs_log("DescramblerAssociate %d",ErrorCode);
432
433 for (k=0;k<SLOTNUM;k++) {
434 if (demux[demux_id].slot_assc[n][k]==0) {
435 demux[demux_id].slot_assc[n][k]=Slot;
436 break;
437 }
438 }
439 } else {
440 ErrorCode = oscam_stapi_DescramblerDisassociate(demux[demux_id].DescramblerHandle[n], Slot);
441 if (ErrorCode != 0)
442 cs_debug_mask(D_DVBAPI, "DescramblerDisassociate %d", ErrorCode);
443
444 cs_debug_mask(D_DVBAPI, "unset pid %04x on %s", pid, dev_list[n].name);
445
446 int32_t k;
447 for (k=0;k<SLOTNUM;k++) {
448 if (demux[demux_id].slot_assc[n][k]==Slot) {
449 demux[demux_id].slot_assc[n][k]=0;
450 return;
451 }
452 }
453 }
454
455 return;
456}
457
458void stapi_startdescrambler(int32_t demux_id, int32_t dev_index, int32_t mode) {
459 int32_t ErrorCode;
460
461 if (mode == DE_START && demux[demux_id].DescramblerHandle[dev_index] == 0) {
462 uint32_t DescramblerHandle=0;
463 ErrorCode = oscam_stapi_DescramblerAllocate(dev_list[dev_index].SessionHandle, &DescramblerHandle);
464 if (ErrorCode != 0) {
465 cs_log("DescramblerAllocate: ErrorCode: %d SignalHandle: %x", ErrorCode, dev_list[dev_index].SignalHandle);
466 return;
467 }
468
469 demux[demux_id].DescramblerHandle[dev_index]=DescramblerHandle;
470 }
471
472 if (mode == DE_STOP && demux[demux_id].DescramblerHandle[dev_index] > 0) {
473 ErrorCode = oscam_stapi_DescramblerDeallocate(demux[demux_id].DescramblerHandle[dev_index]);
474
475 if (ErrorCode != 0)
476 cs_log("DescramblerDeallocate: ErrorCode: %d", ErrorCode);
477
478 demux[demux_id].DescramblerHandle[dev_index]=0;
479 }
480
481 return;
482}
483
484int32_t stapi_set_pid(int32_t demux_id, int32_t UNUSED(num), int32_t idx, uint16_t UNUSED(pid), char *UNUSED(pmtfile)) {
485 int32_t n;
486
487 if (idx==-1) {
488 for (n=0;n<PTINUM;n++) {
489 if (demux[demux_id].DescramblerHandle[n]==0) continue;
490
491 cs_debug_mask(D_DVBAPI, "stop descrambling PTI: %s", dev_list[n].name);
492 stapi_startdescrambler(demux_id, n, DE_STOP);
493 memset(demux[demux_id].slot_assc[n], 0, sizeof(demux[demux_id].slot_assc[n]));
494 }
495 }
496
497 return 1;
498}
499
500int32_t stapi_write_cw(int32_t demux_id, uchar *cw, uint16_t *STREAMpids, int32_t STREAMpidcount, char *pmtfile) {
501 int32_t ErrorCode, l, n, k;
502 unsigned char nullcw[8];
503 memset(nullcw, 0, 8);
504 char *text[] = { "even", "odd" };
505
506 if (!pmtfile) return 0;
507
508 for (n=0;n<PTINUM;n++) {
509 if (dev_list[n].SessionHandle==0) continue;
510 if (demux[demux_id].DescramblerHandle[n]==0) {
511 struct s_dvbapi_priority *p;
512
513 for (p=dvbapi_priority; p != NULL; p=p->next) {
514 if (p->type!='s') continue;
515 if (strcmp(pmtfile, p->pmtfile)!=0)
516 continue;
517
518 if(strcmp(dev_list[n].name, p->devname)==0) {
519 cs_debug_mask(D_DVBAPI, "start descrambling PTI: %s", dev_list[n].name);
520 stapi_startdescrambler(demux_id, n, DE_START);
521 }
522 }
523 }
524
525 if (demux[demux_id].DescramblerHandle[n] == 0) continue;
526 for (k=0;k<STREAMpidcount;k++) {
527 stapi_DescramblerAssociate(demux_id, STREAMpids[k], ASSOCIATE, n);
528 }
529 }
530
531 for (l=0;l<2;l++) {
532 if (memcmp(cw+(l*8), demux[demux_id].lastcw[l], 8)!=0 && memcmp(cw+(l*8),nullcw,8)!=0) {
533 for (n=0;n<PTINUM;n++) {
534 if (demux[demux_id].DescramblerHandle[n]==0) continue;
535
536 ErrorCode = oscam_stapi_DescramblerSet(demux[demux_id].DescramblerHandle[n], l, cw+(l*8));
537 if (ErrorCode != 0)
538 cs_log("DescramblerSet: ErrorCode: %d", ErrorCode);
539
540 memcpy(demux[demux_id].lastcw[l],cw+(l*8),8);
541 cs_debug_mask(D_DVBAPI, "write cw %s index: %d %s", text[l], demux_id, dev_list[n].name);
542 }
543 }
544 }
545
546 return 1;
547}
548
549// Needed for compatability with liboscam_stapi.a
550#undef cs_log
551void cs_log(const char *fmt, ...) {
552 va_list params;
553 char log_txt[512];
554
555 va_start(params, fmt);
556 vsnprintf(log_txt, sizeof(log_txt), fmt, params);
557 va_end(params);
558
559 cs_log_int(0, 1, NULL, 0, log_txt);
560}
561
562#endif
Note: See TracBrowser for help on using the repository browser.