update wiki URL
[oscam.git] / module-dvbapi-stapi5.c
blob7d2f1c2c9f0a3651fccc9c8219c45162006ff4b6
1 #define MODULE_LOG_PREFIX "dvbstapi"
3 #include "globals.h"
5 #if defined(HAVE_DVBAPI) && defined(WITH_STAPI5)
7 #include "module-dvbapi.h"
8 #include "module-dvbapi-stapi.h"
9 #include "oscam-client.h"
10 #include "oscam-files.h"
11 #include "oscam-string.h"
12 #include "oscam-time.h"
14 extern int32_t exit_oscam;
16 #define MAX_STREAMPIDS MAX_DEMUX + 1
18 struct tTkdDescInfo
20 int STREAMPIDs[MAX_STREAMPIDS];
21 uint32_t key_hndl;
22 uint32_t iv_hndl;
23 uint32_t path_hndl;
26 struct read_thread_param
28 int32_t id;
29 struct s_client *cli;
32 #define BUFFLEN 1024
33 #define PROCDIR "/proc/STAPI/stpti/"
34 #define MAX_DESCRAMBLER 16
35 #define TKD_MAX_NUMBER 1
37 /* These functions are in liboscam_stapi5.a */
38 extern char *oscam_stapi5_LibVersion(void);
39 extern uint32_t oscam_stapi5_Open(char *name, uint32_t *sessionhandle);
40 extern uint32_t oscam_stapi5_SignalAllocate(uint32_t sessionhandle, uint32_t *signalhandle);
41 extern uint32_t oscam_stapi5_FilterAllocate(uint32_t sessionhandle, uint32_t *filterhandle);
42 extern uint32_t oscam_stapi5_SlotInit(uint32_t sessionhandle, uint32_t signalhandle, uint32_t *bufferhandle, uint32_t *slothandle, uint16_t pid);
43 extern uint32_t oscam_stapi5_FilterSet(uint32_t filterhandle, uint8_t *filt, uint8_t *mask);
44 extern uint32_t oscam_stapi5_FilterAssociate(uint32_t filterhandle, uint32_t slothandle);
45 extern uint32_t oscam_stapi5_SlotDeallocate(uint32_t slothandle);
46 extern uint32_t oscam_stapi5_BufferDeallocate(uint32_t bufferhandle);
47 extern uint32_t oscam_stapi5_FilterDeallocate(uint32_t filterhandle, uint32_t bufferhandle, uint32_t slothandle);
48 extern uint32_t oscam_stapi5_Close(uint32_t sessionhandle);
49 extern const char *oscam_stapi5_GetRevision(void);
50 extern uint32_t oscam_stapi5_SignalWaitBuffer(uint32_t signalhandle, uint32_t *qbuffer, int32_t timeout);
51 extern uint32_t oscam_stapi5_SignalDisassociateBuffer(uint32_t signalhandle, uint32_t bufferhandle);
52 extern uint32_t oscam_stapi5_BufferReadSection(uint32_t bufferhandle, uint32_t *filterlist, int32_t maxfilter, uint32_t *filtercount, int32_t *crc, uint8_t *buf, int32_t bufsize, uint32_t *size);
53 extern uint32_t oscam_stapi5_SignalAbort(uint32_t signalhandle);
54 extern uint32_t oscam_stapi5_PidQuery(char *name, uint16_t pid);
55 extern uint32_t oscam_stapi5_BufferFlush(uint32_t bufferhandle);
56 extern uint32_t oscam_stapi5_SlotClearPid(uint32_t slot);
57 extern uint32_t oscam_stapi5_SlotUnlink(uint32_t slot);
59 extern const char *oscam_sttkd_GetRevision(void);
60 extern uint32_t oscam_sttkd_Open(char *name, uint32_t *sessionhandle);
61 extern uint32_t oscam_sttkd_Close(uint32_t tkdhandle);
62 extern uint32_t oscam_sttkd_Allocate(uint32_t tkdhandle, uint8_t cp, uint32_t *pathhandle, uint32_t *keyhandle);
63 extern uint32_t oscam_sttkd_Associate(char *name, uint32_t pathhandle, uint16_t Pid);
64 extern uint32_t oscam_sttkd_Deallocate(uint32_t pathhandle, uint32_t Keyhandle);
65 extern uint32_t oscam_sttkd_Disassociate(char *name, uint16_t pid);
66 extern uint32_t oscam_sttkd_KeyWrite(uint32_t keyhandle, uint8_t pol, const uint8_t *cw);
68 // Local functions
69 static void *stapi_read_thread(void *);
70 static int32_t stapi_do_set_filter(int32_t demux_id, FILTERTYPE *filter, uint16_t *pids, int32_t pidcount, uint8_t *filt, uint8_t *mask, int32_t dev_id);
71 static int32_t stapi_do_remove_filter(int32_t demux_id, FILTERTYPE *filter, int32_t dev_id);
73 // These variables are declared in module-dvbapi.c
74 extern int32_t disable_pmt_files;
75 extern struct s_dvbapi_priority *dvbapi_priority;
76 extern DEMUXTYPE demux[MAX_DEMUX];
78 static int32_t stapi_on;
79 static pthread_mutex_t filter_lock;
80 struct STDEVICE dev_list[PTINUM];
82 struct tTkdDescInfo tkd_desc_info[MAX_DESCRAMBLER];
84 static char TKD_DeviceName[TKD_MAX_NUMBER][16];
85 static uint32_t TKDHandle[TKD_MAX_NUMBER];
88 static void stapi_off(void)
90 int32_t i;
91 uint32_t ErrorCode;
93 SAFE_MUTEX_LOCK(&filter_lock);
95 cs_log("stapi shutdown");
97 disable_pmt_files = 1;
98 stapi_on = 0;
99 for(i = 0; i < MAX_DESCRAMBLER; i++)
101 dvbapi_stop_descrambling(i, 0);
103 if (tkd_desc_info[i].path_hndl != 0)
105 ErrorCode = oscam_sttkd_Deallocate(tkd_desc_info[i].path_hndl, tkd_desc_info[i].key_hndl);
106 if (ErrorCode != 0)
107 { cs_log("oscam_sttkd_Deallocate faild! ErrorCode: %d", ErrorCode); }
111 uint8_t TKD_InstanceID = 0;
112 for(TKD_InstanceID = 0; TKD_InstanceID < TKD_MAX_NUMBER; TKD_InstanceID++)
114 ErrorCode = oscam_sttkd_Close(TKDHandle[TKD_InstanceID]);
115 if(ErrorCode != 0)
116 { cs_log("oscam_sttkd_Close: ErrorCode: %d TKDHandle: 0x%08X", ErrorCode, TKDHandle[TKD_InstanceID]); }
119 for(i = 0; i < PTINUM; i++)
121 if(dev_list[i].SessionHandle > 0)
123 if(dev_list[i].SignalHandle > 0)
125 oscam_stapi5_SignalAbort(dev_list[i].SignalHandle);
127 pthread_cancel(dev_list[i].thread);
131 SAFE_MUTEX_UNLOCK(&filter_lock);
132 sleep(2);
133 return;
136 int32_t stapi_open(void)
138 uint32_t ErrorCode;
140 DIR *dirp;
141 struct dirent entry, *dp = NULL;
142 struct stat buf;
143 int32_t i;
144 char pfad[80];
145 stapi_on = 1;
146 int32_t stapi_priority = 0;
148 dirp = opendir(PROCDIR);
149 if(!dirp)
151 cs_log("opendir failed (errno=%d %s)", errno, strerror(errno));
152 return 0;
155 memset(dev_list, 0, sizeof(struct STDEVICE)*PTINUM);
157 if(dvbapi_priority)
159 struct s_dvbapi_priority *p;
160 for(p = dvbapi_priority; p != NULL; p = p->next)
162 if(p->type == 's')
164 stapi_priority = 1;
165 break;
170 if(!stapi_priority)
172 cs_log("WARNING: no PTI devices defined, stapi disabled");
173 return 0;
176 oscam_stapi5_GetRevision();
177 oscam_sttkd_GetRevision();
179 i = 0;
180 while(!cs_readdir_r(dirp, &entry, &dp))
182 if(!dp) { break; }
184 snprintf(pfad, sizeof(pfad), "%s%s", PROCDIR, dp->d_name);
185 if(stat(pfad, &buf) != 0)
186 { continue; }
188 if(!(buf.st_mode & S_IFDIR && strncmp(dp->d_name, ".", 1) != 0))
189 { continue; }
191 int32_t do_open = 0;
192 struct s_dvbapi_priority *p;
194 for(p = dvbapi_priority; p != NULL; p = p->next)
196 if(p->type != 's') { continue; }
197 if(strcmp(dp->d_name, p->devname) == 0)
199 do_open = 1;
200 break;
204 if(!do_open)
206 cs_log("PTI: %s skipped", dp->d_name);
207 continue;
210 ErrorCode = oscam_stapi5_Open(dp->d_name, &dev_list[i].SessionHandle);
211 if(ErrorCode != 0)
213 cs_log("STPTI_Open ErrorCode: %d", ErrorCode);
214 continue;
217 //debug
218 //oscam_stapi_Capability(dp->d_name);
220 cs_strncpy(dev_list[i].name, dp->d_name, sizeof(dev_list[i].name));
221 cs_log("PTI: %s open %d", dp->d_name, i);
223 ErrorCode = oscam_stapi5_SignalAllocate(dev_list[i].SessionHandle, &dev_list[i].SignalHandle);
224 if(ErrorCode != 0)
225 { cs_log("SignalAllocate: ErrorCode: %d SignalHandle: %x", ErrorCode, dev_list[i].SignalHandle); }
227 i++;
228 if(i >= PTINUM) { break; }
230 closedir(dirp);
232 if(i == 0) { return 0; }
234 uint8_t TKD_InstanceID = 0;
235 memset(&tkd_desc_info, 0, sizeof(tkd_desc_info[0]) * MAX_DESCRAMBLER);
237 for(TKD_InstanceID = 0; TKD_InstanceID < TKD_MAX_NUMBER; TKD_InstanceID++)
239 /* Generate the device name dynamically based upon the Instance ID */
240 snprintf(TKD_DeviceName[TKD_InstanceID], sizeof(TKD_DeviceName), "TKD_%02d", TKD_InstanceID);
242 ErrorCode = oscam_sttkd_Open(TKD_DeviceName[TKD_InstanceID], &TKDHandle[TKD_InstanceID]);
243 if(ErrorCode != 0)
244 cs_log("oscam_sttkd_Open: DeviceName: %s, TKDHandle: 0x%08X, ErrorCode: %d", TKD_DeviceName[TKD_InstanceID], TKDHandle[TKD_InstanceID], ErrorCode);
247 SAFE_MUTEX_INIT(&filter_lock, NULL);
249 for(i = 0; i < PTINUM; i++)
251 if(dev_list[i].SessionHandle == 0)
252 { continue; }
254 struct read_thread_param *para;
255 if(!cs_malloc(&para, sizeof(struct read_thread_param)))
256 { return 0; }
257 para->id = i;
258 para->cli = cur_client();
260 int32_t ret = start_thread("stapi read", stapi_read_thread, (void *)para, &dev_list[i].thread, 1, 0);
261 if(ret)
263 return 0;
267 atexit(stapi_off);
269 cs_log("liboscam_stapi5 v.%s initialized", oscam_stapi5_LibVersion());
270 return 1;
273 int32_t stapi_activate_section_filter(int32_t fd, uint8_t *filter, uint8_t *mask)
275 uint32_t ErrorCode;
277 ErrorCode = oscam_stapi5_FilterSet(fd, filter, mask);
278 if(ErrorCode != 0)
280 cs_log_dbg(D_DVBAPI, "Error: oscam_stapi5_FilterSet; %d", ErrorCode);
281 return -1;
284 return ErrorCode;
287 int32_t stapi_set_filter(int32_t demux_id, uint16_t pid, uint8_t *filter, uint8_t *mask, int32_t num, char *pmtfile)
289 int32_t i;
290 int32_t ret = -1;
291 char dest[1024];
292 uint16_t pids[1] = { pid };
293 struct s_dvbapi_priority *p;
295 if(!pmtfile)
297 cs_log_dbg(D_DVBAPI, "No valid pmtfile!");
298 return -1;
301 cs_log_dbg(D_DVBAPI, "pmt file %s demux_id %d", pmtfile, demux_id);
303 for(p = dvbapi_priority; p != NULL; p = p->next)
305 if(p->type != 's') { continue; } // stapi rule?
306 if(strcmp(pmtfile, p->pmtfile) != 0) { continue; } // same file?
308 for(i = 0; i < PTINUM; i++)
310 if(strcmp(dev_list[i].name, p->devname) == 0 && p->disablefilter == 0) // check device name and if filtering is enabled!
312 cs_log_dbg(D_DVBAPI, "set stapi filter on %s for pid %04X", dev_list[i].name, pids[0]);
313 ret = stapi_do_set_filter(demux_id, &dev_list[i].demux_fd[demux_id][num], pids, 1, filter, mask, i);
314 if(ret > 0) // success
316 demux[demux_id].dev_index = i;
317 cs_log_dbg(D_DVBAPI, "%s filter %d set (pid %04X)", dev_list[i].name, num, pid);
318 return ret; // return filternumber
320 else // failure
322 cs_log_dbg(D_DVBAPI, "Error setting new filter for pid %04X on %s!", pid, dev_list[i].name);
323 return -1; // set return to error
329 if(p == NULL)
331 cs_log_dbg(D_DVBAPI, "No matching S: line in oscam.dvbapi for pmtfile %s -> stop descrambling!", pmtfile);
332 snprintf(dest, sizeof(dest), "%s%s", TMPDIR, demux[demux_id].pmt_file);
333 unlink(dest); // remove obsolete pmt file
334 dvbapi_stop_descrambling(demux_id, 0);
336 return ret;
339 int32_t stapi_remove_filter(int32_t demux_id, int32_t num, char *pmtfile)
341 int32_t i, ret = 0;
342 struct s_dvbapi_priority *p;
344 if(!pmtfile) { return 0; }
346 for(p = dvbapi_priority; p != NULL; p = p->next)
348 if(p->type != 's') { continue; }
349 if(strcmp(pmtfile, p->pmtfile) != 0)
350 { continue; }
352 for(i = 0; i < PTINUM; i++)
354 if(strcmp(dev_list[i].name, p->devname) == 0 && p->disablefilter == 0)
356 ret = stapi_do_remove_filter(demux_id, &dev_list[i].demux_fd[demux_id][num], i);
360 if(ret == 1)
362 cs_log_dbg(D_DVBAPI, "filter %d removed", num);
364 else
366 cs_log_dbg(D_DVBAPI, "Error: filter %d was not removed!", num);
368 return ret;
371 static uint32_t check_slot(int32_t dev_id, uint32_t checkslot, FILTERTYPE *skipfilter)
373 int32_t d, f, l;
374 for(d = 0; d < MAX_DEMUX; d++)
376 for(f = 0; f < MAX_FILTER; f++)
378 if(skipfilter && &dev_list[dev_id].demux_fd[d][f] == skipfilter)
379 { continue; }
380 for(l = 0; l < dev_list[dev_id].demux_fd[d][f].NumSlots; l++)
382 if(checkslot == dev_list[dev_id].demux_fd[d][f].SlotHandle[l])
384 return dev_list[dev_id].demux_fd[d][f].BufferHandle[l];
389 return 0;
393 static int32_t stapi_do_set_filter(int32_t demux_id, FILTERTYPE *filter, uint16_t *pids, int32_t pidcount, uint8_t *filt, uint8_t *mask, int32_t dev_id)
395 uint32_t FilterAssociateError = 0;
396 int32_t k, ret = 0;
398 filter->fd = 0;
399 filter->BufferHandle[0] = 0;
400 filter->SlotHandle[0] = 0;
402 if(dev_list[dev_id].SessionHandle == 0) { return 0; }
404 uint32_t FilterAllocateError = oscam_stapi5_FilterAllocate(dev_list[dev_id].SessionHandle, &filter->fd);
406 if(FilterAllocateError != 0)
408 cs_log("FilterAllocate problem");
409 filter->fd = 0;
410 return 0;
413 uint32_t FilterSetError = oscam_stapi5_FilterSet(filter->fd, filt, mask);
415 for(k = 0; k < pidcount; k++)
417 uint16_t pid = pids[k];
419 uint32_t QuerySlot = oscam_stapi5_PidQuery(dev_list[dev_id].name, pid);
420 int32_t SlotInit = 1;
422 if(QuerySlot != 0)
424 uint32_t checkslot = check_slot(dev_id, QuerySlot, NULL);
425 if(checkslot > 0)
427 filter->SlotHandle[k] = QuerySlot;
428 filter->BufferHandle[k] = checkslot;
429 SlotInit = 0;
431 else
433 cs_log("overtake: clear pid, errorcode: %d", oscam_stapi5_SlotClearPid(QuerySlot));
434 SlotInit = 1;
438 if(SlotInit == 1)
440 ret = oscam_stapi5_SlotInit(dev_list[dev_id].SessionHandle, dev_list[dev_id].SignalHandle, &filter->BufferHandle[k], &filter->SlotHandle[k], pid);
443 FilterAssociateError = oscam_stapi5_FilterAssociate(filter->fd, filter->SlotHandle[k]);
444 filter->NumSlots++;
447 if(ret || FilterAllocateError || FilterAssociateError || FilterSetError)
449 cs_log("set_filter: dev: %d FAl: %d FAs: %d FS: %d",
450 dev_id, FilterAllocateError, FilterAssociateError, FilterSetError);
451 stapi_do_remove_filter(demux_id, filter, dev_id);
452 return 0;
454 else
456 return filter->fd; // return fd of filter
460 static int32_t stapi_do_remove_filter(int32_t UNUSED(demux_id), FILTERTYPE *filter, int32_t dev_id)
462 if(filter->fd == 0) { return 0; }
464 uint32_t BufferDeallocateError = 0, SlotDeallocateError = 0, FilterDeallocateError = 0;
466 if(dev_list[dev_id].SessionHandle == 0) { return 0; }
468 int32_t k;
469 for(k = 0; k < filter->NumSlots; k++)
471 uint32_t checkslot = check_slot(dev_id, filter->SlotHandle[k], filter);
473 if(checkslot == 0)
475 FilterDeallocateError = oscam_stapi5_FilterDeallocate(filter->fd, filter->BufferHandle[k], filter->SlotHandle[k]);
477 oscam_stapi5_SlotClearPid(filter->SlotHandle[k]);
478 oscam_stapi5_SlotUnlink(filter->SlotHandle[k]);
479 oscam_stapi5_SignalDisassociateBuffer(dev_list[dev_id].SignalHandle, filter->BufferHandle[k]);
481 BufferDeallocateError = oscam_stapi5_BufferDeallocate(filter->BufferHandle[k]);
482 SlotDeallocateError = oscam_stapi5_SlotDeallocate(filter->SlotHandle[k]);
487 memset(filter, 0, sizeof(FILTERTYPE));
489 if(BufferDeallocateError || SlotDeallocateError || FilterDeallocateError)
491 cs_log("remove_filter: dev: %d BD: %d SD: %d FDe: %d",
492 dev_id, BufferDeallocateError, SlotDeallocateError, FilterDeallocateError);
493 return 0;
495 else
497 return 1;
501 static void stapi_cleanup_thread(void *dev)
503 int32_t dev_index = (int)dev;
505 int32_t ErrorCode;
506 ErrorCode = oscam_stapi5_Close(dev_list[dev_index].SessionHandle);
508 cs_log("liboscam_stapi5: PTI %s closed - %d\n", dev_list[dev_index].name, ErrorCode);
509 dev_list[dev_index].SessionHandle = 0;
512 static void *stapi_read_thread(void *sparam)
514 int32_t dev_index, ErrorCode, i, j, CRCValid;
515 uint32_t QueryBufferHandle = 0, DataSize = 0;
516 uint8_t buf[BUFFLEN];
518 struct read_thread_param *para = sparam;
519 dev_index = para->id;
521 SAFE_SETSPECIFIC(getclient, para->cli);
522 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
523 pthread_cleanup_push(stapi_cleanup_thread, (void *) dev_index);
525 int32_t error_count = 0;
527 while(!exit_oscam)
529 QueryBufferHandle = 0;
530 ErrorCode = oscam_stapi5_SignalWaitBuffer(dev_list[dev_index].SignalHandle, &QueryBufferHandle, 1000);
532 switch(ErrorCode)
534 case 0: // NO_ERROR:
535 break;
536 case 852042: // ERROR_SIGNAL_ABORTED
537 cs_log("Caught abort signal");
538 pthread_exit(NULL);
539 break;
540 case 11: // ERROR_TIMEOUT:
541 //cs_log("timeout %d", dev_index);
542 //TODO: if pidindex == -1 try next
543 continue;
544 break;
545 default:
546 if(QueryBufferHandle != 0)
548 cs_log("SignalWaitBuffer error: %d", ErrorCode);
549 oscam_stapi5_BufferFlush(QueryBufferHandle);
550 continue;
552 cs_log("SignalWaitBuffer: index %d ErrorCode: %d - QueryBuffer: %x", dev_index, ErrorCode, QueryBufferHandle);
553 error_count++;
554 if(error_count > 10)
556 cs_log("Too many errors in reader thread %d, quitting.", dev_index);
557 pthread_exit(NULL);
559 continue;
560 break;
563 uint32_t NumFilterMatches = 0;
564 int32_t demux_id = 0, filter_num = 0;
565 DataSize = 0;
566 uint32_t k;
568 uint32_t MatchedFilterList[10];
569 ErrorCode = oscam_stapi5_BufferReadSection(QueryBufferHandle, MatchedFilterList, 10, &NumFilterMatches, &CRCValid, buf, BUFFLEN, &DataSize);
571 if(ErrorCode != 0)
573 cs_log("BufferRead: index: %d ErrorCode: %d", dev_index, ErrorCode);
574 cs_sleepms(1000);
575 continue;
578 if(DataSize <= 0)
579 { continue; }
581 SAFE_MUTEX_LOCK(&filter_lock); // don't use cs_lock() here; multiple threads using same s_client struct
582 for(k = 0; k < NumFilterMatches; k++)
584 for(i = 0; i < MAX_DEMUX; i++)
586 for(j = 0; j < MAX_FILTER; j++)
588 if(dev_list[dev_index].demux_fd[i][j].fd == MatchedFilterList[k])
590 demux_id = i;
591 filter_num = j;
593 dvbapi_process_input(demux_id, filter_num, buf, DataSize, 0);
598 SAFE_MUTEX_UNLOCK(&filter_lock);
601 pthread_cleanup_pop(0);
603 return NULL;
606 int32_t stapi_init_descrambler(int32_t dev_index)
608 int32_t ErrorCode;
610 if(dev_index >= MAX_DESCRAMBLER)
612 cs_log("TKD MAX_DESCRAMBLER reached!");
613 return 0;
616 ErrorCode = oscam_sttkd_Allocate(TKDHandle[0], 0, &tkd_desc_info[dev_index].path_hndl, &tkd_desc_info[dev_index].key_hndl);
617 if (ErrorCode != 0)
619 cs_log("oscam_sttkd_Allocate faild! ErrorCode: %d", ErrorCode);
620 return 0;
623 return 1;
626 int32_t stapi_set_pid(int32_t demux_id, int32_t UNUSED(num), uint32_t idx, uint16_t pid, char *UNUSED(pmtfile))
628 if(idx == INDEX_INVALID)
630 if (tkd_desc_info[demux[demux_id].dev_index].path_hndl != 0)
632 cs_log_dbg(D_DVBAPI, "stop descrambling of PID %d on %s", pid, dev_list[demux[demux_id].dev_index].name);
633 uint32_t ErrorCode = oscam_sttkd_Disassociate(dev_list[demux[demux_id].dev_index].name, pid);
634 if (ErrorCode != 0)
635 cs_log("oscam_sttkd_Disassociate faild! ErrorCode: %d", ErrorCode);
637 int i;
638 for (i = 0; i < MAX_STREAMPIDS; i++)
640 if (tkd_desc_info[demux[demux_id].dev_index].STREAMPIDs[i] == pid)
642 tkd_desc_info[demux[demux_id].dev_index].STREAMPIDs[i] = 0;
643 break;
650 return 1;
653 int32_t stapi_write_cw(int32_t demux_id, uint8_t *cw, uint16_t *STREAMpids, int32_t STREAMpidcount, char *UNUSED(pmtfile))
655 int32_t ErrorCode, l, x;
656 uint8_t nullcw[8];
657 memset(nullcw, 0, 8);
658 char *text[] = { "even", "odd" };
660 if(dev_list[demux[demux_id].dev_index].SessionHandle == 0) { return 0; }
662 // check if descrambler is started for this dev_index
663 if(tkd_desc_info[demux[demux_id].dev_index].path_hndl == 0)
665 if(!stapi_init_descrambler(demux[demux_id].dev_index))
667 cs_log_dbg(D_DVBAPI, "stapi_write_cw , faild to added descrambler for %s", dev_list[demux[demux_id].dev_index].name);
668 return 0;
672 // descrambler started, check each pid
673 for (x = 0; x < STREAMpidcount; x++)
675 int pid_associated = -1;
677 // search STREAMpids if path got associated
678 for (l = 0; l < MAX_STREAMPIDS; l++)
680 if (tkd_desc_info[demux[demux_id].dev_index].STREAMPIDs[l] == STREAMpids[x])
682 pid_associated = l;
683 break;
687 // if not associated add the pid
688 if(pid_associated < 0)
690 ErrorCode = oscam_sttkd_Associate(dev_list[demux[demux_id].dev_index].name, tkd_desc_info[demux[demux_id].dev_index].path_hndl, STREAMpids[x]);
691 if (ErrorCode != 0)
693 cs_log("stapi_write_cw , oscam_sttkd_Associate faild for pid %04X! ErrorCode: %d", STREAMpids[x], ErrorCode);
694 return 0;
697 // add the pid to the next free index
698 for (l = 0; l < MAX_STREAMPIDS; l++)
700 if (tkd_desc_info[demux[demux_id].dev_index].STREAMPIDs[l] == 0)
702 tkd_desc_info[demux[demux_id].dev_index].STREAMPIDs[l] = STREAMpids[x];
703 pid_associated = l;
704 break;
708 if (pid_associated < 0)
710 cs_log("stapi_write_cw , faild to associate pid %04X, maximum number of %d pids reached", STREAMpids[x], MAX_STREAMPIDS);
711 return 0;
716 //@theparasol: please verify this block is in the right place
717 int32_t pidnum = demux[demux_id].pidindex; // get current pidindex used for descrambling
718 uint32_t idx = demux[demux_id].ECMpids[pidnum].index[0];
720 if(idx == INDEX_INVALID) // if no indexer for this pid get one!
722 idx = dvbapi_get_desc_index(demux_id, pidnum, 0);
723 cs_log_dbg(D_DVBAPI, "Demuxer %d PID: %d CAID: %04X ECMPID: %04X is using index %d", demux_id, pidnum,
724 demux[demux_id].ECMpids[pidnum].CAID, demux[demux_id].ECMpids[pidnum].ECM_PID, idx);
728 for(l = 0; l < 2; l++)
730 // Skip check for BISS1 - cw could be indeed zero
731 // Skip check for BISS2 - we use the extended cw, so the "simple" cw is always zero
732 if(memcmp(cw + (l * 8), demux[demux_id].last_cw[0][l], 8) != 0
733 && (memcmp(cw + (l * 8), nullcw, 8) != 0 || caid_is_biss(demux[demux_id].ECMpids[pidnum].CAID)))
735 ErrorCode = oscam_sttkd_KeyWrite(tkd_desc_info[demux[demux_id].dev_index].key_hndl, l, cw + (l * 8));
737 memcpy(demux[demux_id].last_cw[0][l], cw + (l * 8), 8);
738 cs_log_dbg(D_DVBAPI, "write cw %s index: %d on %s", text[l], demux_id, dev_list[demux[demux_id].dev_index].name);
742 return 1;
745 #endif