- fix Building without Nagra not possible at Nagra_Merlin https://trac.streamboard...
[oscam.git] / module-dvbapi-coolapi.c
blob9f6ea5a916466862997a7175f0c94205cbcd82ed
1 /* Reversed from libcoolstream.so, this comes without any warranty */
3 #define MODULE_LOG_PREFIX "dvbcool"
5 #include "globals.h"
7 #if defined(HAVE_DVBAPI) && (defined(WITH_SU980) || defined(WITH_COOLAPI2) || defined(WITH_COOLAPI))
8 #include "extapi/coolapi.h"
10 #include "module-dvbapi.h"
11 #include "module-dvbapi-coolapi.h"
12 #include "oscam-string.h"
15 #define MAX_COOL_DMX 4
17 //kronos-Plattform (Coolsterem ZEE)
18 //#define MAX_COOL_DMX 3
21 #define DMX_MAX_FILTERS_PER_CHAN 16
22 #define DMX_MAX_CHANNELS_PER_DMX 192
23 //#define MAX_COOL_DMX_FILTERS 128
25 struct s_cool_chanhandle;
27 typedef struct s_cool_filter
29 int32_t fd;
30 struct s_cool_chanhandle *chanhandle;
31 void *filter;
32 int32_t filter_num;
33 uint8_t filter16[16];
34 uint8_t mask16[16];
35 } S_COOL_FILTER;
37 typedef struct s_cool_chanhandle
39 int32_t pid;
40 void *buffer1; // filter Cbuf 1
41 void *buffer2; // filter Cbuf 2
42 void *channel;
43 int32_t demux_index;
44 struct s_cool_dmxhandle *dmx_handle;
45 uint32_t allocated_filters;
46 } S_COOL_CHANHANDLE;
48 typedef struct s_cool_dmxhandle
50 void *handle;
51 uint32_t allocated_channels;
52 } S_COOL_DMXHANDLE;
54 struct cool_dmx
56 int32_t pid;
57 int32_t opened;
58 int32_t fd;
59 pthread_mutex_t mutex;
60 int32_t filter_num;
61 int32_t demux_id;
62 int32_t type;
64 typedef struct cool_dmx dmx_t;
66 typedef struct
68 int32_t type;
69 uint32_t size;
70 #ifdef HAVE_COOLAPI2
71 uint32_t ptsbufsize;
72 #endif
73 int32_t unknown1;
74 int16_t unknown2;
75 int32_t hwm;
76 int32_t lwm;
77 int32_t unknown5;
78 int32_t unknown6;
79 int32_t poolid;
80 #ifdef HAVE_COOLAPI2
81 uint32_t unit;
82 #endif
83 } buffer_open_arg_t;
85 typedef struct
87 int32_t type;
88 int32_t unknown[2];
89 } channel_open_arg_t;
91 // Nevis : 13
92 // Apollo: 13
93 typedef struct
95 uint32_t number;
96 int32_t unknown1; // channel source
97 int32_t unknown2; // mcard cap
98 int32_t unknown3; // descrambler type
99 int32_t unknown4; // support legacy NDS
100 int32_t unknown5;
101 int32_t unknown6;
102 int32_t unknown[6];
103 } device_open_arg_t;
105 typedef struct
107 uint32_t length;
108 uint8_t filter[18]; //strange: initialization with max 18 possible but length limited to 12
109 uint8_t mask[18];
110 uint8_t nmask[18];
111 int8_t fvernum;
112 int8_t crcchange;
113 int8_t keeprbytes;
114 int32_t mode;
115 } filter_set_t;
118 typedef enum
120 CONTINUOUS_ACQUIRE = 0,
121 ONE_SHOT_ACQUIRE,
122 TOGGLE_ACQUIRE
123 } DATA_ACQUIRE_MODE;
125 typedef enum
127 DATA_ACQUIRED = 1,
128 CHANNEL_TIMEOUT,
129 CRC_ERROR,
130 BUF_OVERFLOW,
131 PES_ERROR,
132 COPY_DONE,
133 CHANNEL_INFO
134 } DATA_ACQUIRE_STATUS;
136 typedef struct
138 uint32_t PTSLow;
139 uint32_t PTSHi;
140 } DMX_PTS;
142 typedef struct
144 void *channel;
145 DATA_ACQUIRE_STATUS type;
147 DMX_PTS ptssnapshot;
148 void *buf;
149 uint32_t start;
151 DATA_ACQUIRE_MODE mode;
152 uint32_t len;
153 uint16_t num;
154 void *filters[DMX_MAX_FILTERS_PER_CHAN];
155 void *tags[DMX_MAX_FILTERS_PER_CHAN];
156 } dmx_callback_data_t;
158 /* These functions are implemented in libnxp */
159 extern int32_t cnxt_cbuf_open(void **handle, buffer_open_arg_t *arg, void *, void *);
160 extern int32_t cnxt_dmx_open(void **device, device_open_arg_t *arg, void *, void *);
161 extern int32_t cnxt_dmx_channel_open(void *device, void **channel, channel_open_arg_t *arg, void *callback, void *);
162 extern int32_t cnxt_dmx_set_filter(void *handle, filter_set_t *arg, void *);
163 extern int32_t cnxt_dmx_channel_suspend(void *handle, int32_t enable);
165 /* Local coolapi functions */
166 static int32_t coolapi_read(dmx_t *dmx, dmx_callback_data_t *dataa, uint8_t *buffer);
168 static int8_t dmx_opened;
169 int32_t cool_kal_opened = 0;
171 static S_COOL_DMXHANDLE dmx_handles[MAX_COOL_DMX];
172 static dmx_t cdemuxes[MAX_COOL_DMX][MAX_FILTER];
173 static pthread_mutex_t demux_lock = PTHREAD_MUTEX_INITIALIZER;
174 extern void *dvbapi_client;
176 static LLIST *ll_cool_filter = NULL;
177 static LLIST *ll_cool_chanhandle = NULL;
179 #define COOLDEMUX_FD(device, num) (('O' << 24) | ('S' << 16) | (device << 8) | num)
180 #define COOLDEMUX_DMX_DEV(fd) (((fd) >> 8) & 0xFF)
181 #define COOLDEMUX_FLT_IDX(fd) (((fd) >> 0) & 0xFF)
182 #define COOLDEMUX_IS_VALID_FD(fd) ((((fd) & 0xFF000000) == ('O' << 24)) && \
183 (((fd) & 0x00FF0000) == ('S' << 16)))
185 #define COOLDEMUX_DATA_RECEIVED 1
186 #define COOLDEMUX_CHANNEL_TIMEOUT 2
187 #define COOLDEMUX_CRC_ERROR 3
188 #define COOLDEMUX_BUFF_OVERFLOW 4
190 static dmx_t *find_demux(int32_t fd, int32_t dmx_dev_num)
192 if(dmx_dev_num < 0 || dmx_dev_num >= MAX_COOL_DMX)
194 cs_log("Invalid demux %d", dmx_dev_num);
195 return NULL;
198 dmx_t *dmx;
199 int32_t i;
201 if(fd == 0) // DEMUX FILTER ALLOCATE
203 for(i = 0; i < MAX_FILTER; i++)
205 dmx = &cdemuxes[dmx_dev_num][i];
206 if(!dmx->opened)
208 dmx->fd = COOLDEMUX_FD(dmx_dev_num, i);
209 cs_log_dbg(D_DVBAPI, "opening new fd: %08x", dmx->fd);
210 return dmx;
213 cs_log_dbg(D_DVBAPI, "ERROR: no free demux found");
214 return NULL;
217 if (!COOLDEMUX_IS_VALID_FD(fd))
219 cs_log_dbg(D_DVBAPI, "ERROR: invalid FD");
220 return NULL;
223 dmx_dev_num = COOLDEMUX_DMX_DEV(fd);
224 for(i = 0; i < MAX_FILTER; i++)
226 dmx = &cdemuxes[dmx_dev_num][i];
227 if(dmx->fd == fd)
229 return dmx;
233 cs_log_dbg(D_DVBAPI, "ERROR: CANT FIND Demux %08x", fd);
235 return NULL;
238 int32_t coolapi_get_filter_num(int32_t fd)
240 if (!COOLDEMUX_IS_VALID_FD(fd))
242 cs_log_dbg(D_DVBAPI, "ERROR: invalid FD");
243 return -1;
246 return cdemuxes[COOLDEMUX_DMX_DEV(fd)][COOLDEMUX_FLT_IDX(fd)].filter_num;
249 static S_COOL_CHANHANDLE *find_chanhandle(int32_t demux_index, int32_t pid)
251 // Find matching channel, if it exists.
252 if(ll_count(ll_cool_chanhandle) > 0)
254 LL_ITER itr = ll_iter_create(ll_cool_chanhandle);
255 S_COOL_CHANHANDLE *handle_item;
257 while((handle_item = ll_iter_next(&itr)))
259 if(handle_item->demux_index == demux_index && handle_item->pid == pid)
261 return handle_item;
266 return NULL;
269 static int32_t remove_chanhandle(S_COOL_CHANHANDLE *handle)
271 // Find matching channel, if it exists.
272 if(ll_count(ll_cool_chanhandle) > 0)
274 LL_ITER itr = ll_iter_create(ll_cool_chanhandle);
275 S_COOL_CHANHANDLE *handle_item;
277 while((handle_item = ll_iter_next(&itr)))
279 if(handle_item == handle)
281 ll_iter_remove_data(&itr);
282 return 0;
287 return -1;
290 static S_COOL_FILTER *find_filter_by_chanhandle(S_COOL_CHANHANDLE *chanhandle, int32_t filter_num)
292 // Find matching channel, if it exists.
293 if(ll_count(ll_cool_filter) > 0)
295 LL_ITER itr = ll_iter_create(ll_cool_filter);
296 S_COOL_FILTER *filter_item;
298 while((filter_item = ll_iter_next(&itr)))
300 if(filter_item->chanhandle == chanhandle && filter_item->filter_num == filter_num)
302 return filter_item;
307 return NULL;
310 static S_COOL_FILTER *find_filter_by_channel(void *channel, int32_t filter_num)
312 // Find matching channel, if it exists.
313 if(ll_count(ll_cool_filter) > 0)
315 LL_ITER itr = ll_iter_create(ll_cool_filter);
316 S_COOL_FILTER *filter_item;
318 while((filter_item = ll_iter_next(&itr)))
320 if(filter_item->chanhandle &&
321 filter_item->chanhandle->channel == channel &&
322 filter_item->filter_num == filter_num)
324 return filter_item;
329 return NULL;
332 static int32_t remove_filter(S_COOL_FILTER *filter_handle)
334 if(ll_count(ll_cool_filter) > 0)
336 LL_ITER itr = ll_iter_create(ll_cool_filter);
337 S_COOL_FILTER *filter_item;
339 while((filter_item = ll_iter_next(&itr)))
341 if(filter_item == filter_handle)
343 ll_iter_remove_data(&itr);
344 return 0;
349 return -1;
352 static void coolapi_read_data(dmx_t *dmx, dmx_callback_data_t *data)
354 if(!dmx)
356 cs_log_dbg(D_DVBAPI, "handle is NULL!");
357 return;
360 int32_t ret;
361 uint8_t buffer[4096];
363 SAFE_SETSPECIFIC(getclient, dvbapi_client);
364 SAFE_MUTEX_LOCK(&dmx->mutex);
365 memset(buffer, 0, sizeof(buffer));
366 ret = coolapi_read(dmx, data, buffer);
367 SAFE_MUTEX_UNLOCK(&dmx->mutex);
369 if(ret > -1) {
370 uint16_t filters = data->num;
371 uint16_t flt;
373 for (flt = 0; flt < filters; flt++) {
374 uint32_t n = (uint32_t)data->tags[flt];
375 S_COOL_FILTER *filter = find_filter_by_channel(data->channel, n);
377 if (!filter || data->filters[flt] != filter->filter)
379 cs_log_dbg(D_DVBAPI, "filter not found in notification!!!!");
380 continue;
383 dvbapi_process_input(dmx->demux_id, n, buffer, data->len, 0);
388 static void dmx_callback(void *channel, dmx_t *dmx, int32_t type, dmx_callback_data_t *data)
390 if(!dmx)
392 cs_log_dbg(D_DVBAPI, "wrong dmx pointer !!!");
393 return;
396 if(data == NULL)
397 return;
399 if (channel != data->channel)
400 return;
402 switch(type)
404 #ifdef WITH_COOLAPI2
405 case 0x11:
406 #else
407 case 0x0E:
408 #endif
409 if(data->type == COOLDEMUX_DATA_RECEIVED && data->len > 0) {
410 coolapi_read_data(dmx, data);
411 } else if(data->type == COOLDEMUX_CRC_ERROR && data->len > 0) {
412 cs_log_dbg(D_DVBAPI, "CRC error !!!");
413 cnxt_cbuf_removed_data(data->buf, data->len);
414 } else if(data->type == COOLDEMUX_BUFF_OVERFLOW) {
415 cs_log_dbg(D_DVBAPI, "OVERFLOW !!!");
416 } else {
417 cs_log_dbg(D_DVBAPI, "unknown callback data %d len %d", data->type, data->len);
419 break;
420 default:
421 break;
425 int32_t coolapi_set_filter(int32_t fd, int32_t num, int32_t pid, uint8_t *flt, uint8_t *mask, int32_t type)
427 dmx_t *dmx = find_demux(fd, 0);
428 if(!dmx)
430 cs_log_dbg(D_DVBAPI, "dmx is NULL!");
431 return -1;
434 int32_t result, channel_found;
435 SAFE_MUTEX_LOCK(&dmx->mutex);
437 // Find matching channel, if it exists.
438 S_COOL_CHANHANDLE *handle_item = find_chanhandle(COOLDEMUX_DMX_DEV(fd), pid);
439 if(!handle_item)
441 // No channel was found, allocate one
442 buffer_open_arg_t bufarg;
443 int32_t uBufferSize = 8192 + 64;
444 /* Mark that we did not find any open channel on this PID */
445 channel_found = 0;
447 if(!cs_malloc(&handle_item, sizeof(S_COOL_CHANHANDLE)))
449 return -1;
452 memset(&bufarg, 0, sizeof(bufarg));
454 #ifdef HAVE_COOLAPI2
455 bufarg.poolid = 5
456 #endif
457 bufarg.type = 3;
458 bufarg.size = uBufferSize;
459 bufarg.hwm = (uBufferSize * 7) / 8;
461 result = cnxt_cbuf_open(&handle_item->buffer1, &bufarg, NULL, NULL);
462 coolapi_check_error("cnxt_cbuf_open", result);
463 bufarg.type = 0;
465 #ifdef HAVE_COOLAPI2
466 bufarg.poolid = 0
467 #endif
468 result = cnxt_cbuf_open(&handle_item->buffer2, &bufarg, NULL, NULL);
469 coolapi_check_error("cnxt_cbuf_open", result);
471 channel_open_arg_t chanarg;
472 memset(&chanarg, 0, sizeof(channel_open_arg_t));
474 chanarg.type = 4;
475 result = cnxt_dmx_channel_open(dmx_handles[COOLDEMUX_DMX_DEV(fd)].handle, &handle_item->channel, &chanarg, dmx_callback, dmx);
476 coolapi_check_error("cnxt_dmx_channel_open", result);
478 result = cnxt_dmx_set_channel_buffer(handle_item->channel, 0, handle_item->buffer1);
479 coolapi_check_error("cnxt_dmx_set_channel_buffer", result);
481 result = cnxt_dmx_channel_attach(handle_item->channel, 0xB, 0, handle_item->buffer2);
482 coolapi_check_error("cnxt_dmx_channel_attach", result);
484 result = cnxt_cbuf_attach(handle_item->buffer2, 2, handle_item->channel);
485 coolapi_check_error("cnxt_cbuf_attach", result);
487 result = cnxt_dmx_set_channel_pid(handle_item->channel, pid);
488 coolapi_check_error("cnxt_dmx_set_channel_pid", result);
490 result = cnxt_cbuf_flush(handle_item->buffer1, 0);
491 coolapi_check_error("cnxt_cbuf_flush", result);
492 result = cnxt_cbuf_flush(handle_item->buffer2, 0);
493 coolapi_check_error("cnxt_cbuf_flush", result);
495 handle_item->pid = pid;
496 handle_item->dmx_handle = &dmx_handles[COOLDEMUX_DMX_DEV(fd)];
497 dmx_handles[COOLDEMUX_DMX_DEV(fd)].allocated_channels++;
498 ll_append(ll_cool_chanhandle, handle_item);
500 cs_log_dbg(D_DVBAPI, "opened new channel %x", (int32_t) handle_item->channel);;
502 else
504 channel_found = 1;
507 cs_log_dbg(D_DVBAPI, "setting new filter fd=%08x demux=%d channel=%x num=%d pid=%04x flt=%x mask=%x", fd, COOLDEMUX_DMX_DEV(fd), (int32_t) handle_item->channel, num, pid, flt[0], mask[0]);
508 void *filter_handle = NULL;
509 filter_set_t filterset;
510 int32_t has_filter = 0;
512 S_COOL_FILTER *filter_item = find_filter_by_chanhandle(handle_item, num);
513 if (filter_item && type == dmx->type && pid == dmx->pid &&
514 (memcmp(flt, filter_item->filter16, 16) || memcmp(mask, filter_item->mask16, 16)))
516 cs_log_dbg(D_DVBAPI, "setting new filter fd=%08x demux=%d channel=%x num=%d pid=%04x flt=%x mask=%x, filter exists.. modifying", fd, COOLDEMUX_DMX_DEV(fd), (int32_t) handle_item->channel, num, pid, flt[0], mask[0]);
517 filter_handle = filter_item->filter;
519 has_filter = 1;
521 memcpy(filter_item->filter16, flt, 16);
522 memcpy(filter_item->mask16, mask, 16);
524 else
526 dmx->pid = pid;
527 dmx->type = type;
528 dmx->filter_num = num;
529 result = cnxt_dmx_open_filter(dmx_handles[COOLDEMUX_DMX_DEV(fd)].handle, &filter_handle);
530 coolapi_check_error("cnxt_dmx_open_filter", result);
532 if(!cs_malloc(&filter_item, sizeof(S_COOL_FILTER)))
534 SAFE_MUTEX_UNLOCK(&dmx->mutex);
535 return -1;
538 // fill filter item
539 filter_item->fd = fd;
540 filter_item->filter = filter_handle;
541 filter_item->filter_num = num;
542 filter_item->chanhandle = handle_item;
543 memcpy(filter_item->filter16, flt, 16);
544 memcpy(filter_item->mask16, mask, 16);
546 //add filter item
547 ll_append(ll_cool_filter, filter_item);
548 // increase allocated filters
549 handle_item->allocated_filters++;
552 if (has_filter)
554 result = cnxt_dmx_channel_suspend(handle_item->channel, 1);
555 coolapi_check_error("cnxt_dmx_channel_suspend", result);
556 result = cnxt_dmx_channel_detach_filter(handle_item->channel, filter_handle);
557 coolapi_check_error("cnxt_dmx_channel_detach_filter", result);
560 memset(&filterset, 0, sizeof(filterset));
561 filterset.length = 12;
562 memcpy(filterset.filter, flt, 16);
563 memcpy(filterset.mask, mask, 16);
565 result = cnxt_dmx_set_filter(filter_handle, &filterset, (void *)num);
566 coolapi_check_error("cnxt_dmx_set_filter", result);
568 result = cnxt_dmx_channel_attach_filter(handle_item->channel, filter_handle);
569 coolapi_check_error("cnxt_dmx_channel_attach_filter", result);
571 if (has_filter)
573 result = cnxt_dmx_channel_suspend(handle_item->channel, 0);
574 coolapi_check_error("cnxt_dmx_channel_suspend", result);
577 if(!channel_found)
579 // Start channel
580 result = cnxt_dmx_channel_ctrl(handle_item->channel, 2, 0);
581 coolapi_check_error("cnxt_dmx_channel_ctrl", result);
584 SAFE_MUTEX_UNLOCK(&dmx->mutex);
586 return 0;
589 int32_t coolapi_remove_filter(int32_t fd, int32_t num)
591 void * channel = NULL;
592 void * filter = NULL;
594 dmx_t *dmx = find_demux(fd, 0);
595 if(!dmx)
597 cs_log_dbg(D_DVBAPI, "dmx is NULL!");
598 return -1;
601 if(dmx->pid <= 0)
602 { return -1; }
604 int32_t result;
606 SAFE_MUTEX_LOCK(&dmx->mutex);
608 // Find matching channel, if it exists.
609 S_COOL_CHANHANDLE *handle_item = find_chanhandle(COOLDEMUX_DMX_DEV(fd), dmx->pid);
610 if (!handle_item)
612 SAFE_MUTEX_UNLOCK(&dmx->mutex);
613 cs_log_dbg(D_DVBAPI, "removing filter fd=%08x num=%d pid=%04xcfailed, channel does not exist.", fd, num, dmx->pid);
614 return -1;
617 channel = handle_item->channel;
618 cs_log_dbg(D_DVBAPI, "removing filter fd=%08x num=%d pid=%04x on channel=%p", fd, num, dmx->pid, channel);
621 S_COOL_FILTER *filter_item = find_filter_by_chanhandle(handle_item, num);
622 if(filter_item)
624 result = cnxt_dmx_channel_suspend(channel, 1);
625 coolapi_check_error("cnxt_dmx_channel_suspend", result);
626 result = cnxt_dmx_channel_detach_filter(channel, filter_item->filter);
627 coolapi_check_error("cnxt_dmx_channel_detach_filter", result);
628 #if 0
629 result = cnxt_dmx_close_filter(filter_item->filter);
630 coolapi_check_error("cnxt_dmx_close_filter", result);
631 #endif
632 filter = filter_item->filter;
633 remove_filter(filter_item);
634 handle_item->allocated_filters--;
636 else
638 SAFE_MUTEX_UNLOCK(&dmx->mutex);
639 cs_log_dbg(D_DVBAPI, "removing filter fd=%08x num=%d pid=%04x on channel=%x failed, channel does not exist.", fd, num, dmx->pid, (int32_t) handle_item->channel);
640 return -1;
643 if (!handle_item->allocated_filters)
645 result = cnxt_dmx_channel_ctrl(channel, 0, 0);
646 coolapi_check_error("cnxt_dmx_channel_ctrl", result);
647 cs_log_dbg(D_DVBAPI, "closing channel %x", (int32_t) channel);
649 result = cnxt_dmx_set_channel_pid(channel, 0x1FFF);
650 coolapi_check_error("cnxt_dmx_set_channel_pid", result);
652 result = cnxt_cbuf_flush(handle_item->buffer1, 0);
653 coolapi_check_error("cnxt_cbuf_flush", result);
655 result = cnxt_cbuf_flush(handle_item->buffer2, 0);
656 coolapi_check_error("cnxt_cbuf_flush", result);
658 result = cnxt_cbuf_detach(handle_item->buffer2, 2, channel);
659 coolapi_check_error("cnxt_cbuf_detach", result);
661 result = cnxt_dmx_channel_detach(channel, 0xB, 0, handle_item->buffer1);
662 coolapi_check_error("cnxt_dmx_channel_detach", result);
664 #if 0
665 result = cnxt_dmx_channel_close(channel);
666 coolapi_check_error("cnxt_dmx_channel_close", result);
667 #endif
669 result = cnxt_cbuf_close(handle_item->buffer2);
670 coolapi_check_error("cnxt_cbuf_close", result);
672 result = cnxt_cbuf_close(handle_item->buffer1);
673 coolapi_check_error("cnxt_cbuf_close", result);
674 handle_item->channel = NULL;
675 handle_item->buffer1 = NULL;
676 handle_item->buffer2 = NULL;
677 remove_chanhandle(handle_item);
678 dmx_handles[COOLDEMUX_DMX_DEV(fd)].allocated_channels--;
679 dmx->pid = -1;
680 } else {
681 result = cnxt_dmx_channel_suspend(channel, 0);
682 coolapi_check_error("cnxt_dmx_channel_suspend", result);
683 channel = NULL;
686 SAFE_MUTEX_UNLOCK(&dmx->mutex);
687 if (filter) {
688 result = cnxt_dmx_close_filter(filter);
689 coolapi_check_error("cnxt_dmx_close_filter", result);
692 // COOLAPI2 - We don't want to close Channel on no ECM Filters (Makes AU / EMMs work)
693 if(dmx->type != TYPE_ECM)
694 { return 0; }
696 if (channel) {
697 result = cnxt_dmx_channel_close(channel);
698 coolapi_check_error("cnxt_dmx_channel_close", result);
701 return 0;
704 int32_t coolapi_open_device(int32_t demux_index, int32_t demux_id)
706 dmx_t *dmx;
708 SAFE_MUTEX_LOCK(&demux_lock);
710 dmx = find_demux(0, demux_index);
711 if(!dmx)
713 SAFE_MUTEX_UNLOCK(&demux_lock);
714 cs_log("no free demux found");
715 return 0;
718 if(!ll_cool_filter)
719 { ll_cool_filter = ll_create("ll_cool_filter"); }
721 if(!ll_cool_chanhandle)
722 { ll_cool_chanhandle = ll_create("ll_cool_chanhandle"); }
724 dmx->demux_id = demux_id;
725 dmx->pid = -1;
727 //dmx->device = dmx_handles[demux_index].handle;
728 dmx->opened = 1;
730 pthread_mutexattr_t attr;
731 SAFE_MUTEXATTR_INIT(&attr);
732 SAFE_MUTEXATTR_SETTYPE(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
733 SAFE_MUTEX_INIT(&dmx->mutex, &attr);
735 SAFE_MUTEX_UNLOCK(&demux_lock);
737 return dmx->fd;
740 int32_t coolapi_close_device(int32_t fd)
742 dmx_t *dmx = find_demux(fd, 0);
743 if(!dmx)
745 cs_log_dbg(D_DVBAPI, "dmx is NULL!");
746 SAFE_MUTEX_UNLOCK(&demux_lock);
747 return -1;
750 cs_log_dbg(D_DVBAPI, "closing fd=%08x", fd);
751 dmx->opened = 0;
752 pthread_mutex_destroy(&dmx->mutex);
754 memset(dmx, 0, sizeof(dmx_t));
755 return 0;
758 /* write cw to all demuxes in mask with passed index */
759 int32_t coolapi_write_cw(int32_t mask, uint16_t *STREAMpids, int32_t count, ca_descr_t *ca_descr)
761 int32_t i;
762 uint32_t idx = ca_descr->index;
763 int32_t result;
764 void *channel;
766 cs_log_dbg(D_DVBAPI, "cw%d: mask %d index %d pid count %d", ca_descr->parity, mask, idx, count);
767 for(i = 0; i < count; i++)
769 int32_t pid = STREAMpids[i];
770 int32_t j;
771 for(j = 0; j < MAX_COOL_DMX; j++)
773 if(mask & (1 << j))
775 result = cnxt_dmx_get_channel_from_pid(dmx_handles[j].handle, pid, &channel);
776 if(result == 0)
778 cs_log_dbg(D_DVBAPI, "Found demux %d channel %x for pid %04x", j, (int32_t) channel, pid);
779 result = cnxt_dmx_set_channel_key(channel, 0, ca_descr->parity, ca_descr->cw, 8);
780 coolapi_check_error("cnxt_dmx_set_channel_key", result);
781 if(result != 0)
783 cs_log("set_channel_key failed for demux %d pid %04x", j, pid);
789 return 0;
792 static int32_t coolapi_read(dmx_t *dmx, dmx_callback_data_t *data, uint8_t *buffer)
794 if(!dmx)
796 cs_log_dbg(D_DVBAPI, "dmx is NULL!");
797 return -1;
800 int32_t result;
801 uint32_t done = 0, toread, len = data->len;
802 uint32_t bytes_used = 0;
804 //cs_log_dbg(D_DVBAPI, "dmx channel %x pid %x len %d", (int) dmx->channel, dmx->pid, len);
806 result = cnxt_cbuf_get_used(data->buf, &bytes_used);
807 coolapi_check_error("cnxt_cbuf_get_used", result);
808 if(bytes_used == 0)
809 { return -1; }
811 result = cnxt_cbuf_read_data(data->buf, buffer, 3, &done);
812 coolapi_check_error("cnxt_cbuf_read_data", result);
814 if(done != 3)
815 { return -1; }
817 toread = ((buffer[1] << 8) | buffer[2]) & 0xFFF;
818 if((toread + 3) > len)
819 { return -1; }
820 result = cnxt_cbuf_read_data(data->buf, buffer + 3, toread, &done);
821 coolapi_check_error("cnxt_cbuf_read_data", result);
822 if(done != toread)
823 { return -1; }
824 done += 3;
826 //cs_log_dbg(D_DVBAPI, "bytes read %d\n", done);
828 return 0;
831 static void coolapi_dmx_open(void)
833 int32_t result = 0;
834 device_open_arg_t devarg;
836 if(!dmx_opened)
838 int32_t i;
840 cs_log_dbg(D_DVBAPI, "Open Coolstream DMX API");
842 memset(&devarg, 0, sizeof(device_open_arg_t));
844 devarg.unknown1 = 1;
845 devarg.unknown3 = 3;
846 devarg.unknown6 = 1;
847 for(i = 0; i < MAX_COOL_DMX; i++)
849 devarg.number = i;
850 result = cnxt_dmx_open(&dmx_handles[i].handle, &devarg, NULL, NULL);
851 coolapi_check_error("cnxt_dmx_open", result);
853 dmx_opened = 1;
857 static void coolapi_dmx_close(void)
859 if(dmx_opened)
861 int32_t result;
862 int32_t i;
864 for(i = 0; i < MAX_COOL_DMX; i++)
866 result = cnxt_dmx_close(dmx_handles[i].handle);
867 coolapi_check_error("cnxt_dmx_close", result);
868 dmx_handles[i].handle = NULL;
870 dmx_opened = 0;
874 static void coolapi_start_api(void);
875 static void coolapi_stop_api(void);
877 void coolapi_open_all(void)
879 SAFE_MUTEX_LOCK(&demux_lock);
881 coolapi_start_api();
882 cool_kal_opened = 1;
883 coolapi_dmx_open();
885 SAFE_MUTEX_UNLOCK(&demux_lock);
888 void coolapi_close_all(void)
890 SAFE_MUTEX_LOCK(&demux_lock);
892 if(!dmx_opened) {
893 SAFE_MUTEX_UNLOCK(&demux_lock);
894 return;
897 int32_t i, j;
899 for(i = 0; i < MAX_COOL_DMX; i++)
901 for(j = 0; j < MAX_FILTER; j++)
903 if(cdemuxes[i][j].fd > 0)
905 coolapi_remove_filter(cdemuxes[i][j].fd, cdemuxes[i][j].filter_num);
906 coolapi_close_device(cdemuxes[i][j].fd);
911 coolapi_dmx_close();
912 coolapi_stop_api();
913 cool_kal_opened = 0;
915 SAFE_MUTEX_UNLOCK(&demux_lock);
917 #endif
919 #if defined(HAVE_DVBAPI) && (defined(WITH_SU980) || defined(WITH_COOLAPI2))
920 #include "extapi/coolapi.h"
921 extern void cnxt_css_drv_init(void);
922 extern void cnxt_css_drv_term(void);
923 extern void cnxt_smc_term(void);
925 static void coolapi_start_api(void)
927 cnxt_kal_initialize();
928 cnxt_css_drv_init();
929 cnxt_cbuf_init(NULL);
930 cnxt_dmx_init(NULL);
931 cnxt_smc_init(NULL);
934 static void coolapi_stop_api(void)
936 cnxt_css_drv_term();
937 cnxt_kal_terminate();
939 #elif defined(HAVE_DVBAPI) && defined(WITH_COOLAPI)
940 static void coolapi_start_api(void)
942 cnxt_kal_initialize();
943 cnxt_drv_init();
944 cnxt_smc_init(NULL);
947 static void coolapi_stop_api(void)
949 cnxt_kal_terminate();
950 cnxt_drv_term();
952 #endif