1 /* Reversed from libcoolstream.so, this comes without any warranty */
3 #define MODULE_LOG_PREFIX "dvbcool"
7 #if defined(HAVE_DVBAPI) && defined(WITH_COOLAPI)
9 #include "extapi/coolapi.h"
11 #include "module-dvbapi.h"
12 #include "module-dvbapi-coolapi.h"
13 #include "oscam-string.h"
15 #define MAX_COOL_DMX 4
17 typedef struct s_cool_filter
26 typedef struct s_cool_chanhandle
46 pthread_mutex_t mutex
;
52 typedef struct cool_dmx dmx_t
;
85 uint8_t filter
[18]; //strange: initialization with max 18 possible but length limited to 12
97 CONTINUOUS_ACQUIRE
= 0,
111 } DATA_ACQUIRE_STATUS
;
122 DATA_ACQUIRE_STATUS type
;
124 DATA_ACQUIRE_MODE mode
;
130 } dmx_callback_data_t
;
132 /* These functions are implemented in libnxp */
133 extern int32_t cnxt_cbuf_open(void **handle
, buffer_open_arg_t
*arg
, void *, void *);
134 extern int32_t cnxt_dmx_open(void **device
, device_open_arg_t
*arg
, void *, void *);
135 extern int32_t cnxt_dmx_channel_open(void *device
, void **channel
, channel_open_arg_t
*arg
, void *callback
, void *);
136 extern int32_t cnxt_dmx_set_filter(void *handle
, filter_set_t
*arg
, void *);
137 extern int32_t cnxt_dmx_channel_suspend(void *handle
, int32_t enable
);
139 /* Local coolapi functions */
140 static void coolapi_open(void);
141 static int32_t coolapi_read(dmx_t
*dmx
, dmx_callback_data_t
*data
);
143 static int8_t dmx_opened
;
144 int8_t cool_kal_opened
= 0;
146 static void *dmx_device
[MAX_COOL_DMX
];
147 static dmx_t cdemuxes
[MAX_COOL_DMX
][MAX_FILTER
];
149 extern void *dvbapi_client
;
151 static LLIST
*ll_cool_filter
= NULL
;
152 static LLIST
*ll_cool_chanhandle
= NULL
;
154 #define COOLDEMUX_FD(device, num) (('O' << 24) | ('S' << 16) | (device << 8) | num)
155 #define COOLDEMUX_DMX_DEV(fd) (((fd) >> 8) & 0xFF)
157 static dmx_t
*find_demux(int32_t fd
, int32_t dmx_dev_num
)
159 if(dmx_dev_num
< 0 || dmx_dev_num
>= MAX_COOL_DMX
)
161 cs_log("Invalid demux %d", dmx_dev_num
);
170 for(i
= 0; i
< MAX_FILTER
; i
++)
172 if(!cdemuxes
[idx
][i
].opened
)
174 cdemuxes
[idx
][i
].fd
= COOLDEMUX_FD(dmx_dev_num
, i
);
175 cs_log_dbg(D_DVBAPI
, "opening new fd: %08x", cdemuxes
[idx
][i
].fd
);
176 cdemuxes
[idx
][i
].demux_index
= dmx_dev_num
;
177 return &cdemuxes
[idx
][i
];
180 cs_log_dbg(D_DVBAPI
, "ERROR: no free demux found");
184 idx
= COOLDEMUX_DMX_DEV(fd
);
185 for(i
= 0; i
< MAX_FILTER
; i
++)
187 if(cdemuxes
[idx
][i
].fd
== fd
)
188 { return &cdemuxes
[idx
][i
]; }
191 cs_log_dbg(D_DVBAPI
, "ERROR: CANT FIND Demux %08x", fd
);
196 static void coolapi_read_data(dmx_t
*dmx
, dmx_callback_data_t
*data
)
200 cs_log_dbg(D_DVBAPI
, "handle is NULL!");
206 SAFE_SETSPECIFIC(getclient
, dvbapi_client
);
207 SAFE_MUTEX_LOCK(&dmx
->mutex
);
208 memset(dmx
->buffer
, 0, 4096);
209 ret
= coolapi_read(dmx
, data
);
210 SAFE_MUTEX_UNLOCK(&dmx
->mutex
);
212 { dvbapi_process_input(dmx
->demux_id
, dmx
->filter_num
, dmx
->buffer
, data
->len
, 0); }
215 static void dmx_callback(void *UNUSED(unk
), dmx_t
*dmx
, int32_t type
, dmx_callback_data_t
*data
)
219 cs_log_dbg(D_DVBAPI
, "wrong dmx pointer !!!");
228 if(data
->type
== 1 && data
->len
> 0)
230 coolapi_read_data(dmx
, data
);
233 { cs_log_dbg(D_DVBAPI
, "unknown callback data %d len %d", data
->type
, data
->len
); }
242 int32_t coolapi_set_filter(int32_t fd
, int32_t num
, int32_t pid
, uint8_t *flt
, uint8_t *mask
, int32_t type
)
244 dmx_t
*dmx
= find_demux(fd
, 0);
247 cs_log_dbg(D_DVBAPI
, "dmx is NULL!");
251 int32_t result
, channel_found
= 0;
253 void *channel
= NULL
;
255 if(ll_count(ll_cool_chanhandle
) > 0)
257 LL_ITER itr
= ll_iter_create(ll_cool_chanhandle
);
258 S_COOL_CHANHANDLE
*handle_item
;
259 while((handle_item
= ll_iter_next(&itr
)))
261 if(handle_item
->demux_index
== dmx
->demux_index
&& handle_item
->pid
== pid
)
263 channel
= handle_item
->channel
;
272 buffer_open_arg_t bufarg
;
273 int32_t uBufferSize
= 8256;
274 memset(&bufarg
, 0, sizeof(bufarg
));
277 bufarg
.size
= uBufferSize
;
278 bufarg
.unknown3
= (uBufferSize
* 7) / 8;
280 result
= cnxt_cbuf_open(&dmx
->buffer1
, &bufarg
, NULL
, NULL
);
281 coolapi_check_error("cnxt_cbuf_open", result
);
285 result
= cnxt_cbuf_open(&dmx
->buffer2
, &bufarg
, NULL
, NULL
);
286 coolapi_check_error("cnxt_cbuf_open", result
);
288 channel_open_arg_t chanarg
;
289 memset(&chanarg
, 0, sizeof(channel_open_arg_t
));
292 result
= cnxt_dmx_channel_open(dmx
->device
, &dmx
->channel
, &chanarg
, dmx_callback
, dmx
);
293 coolapi_check_error("cnxt_dmx_channel_open", result
);
295 result
= cnxt_dmx_set_channel_buffer(dmx
->channel
, 0, dmx
->buffer1
);
296 coolapi_check_error("cnxt_dmx_set_channel_buffer", result
);
298 result
= cnxt_dmx_channel_attach(dmx
->channel
, 0xB, 0, dmx
->buffer2
);
299 coolapi_check_error("cnxt_dmx_channel_attach", result
);
301 result
= cnxt_cbuf_attach(dmx
->buffer2
, 2, dmx
->channel
);
302 coolapi_check_error("cnxt_cbuf_attach", result
);
304 result
= cnxt_dmx_set_channel_pid(dmx
->channel
, pid
);
305 coolapi_check_error("cnxt_dmx_set_channel_pid", result
);
307 result
= cnxt_cbuf_flush(dmx
->buffer1
, 0);
308 coolapi_check_error("cnxt_cbuf_flush", result
);
309 result
= cnxt_cbuf_flush(dmx
->buffer2
, 0);
310 coolapi_check_error("cnxt_cbuf_flush", result
);
312 S_COOL_CHANHANDLE
*handle_item
;
313 if(cs_malloc(&handle_item
, sizeof(S_COOL_CHANHANDLE
)))
315 handle_item
->pid
= pid
;
316 handle_item
->channel
= dmx
->channel
;
317 handle_item
->buffer1
= dmx
->buffer1
;
318 handle_item
->buffer2
= dmx
->buffer2
;
319 handle_item
->demux_index
= dmx
->demux_index
;
320 ll_append(ll_cool_chanhandle
, handle_item
);
322 cs_log_dbg(D_DVBAPI
, "opened new channel %x", (int32_t) dmx
->channel
);
327 dmx
->channel
= channel
;
332 cs_log_dbg(D_DVBAPI
, "setting new filter fd=%08x demux=%d channel=%x num=%d pid=%04x flt=%x mask=%x", fd
, dmx
->demux_index
, (int32_t) dmx
->channel
, num
, pid
, flt
[0], mask
[0]);
334 SAFE_MUTEX_LOCK(&dmx
->mutex
);
337 dmx
->filter_num
= num
;
341 memset(&filter
, 0, sizeof(filter
));
343 memcpy(filter
.filter
, flt
, 16);
344 memcpy(filter
.mask
, mask
, 16);
346 result
= cnxt_dmx_open_filter(dmx
->device
, &dmx
->filter
);
347 coolapi_check_error("cnxt_dmx_open_filter", result
);
349 result
= cnxt_dmx_set_filter(dmx
->filter
, &filter
, NULL
);
350 coolapi_check_error("cnxt_dmx_set_filter", result
);
352 result
= cnxt_dmx_channel_suspend(dmx
->channel
, 1);
353 coolapi_check_error("cnxt_dmx_channel_suspend", result
);
354 result
= cnxt_dmx_channel_attach_filter(dmx
->channel
, dmx
->filter
);
355 coolapi_check_error("cnxt_dmx_channel_attach_filter", result
);
356 result
= cnxt_dmx_channel_suspend(dmx
->channel
, 0);
357 coolapi_check_error("cnxt_dmx_channel_suspend", result
);
361 result
= cnxt_dmx_channel_ctrl(dmx
->channel
, 0, 0);
362 coolapi_check_error("cnxt_dmx_channel_ctrl", result
);
365 result
= cnxt_dmx_channel_ctrl(dmx
->channel
, 2, 0);
366 coolapi_check_error("cnxt_dmx_channel_ctrl", result
);
368 SAFE_MUTEX_UNLOCK(&dmx
->mutex
);
370 S_COOL_FILTER
*filter_item
;
371 if(cs_malloc(&filter_item
, sizeof(S_COOL_FILTER
)))
374 filter_item
->fd
= fd
;
375 filter_item
->pid
= pid
;
376 filter_item
->channel
= (int32_t) dmx
->channel
;
377 memcpy(filter_item
->filter16
, flt
, 16);
378 memcpy(filter_item
->mask16
, mask
, 16);
381 ll_append(ll_cool_filter
, filter_item
);
386 int32_t coolapi_remove_filter(int32_t fd
, int32_t num
)
388 dmx_t
*dmx
= find_demux(fd
, 0);
391 cs_log_dbg(D_DVBAPI
, "dmx is NULL!");
398 int32_t result
, filter_on_channel
= 0;
400 cs_log_dbg(D_DVBAPI
, "removing filter fd=%08x num=%d pid=%04x on channel=%x", fd
, num
, dmx
->pid
, (int32_t) dmx
->channel
);
402 SAFE_MUTEX_LOCK(&dmx
->mutex
);
406 result
= cnxt_dmx_channel_suspend(dmx
->channel
, 1);
407 coolapi_check_error("cnxt_dmx_channel_suspend", result
);
408 result
= cnxt_dmx_channel_detach_filter(dmx
->channel
, dmx
->filter
);
409 coolapi_check_error("cnxt_dmx_channel_detach_filter", result
);
410 result
= cnxt_dmx_channel_suspend(dmx
->channel
, 0);
411 coolapi_check_error("cnxt_dmx_channel_suspend", result
);
412 result
= cnxt_dmx_close_filter(dmx
->filter
);
413 coolapi_check_error("cnxt_dmx_close_filter", result
);
415 result
= cnxt_dmx_channel_ctrl(dmx
->channel
, 0, 0);
416 coolapi_check_error("cnxt_dmx_channel_ctrl", result
);
419 LL_ITER itr
= ll_iter_create(ll_cool_filter
);
420 S_COOL_FILTER
*filter_item
;
421 while((filter_item
= ll_iter_next(&itr
)))
423 if(filter_item
->channel
== (int32_t) dmx
->channel
)
424 { filter_on_channel
++; }
425 if(filter_item
->fd
== fd
)
427 ll_iter_remove_data(&itr
);
432 if(!filter_on_channel
)
434 cs_log_dbg(D_DVBAPI
, "closing channel %x", (int32_t) dmx
->channel
);
436 itr
= ll_iter_create(ll_cool_chanhandle
);
437 S_COOL_CHANHANDLE
*handle_item
;
438 while((handle_item
= ll_iter_next(&itr
)))
440 if(handle_item
->demux_index
== dmx
->demux_index
&& handle_item
->pid
== dmx
->pid
)
442 dmx
->buffer1
= handle_item
->buffer1
;
443 dmx
->buffer2
= handle_item
->buffer2
;
444 ll_iter_remove_data(&itr
);
449 if(!dmx
->buffer1
|| !dmx
->buffer2
)
450 { cs_log_dbg(D_DVBAPI
, "WARNING: buffer handle not found!"); }
452 result
= cnxt_dmx_channel_ctrl(dmx
->channel
, 0, 0);
453 coolapi_check_error("cnxt_dmx_channel_ctrl", result
);
455 result
= cnxt_dmx_set_channel_pid(dmx
->channel
, 0x1FFF);
456 coolapi_check_error("cnxt_dmx_set_channel_pid", result
);
458 result
= cnxt_cbuf_flush(dmx
->buffer1
, 0);
459 coolapi_check_error("cnxt_cbuf_flush", result
);
461 result
= cnxt_cbuf_flush(dmx
->buffer2
, 0);
462 coolapi_check_error("cnxt_cbuf_flush", result
);
464 result
= cnxt_cbuf_detach(dmx
->buffer2
, 2, dmx
->channel
);
465 coolapi_check_error("cnxt_cbuf_detach", result
);
466 result
= cnxt_dmx_channel_detach(dmx
->channel
, 0xB, 0, dmx
->buffer1
);
467 coolapi_check_error("cnxt_dmx_channel_detach", result
);
469 result
= cnxt_dmx_channel_close(dmx
->channel
);
470 coolapi_check_error("cnxt_dmx_channel_close", result
);
472 result
= cnxt_cbuf_close(dmx
->buffer2
);
473 coolapi_check_error("cnxt_cbuf_close", result
);
475 result
= cnxt_cbuf_close(dmx
->buffer1
);
476 coolapi_check_error("cnxt_cbuf_close", result
);
479 if(filter_on_channel
)
481 result
= cnxt_dmx_channel_ctrl(dmx
->channel
, 2, 0);
482 coolapi_check_error("cnxt_dmx_channel_ctrl", result
);
485 SAFE_MUTEX_UNLOCK(&dmx
->mutex
);
491 int32_t coolapi_open_device(int32_t demux_index
, int32_t demux_id
)
497 dmx
= find_demux(0, demux_index
);
500 cs_log("no free demux found");
505 { ll_cool_filter
= ll_create("ll_cool_filter"); }
507 if(!ll_cool_chanhandle
)
508 { ll_cool_chanhandle
= ll_create("ll_cool_chanhandle"); }
510 dmx
->demux_index
= demux_index
;
511 dmx
->demux_id
= demux_id
;
514 dmx
->device
= dmx_device
[demux_index
];
517 pthread_mutexattr_t attr
;
518 SAFE_MUTEXATTR_INIT(&attr
);
519 SAFE_MUTEXATTR_SETTYPE(&attr
, PTHREAD_MUTEX_ERRORCHECK_NP
);
520 SAFE_MUTEX_INIT(&dmx
->mutex
, &attr
);
525 int32_t coolapi_close_device(int32_t fd
)
527 dmx_t
*dmx
= find_demux(fd
, 0);
530 cs_log_dbg(D_DVBAPI
, "dmx is NULL!");
534 cs_log_dbg(D_DVBAPI
, "closing fd=%08x", fd
);
536 pthread_mutex_destroy(&dmx
->mutex
);
538 memset(dmx
, 0, sizeof(dmx_t
));
542 /* write cw to all demuxes in mask with passed index */
543 int32_t coolapi_write_cw(int32_t mask
, uint16_t *STREAMpids
, int32_t count
, ca_descr_t
*ca_descr
)
545 int32_t i
, idx
= ca_descr
->index
;
549 cs_log_dbg(D_DVBAPI
, "cw%d: mask %d index %d pid count %d", ca_descr
->parity
, mask
, idx
, count
);
550 for(i
= 0; i
< count
; i
++)
552 int32_t pid
= STREAMpids
[i
];
554 for(j
= 0; j
< MAX_COOL_DMX
; j
++)
558 result
= cnxt_dmx_get_channel_from_pid(dmx_device
[j
], pid
, &channel
);
561 cs_log_dbg(D_DVBAPI
, "Found demux %d channel %x for pid %04x", j
, (int32_t) channel
, pid
);
562 result
= cnxt_dmx_set_channel_key(channel
, 0, ca_descr
->parity
, ca_descr
->cw
, 8);
563 coolapi_check_error("cnxt_dmx_set_channel_key", result
);
566 cs_log("set_channel_key failed for demux %d pid %04x", j
, pid
);
575 static int32_t coolapi_read(dmx_t
*dmx
, dmx_callback_data_t
*data
)
579 cs_log_dbg(D_DVBAPI
, "dmx is NULL!");
584 uint32_t done
= 0, toread
, len
= data
->len
;
585 uint8_t *buff
= &dmx
->buffer
[0];
586 uint32_t bytes_used
= 0;
588 //cs_log_dbg(D_DVBAPI, "dmx channel %x pid %x len %d", (int) dmx->channel, dmx->pid, len);
590 result
= cnxt_cbuf_get_used(data
->buf
, &bytes_used
);
591 coolapi_check_error("cnxt_cbuf_get_used", result
);
595 result
= cnxt_cbuf_read_data(data
->buf
, buff
, 3, &done
);
596 coolapi_check_error("cnxt_cbuf_read_data", result
);
601 toread
= ((buff
[1] << 8) | buff
[2]) & 0xFFF;
602 if((toread
+ 3) > len
)
604 result
= cnxt_cbuf_read_data(data
->buf
, buff
+ 3, toread
, &done
);
605 coolapi_check_error("cnxt_cbuf_read_data", result
);
610 //cs_log_dbg(D_DVBAPI, "bytes read %d\n", done);
615 void coolapi_open_all(void)
617 cnxt_kal_initialize();
623 static void coolapi_open(void)
626 device_open_arg_t devarg
;
632 cs_log_dbg(D_DVBAPI
, "Open Coolstream DMX API");
633 cnxt_cbuf_init(NULL
);
636 memset(&devarg
, 0, sizeof(device_open_arg_t
));
641 for(i
= 0; i
< MAX_COOL_DMX
; i
++)
644 result
= cnxt_dmx_open(&dmx_device
[i
], &devarg
, NULL
, NULL
);
645 coolapi_check_error("cnxt_dmx_open", result
);
651 void coolapi_close_all(void)
658 for(i
= 0; i
< MAX_COOL_DMX
; i
++)
660 for(j
= 0; j
< MAX_FILTER
; j
++)
662 if(cdemuxes
[i
][j
].fd
> 0)
664 coolapi_remove_filter(cdemuxes
[i
][j
].fd
, cdemuxes
[i
][j
].filter_num
);
665 coolapi_close_device(cdemuxes
[i
][j
].fd
);
669 for(i
= 0; i
< MAX_COOL_DMX
; i
++)
671 result
= cnxt_dmx_close(dmx_device
[i
]);
672 coolapi_check_error("cnxt_dmx_close", result
);
673 dmx_device
[i
] = NULL
;
677 cnxt_kal_terminate();
680 #elif defined(HAVE_DVBAPI) && defined(WITH_SU980)
681 #include "extapi/coolapi.h"
682 void cnxt_css_drv_init(void);
683 void cnxt_css_drv_term(void);
684 void cnxt_smc_term(void);
686 int32_t cool_kal_opened
= 0;
687 void coolapi_open_all(void)
689 cnxt_kal_initialize();
695 void coolapi_close_all(void)
697 cnxt_kal_terminate();