- fix Building without Nagra not possible at Nagra_Merlin https://trac.streamboard...
[oscam.git] / module-dvbapi-stapi5.c
blob2bd07a4efc72cb59a955808e63185256a846a75c
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[512];
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);
156 memset(pfad, 0, sizeof(pfad));
158 if(dvbapi_priority)
160 struct s_dvbapi_priority *p;
161 for(p = dvbapi_priority; p != NULL; p = p->next)
163 if(p->type == 's')
165 stapi_priority = 1;
166 break;
171 if(!stapi_priority)
173 cs_log("WARNING: no PTI devices defined, stapi disabled");
174 return 0;
177 oscam_stapi5_GetRevision();
178 oscam_sttkd_GetRevision();
180 i = 0;
181 while(!cs_readdir_r(dirp, &entry, &dp))
183 if(!dp) { break; }
185 snprintf(pfad, sizeof(pfad), "%s%s", PROCDIR, dp->d_name);
186 if(stat(pfad, &buf) != 0)
187 { continue; }
189 if(!(buf.st_mode & S_IFDIR && strncmp(dp->d_name, ".", 1) != 0))
190 { continue; }
192 int32_t do_open = 0;
193 struct s_dvbapi_priority *p;
195 for(p = dvbapi_priority; p != NULL; p = p->next)
197 if(p->type != 's') { continue; }
198 if(strcmp(dp->d_name, p->devname) == 0)
200 do_open = 1;
201 break;
205 if(!do_open)
207 cs_log("PTI: %s skipped", dp->d_name);
208 continue;
211 ErrorCode = oscam_stapi5_Open(dp->d_name, &dev_list[i].SessionHandle);
212 if(ErrorCode != 0)
214 cs_log("STPTI_Open ErrorCode: %d", ErrorCode);
215 continue;
218 //debug
219 //oscam_stapi_Capability(dp->d_name);
221 cs_strncpy(dev_list[i].name, dp->d_name, sizeof(dev_list[i].name));
222 cs_log("PTI: %s open %d", dp->d_name, i);
224 ErrorCode = oscam_stapi5_SignalAllocate(dev_list[i].SessionHandle, &dev_list[i].SignalHandle);
225 if(ErrorCode != 0)
226 { cs_log("SignalAllocate: ErrorCode: %d SignalHandle: %x", ErrorCode, dev_list[i].SignalHandle); }
228 i++;
229 if(i >= PTINUM) { break; }
231 closedir(dirp);
233 if(i == 0) { return 0; }
235 uint8_t TKD_InstanceID = 0;
236 memset(&tkd_desc_info, 0, sizeof(tkd_desc_info[0]) * MAX_DESCRAMBLER);
238 for(TKD_InstanceID = 0; TKD_InstanceID < TKD_MAX_NUMBER; TKD_InstanceID++)
240 /* Generate the device name dynamically based upon the Instance ID */
241 snprintf(TKD_DeviceName[TKD_InstanceID], sizeof(TKD_DeviceName), "TKD_%02d", TKD_InstanceID);
243 ErrorCode = oscam_sttkd_Open(TKD_DeviceName[TKD_InstanceID], &TKDHandle[TKD_InstanceID]);
244 if(ErrorCode != 0)
245 cs_log("oscam_sttkd_Open: DeviceName: %s, TKDHandle: 0x%08X, ErrorCode: %d", TKD_DeviceName[TKD_InstanceID], TKDHandle[TKD_InstanceID], ErrorCode);
248 SAFE_MUTEX_INIT(&filter_lock, NULL);
250 for(i = 0; i < PTINUM; i++)
252 if(dev_list[i].SessionHandle == 0)
253 { continue; }
255 struct read_thread_param *para;
256 if(!cs_malloc(&para, sizeof(struct read_thread_param)))
257 { return 0; }
258 para->id = i;
259 para->cli = cur_client();
261 int32_t ret = start_thread("stapi read", stapi_read_thread, (void *)para, &dev_list[i].thread, 1, 0);
262 if(ret)
264 return 0;
268 atexit(stapi_off);
270 cs_log("liboscam_stapi5 v.%s initialized", oscam_stapi5_LibVersion());
271 return 1;
274 int32_t stapi_activate_section_filter(int32_t fd, uint8_t *filter, uint8_t *mask)
276 uint32_t ErrorCode;
278 ErrorCode = oscam_stapi5_FilterSet(fd, filter, mask);
279 if(ErrorCode != 0)
281 cs_log_dbg(D_DVBAPI, "Error: oscam_stapi5_FilterSet; %d", ErrorCode);
282 return -1;
285 return ErrorCode;
288 int32_t stapi_set_filter(int32_t demux_id, uint16_t pid, uint8_t *filter, uint8_t *mask, int32_t num, char *pmtfile)
290 int32_t i;
291 int32_t ret = -1;
292 char dest[1024];
293 uint16_t pids[1] = { pid };
294 struct s_dvbapi_priority *p;
296 if(!pmtfile)
298 cs_log_dbg(D_DVBAPI, "No valid pmtfile!");
299 return -1;
302 cs_log_dbg(D_DVBAPI, "pmt file %s demux_id %d", pmtfile, demux_id);
304 for(p = dvbapi_priority; p != NULL; p = p->next)
306 if(p->type != 's') { continue; } // stapi rule?
307 if(strcmp(pmtfile, p->pmtfile) != 0) { continue; } // same file?
309 for(i = 0; i < PTINUM; i++)
311 if(strcmp(dev_list[i].name, p->devname) == 0 && p->disablefilter == 0) // check device name and if filtering is enabled!
313 cs_log_dbg(D_DVBAPI, "set stapi filter on %s for pid %04X", dev_list[i].name, pids[0]);
314 ret = stapi_do_set_filter(demux_id, &dev_list[i].demux_fd[demux_id][num], pids, 1, filter, mask, i);
315 if(ret > 0) // success
317 demux[demux_id].dev_index = i;
318 cs_log_dbg(D_DVBAPI, "%s filter %d set (pid %04X)", dev_list[i].name, num, pid);
319 return ret; // return filternumber
321 else // failure
323 cs_log_dbg(D_DVBAPI, "Error setting new filter for pid %04X on %s!", pid, dev_list[i].name);
324 return -1; // set return to error
330 if(p == NULL)
332 cs_log_dbg(D_DVBAPI, "No matching S: line in oscam.dvbapi for pmtfile %s -> stop descrambling!", pmtfile);
333 snprintf(dest, sizeof(dest), "%s%s", TMPDIR, demux[demux_id].pmt_file);
334 unlink(dest); // remove obsolete pmt file
335 dvbapi_stop_descrambling(demux_id, 0);
337 return ret;
340 int32_t stapi_remove_filter(int32_t demux_id, int32_t num, char *pmtfile)
342 int32_t i, ret = 0;
343 struct s_dvbapi_priority *p;
345 if(!pmtfile) { return 0; }
347 for(p = dvbapi_priority; p != NULL; p = p->next)
349 if(p->type != 's') { continue; }
350 if(strcmp(pmtfile, p->pmtfile) != 0)
351 { continue; }
353 for(i = 0; i < PTINUM; i++)
355 if(strcmp(dev_list[i].name, p->devname) == 0 && p->disablefilter == 0)
357 ret = stapi_do_remove_filter(demux_id, &dev_list[i].demux_fd[demux_id][num], i);
361 if(ret == 1)
363 cs_log_dbg(D_DVBAPI, "filter %d removed", num);
365 else
367 cs_log_dbg(D_DVBAPI, "Error: filter %d was not removed!", num);
369 return ret;
372 static uint32_t check_slot(int32_t dev_id, uint32_t checkslot, FILTERTYPE *skipfilter)
374 int32_t d, f, l;
375 for(d = 0; d < MAX_DEMUX; d++)
377 for(f = 0; f < MAX_FILTER; f++)
379 if(skipfilter && &dev_list[dev_id].demux_fd[d][f] == skipfilter)
380 { continue; }
381 for(l = 0; l < dev_list[dev_id].demux_fd[d][f].NumSlots; l++)
383 if(checkslot == dev_list[dev_id].demux_fd[d][f].SlotHandle[l])
385 return dev_list[dev_id].demux_fd[d][f].BufferHandle[l];
390 return 0;
394 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)
396 uint32_t FilterAssociateError = 0;
397 int32_t k, ret = 0;
399 filter->fd = 0;
400 filter->BufferHandle[0] = 0;
401 filter->SlotHandle[0] = 0;
403 if(dev_list[dev_id].SessionHandle == 0) { return 0; }
405 uint32_t FilterAllocateError = oscam_stapi5_FilterAllocate(dev_list[dev_id].SessionHandle, &filter->fd);
407 if(FilterAllocateError != 0)
409 cs_log("FilterAllocate problem");
410 filter->fd = 0;
411 return 0;
414 uint32_t FilterSetError = oscam_stapi5_FilterSet(filter->fd, filt, mask);
416 for(k = 0; k < pidcount; k++)
418 uint16_t pid = pids[k];
420 uint32_t QuerySlot = oscam_stapi5_PidQuery(dev_list[dev_id].name, pid);
421 int32_t SlotInit = 1;
423 if(QuerySlot != 0)
425 uint32_t checkslot = check_slot(dev_id, QuerySlot, NULL);
426 if(checkslot > 0)
428 filter->SlotHandle[k] = QuerySlot;
429 filter->BufferHandle[k] = checkslot;
430 SlotInit = 0;
432 else
434 cs_log("overtake: clear pid, errorcode: %d", oscam_stapi5_SlotClearPid(QuerySlot));
435 SlotInit = 1;
439 if(SlotInit == 1)
441 ret = oscam_stapi5_SlotInit(dev_list[dev_id].SessionHandle, dev_list[dev_id].SignalHandle, &filter->BufferHandle[k], &filter->SlotHandle[k], pid);
444 FilterAssociateError = oscam_stapi5_FilterAssociate(filter->fd, filter->SlotHandle[k]);
445 filter->NumSlots++;
448 if(ret || FilterAllocateError || FilterAssociateError || FilterSetError)
450 cs_log("set_filter: dev: %d FAl: %d FAs: %d FS: %d",
451 dev_id, FilterAllocateError, FilterAssociateError, FilterSetError);
452 stapi_do_remove_filter(demux_id, filter, dev_id);
453 return 0;
455 else
457 return filter->fd; // return fd of filter
461 static int32_t stapi_do_remove_filter(int32_t UNUSED(demux_id), FILTERTYPE *filter, int32_t dev_id)
463 if(filter->fd == 0) { return 0; }
465 uint32_t BufferDeallocateError = 0, SlotDeallocateError = 0, FilterDeallocateError = 0;
467 if(dev_list[dev_id].SessionHandle == 0) { return 0; }
469 int32_t k;
470 for(k = 0; k < filter->NumSlots; k++)
472 uint32_t checkslot = check_slot(dev_id, filter->SlotHandle[k], filter);
474 if(checkslot == 0)
476 FilterDeallocateError = oscam_stapi5_FilterDeallocate(filter->fd, filter->BufferHandle[k], filter->SlotHandle[k]);
478 oscam_stapi5_SlotClearPid(filter->SlotHandle[k]);
479 oscam_stapi5_SlotUnlink(filter->SlotHandle[k]);
480 oscam_stapi5_SignalDisassociateBuffer(dev_list[dev_id].SignalHandle, filter->BufferHandle[k]);
482 BufferDeallocateError = oscam_stapi5_BufferDeallocate(filter->BufferHandle[k]);
483 SlotDeallocateError = oscam_stapi5_SlotDeallocate(filter->SlotHandle[k]);
488 memset(filter, 0, sizeof(FILTERTYPE));
490 if(BufferDeallocateError || SlotDeallocateError || FilterDeallocateError)
492 cs_log("remove_filter: dev: %d BD: %d SD: %d FDe: %d",
493 dev_id, BufferDeallocateError, SlotDeallocateError, FilterDeallocateError);
494 return 0;
496 else
498 return 1;
502 static void stapi_cleanup_thread(void *dev)
504 int32_t dev_index = (int)dev;
506 int32_t ErrorCode;
507 ErrorCode = oscam_stapi5_Close(dev_list[dev_index].SessionHandle);
509 cs_log("liboscam_stapi5: PTI %s closed - %d\n", dev_list[dev_index].name, ErrorCode);
510 dev_list[dev_index].SessionHandle = 0;
513 static void *stapi_read_thread(void *sparam)
515 int32_t dev_index, ErrorCode, i, j, CRCValid;
516 uint32_t QueryBufferHandle = 0, DataSize = 0;
517 uint8_t buf[BUFFLEN];
519 struct read_thread_param *para = sparam;
520 dev_index = para->id;
522 SAFE_SETSPECIFIC(getclient, para->cli);
523 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
524 pthread_cleanup_push(stapi_cleanup_thread, (void *) dev_index);
526 int32_t error_count = 0;
528 while(!exit_oscam)
530 QueryBufferHandle = 0;
531 ErrorCode = oscam_stapi5_SignalWaitBuffer(dev_list[dev_index].SignalHandle, &QueryBufferHandle, 1000);
533 switch(ErrorCode)
535 case 0: // NO_ERROR:
536 break;
537 case 852042: // ERROR_SIGNAL_ABORTED
538 cs_log("Caught abort signal");
539 pthread_exit(NULL);
540 break;
541 case 11: // ERROR_TIMEOUT:
542 //cs_log("timeout %d", dev_index);
543 //TODO: if pidindex == -1 try next
544 continue;
545 break;
546 default:
547 if(QueryBufferHandle != 0)
549 cs_log("SignalWaitBuffer error: %d", ErrorCode);
550 oscam_stapi5_BufferFlush(QueryBufferHandle);
551 continue;
553 cs_log("SignalWaitBuffer: index %d ErrorCode: %d - QueryBuffer: %x", dev_index, ErrorCode, QueryBufferHandle);
554 error_count++;
555 if(error_count > 10)
557 cs_log("Too many errors in reader thread %d, quitting.", dev_index);
558 pthread_exit(NULL);
560 continue;
561 break;
564 uint32_t NumFilterMatches = 0;
565 int32_t demux_id = 0, filter_num = 0;
566 DataSize = 0;
567 uint32_t k;
569 uint32_t MatchedFilterList[10];
570 ErrorCode = oscam_stapi5_BufferReadSection(QueryBufferHandle, MatchedFilterList, 10, &NumFilterMatches, &CRCValid, buf, BUFFLEN, &DataSize);
572 if(ErrorCode != 0)
574 cs_log("BufferRead: index: %d ErrorCode: %d", dev_index, ErrorCode);
575 cs_sleepms(1000);
576 continue;
579 if(DataSize <= 0)
580 { continue; }
582 SAFE_MUTEX_LOCK(&filter_lock); // don't use cs_lock() here; multiple threads using same s_client struct
583 for(k = 0; k < NumFilterMatches; k++)
585 for(i = 0; i < MAX_DEMUX; i++)
587 for(j = 0; j < MAX_FILTER; j++)
589 if(dev_list[dev_index].demux_fd[i][j].fd == MatchedFilterList[k])
591 demux_id = i;
592 filter_num = j;
594 dvbapi_process_input(demux_id, filter_num, buf, DataSize, 0);
599 SAFE_MUTEX_UNLOCK(&filter_lock);
602 pthread_cleanup_pop(0);
604 return NULL;
607 int32_t stapi_init_descrambler(int32_t dev_index)
609 int32_t ErrorCode;
611 if(dev_index >= MAX_DESCRAMBLER)
613 cs_log("TKD MAX_DESCRAMBLER reached!");
614 return 0;
617 ErrorCode = oscam_sttkd_Allocate(TKDHandle[0], 0, &tkd_desc_info[dev_index].path_hndl, &tkd_desc_info[dev_index].key_hndl);
618 if (ErrorCode != 0)
620 cs_log("oscam_sttkd_Allocate faild! ErrorCode: %d", ErrorCode);
621 return 0;
624 return 1;
627 int32_t stapi_set_pid(int32_t demux_id, int32_t UNUSED(num), uint32_t idx, uint16_t pid, char *UNUSED(pmtfile))
629 if(idx == INDEX_INVALID)
631 if (tkd_desc_info[demux[demux_id].dev_index].path_hndl != 0)
633 cs_log_dbg(D_DVBAPI, "stop descrambling of PID %d on %s", pid, dev_list[demux[demux_id].dev_index].name);
634 uint32_t ErrorCode = oscam_sttkd_Disassociate(dev_list[demux[demux_id].dev_index].name, pid);
635 if (ErrorCode != 0)
636 cs_log("oscam_sttkd_Disassociate faild! ErrorCode: %d", ErrorCode);
638 int i;
639 for (i = 0; i < MAX_STREAMPIDS; i++)
641 if (tkd_desc_info[demux[demux_id].dev_index].STREAMPIDs[i] == pid)
643 tkd_desc_info[demux[demux_id].dev_index].STREAMPIDs[i] = 0;
644 break;
651 return 1;
654 int32_t stapi_write_cw(int32_t demux_id, uint8_t *cw, uint16_t *STREAMpids, int32_t STREAMpidcount, char *UNUSED(pmtfile))
656 int32_t ErrorCode, l, x;
657 uint8_t nullcw[8];
658 memset(nullcw, 0, 8);
659 char *text[] = { "even", "odd" };
661 if(dev_list[demux[demux_id].dev_index].SessionHandle == 0) { return 0; }
663 // check if descrambler is started for this dev_index
664 if(tkd_desc_info[demux[demux_id].dev_index].path_hndl == 0)
666 if(!stapi_init_descrambler(demux[demux_id].dev_index))
668 cs_log_dbg(D_DVBAPI, "stapi_write_cw , faild to added descrambler for %s", dev_list[demux[demux_id].dev_index].name);
669 return 0;
673 // descrambler started, check each pid
674 for (x = 0; x < STREAMpidcount; x++)
676 int pid_associated = -1;
678 // search STREAMpids if path got associated
679 for (l = 0; l < MAX_STREAMPIDS; l++)
681 if (tkd_desc_info[demux[demux_id].dev_index].STREAMPIDs[l] == STREAMpids[x])
683 pid_associated = l;
684 break;
688 // if not associated add the pid
689 if(pid_associated < 0)
691 ErrorCode = oscam_sttkd_Associate(dev_list[demux[demux_id].dev_index].name, tkd_desc_info[demux[demux_id].dev_index].path_hndl, STREAMpids[x]);
692 if (ErrorCode != 0)
694 cs_log("stapi_write_cw , oscam_sttkd_Associate faild for pid %04X! ErrorCode: %d", STREAMpids[x], ErrorCode);
695 return 0;
698 // add the pid to the next free index
699 for (l = 0; l < MAX_STREAMPIDS; l++)
701 if (tkd_desc_info[demux[demux_id].dev_index].STREAMPIDs[l] == 0)
703 tkd_desc_info[demux[demux_id].dev_index].STREAMPIDs[l] = STREAMpids[x];
704 pid_associated = l;
705 break;
709 if (pid_associated < 0)
711 cs_log("stapi_write_cw , faild to associate pid %04X, maximum number of %d pids reached", STREAMpids[x], MAX_STREAMPIDS);
712 return 0;
717 //@theparasol: please verify this block is in the right place
718 int32_t pidnum = demux[demux_id].pidindex; // get current pidindex used for descrambling
719 uint32_t idx = demux[demux_id].ECMpids[pidnum].index[0];
721 if(idx == INDEX_INVALID) // if no indexer for this pid get one!
723 idx = dvbapi_get_desc_index(demux_id, pidnum, 0);
724 cs_log_dbg(D_DVBAPI, "Demuxer %d PID: %d CAID: %04X ECMPID: %04X is using index %d", demux_id, pidnum,
725 demux[demux_id].ECMpids[pidnum].CAID, demux[demux_id].ECMpids[pidnum].ECM_PID, idx);
729 for(l = 0; l < 2; l++)
731 // Skip check for BISS1 - cw could be indeed zero
732 // Skip check for BISS2 - we use the extended cw, so the "simple" cw is always zero
733 if(memcmp(cw + (l * 8), demux[demux_id].last_cw[0][l], 8) != 0
734 && (memcmp(cw + (l * 8), nullcw, 8) != 0 || caid_is_biss(demux[demux_id].ECMpids[pidnum].CAID)))
736 ErrorCode = oscam_sttkd_KeyWrite(tkd_desc_info[demux[demux_id].dev_index].key_hndl, l, cw + (l * 8));
738 memcpy(demux[demux_id].last_cw[0][l], cw + (l * 8), 8);
739 cs_log_dbg(D_DVBAPI, "write cw %s index: %d on %s", text[l], demux_id, dev_list[demux[demux_id].dev_index].name);
743 return 1;
746 #endif