[gbx] - more generalized routing info in cw msg
[oscam.git] / module-dvbapi-coolapi-legacy.c
bloba04589ee8f8a3767f1a122be83157707eea67ded
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_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
19 int32_t fd;
20 int32_t channel;
21 int32_t pid;
22 uint8_t filter16[16];
23 uint8_t mask16[16];
24 } S_COOL_FILTER;
26 typedef struct s_cool_chanhandle
28 int32_t pid;
29 void *buffer1;
30 void *buffer2;
31 void *channel;
32 int32_t demux_index;
33 } S_COOL_CHANHANDLE;
35 struct cool_dmx
37 int32_t opened;
38 int32_t fd;
39 uint8_t buffer[4096];
40 void *buffer1;
41 void *buffer2;
42 void *channel;
43 void *filter;
44 void *device;
45 int32_t pid;
46 pthread_mutex_t mutex;
47 int32_t demux_index;
48 int32_t demux_id;
49 int32_t filter_num;
50 int32_t type;
52 typedef struct cool_dmx dmx_t;
54 typedef struct
56 int32_t type;
57 uint32_t size;
58 int32_t unknown1;
59 int16_t unknown2;
60 int32_t unknown3;
61 int32_t unknown[4];
62 } buffer_open_arg_t;
64 typedef struct
66 int32_t type;
67 int32_t unknown[2];
68 } channel_open_arg_t;
70 typedef struct
72 uint32_t number;
73 int32_t unknown1;
74 int32_t unknown2;
75 int32_t unknown3;
76 int32_t unknown4;
77 int32_t unknown5;
78 int32_t unknown6;
79 int32_t unknown[6];
80 } device_open_arg_t;
82 typedef struct
84 uint32_t length;
85 uint8_t filter[18]; //strange: initialization with max 18 possible but length limited to 12
86 uint8_t mask[18];
87 uint8_t nmask[18];
88 int8_t fvernum;
89 int8_t crcchange;
90 int8_t keeprbytes;
91 int32_t mode;
92 } filter_set_t;
95 typedef enum
97 CONTINUOUS_ACQUIRE = 0,
98 ONE_SHOT_ACQUIRE,
99 TOGGLE_ACQUIRE
100 } DATA_ACQUIRE_MODE;
102 typedef enum
104 DATA_ACQUIRED = 1,
105 CHANNEL_TIMEOUT,
106 CRC_ERROR,
107 BUF_OVERFLOW,
108 PES_ERROR,
109 COPY_DONE,
110 CHANNEL_INFO
111 } DATA_ACQUIRE_STATUS;
113 typedef struct
115 uint32_t PTSLow;
116 uint32_t PTSHi;
117 } DMX_PTS;
119 typedef struct
121 void *channel;
122 DATA_ACQUIRE_STATUS type;
123 DMX_PTS ptssnapshop;
124 DATA_ACQUIRE_MODE mode;
125 void *buf;
126 uint32_t len;
127 uint32_t num;
128 void *filters[64];
129 void *tags[64];
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);
162 return NULL;
165 int32_t i, idx;
167 idx = dmx_dev_num;
168 if(fd == 0)
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");
181 return NULL;
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);
193 return NULL;
196 static void coolapi_read_data(dmx_t *dmx, dmx_callback_data_t *data)
198 if(!dmx)
200 cs_log_dbg(D_DVBAPI, "handle is NULL!");
201 return;
204 int32_t ret;
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);
211 if(ret > -1)
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)
217 if(!dmx)
219 cs_log_dbg(D_DVBAPI, "wrong dmx pointer !!!");
220 return;
223 if(data != NULL)
225 switch(type)
227 case 0xE:
228 if(data->type == 1 && data->len > 0)
230 coolapi_read_data(dmx, data);
232 else
233 { cs_log_dbg(D_DVBAPI, "unknown callback data %d len %d", data->type, data->len); }
234 break;
235 default:
236 break;
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);
245 if(!dmx)
247 cs_log_dbg(D_DVBAPI, "dmx is NULL!");
248 return -1;
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;
264 channel_found = 1;
265 break;
270 if(!channel)
272 buffer_open_arg_t bufarg;
273 int32_t uBufferSize = 8256;
274 memset(&bufarg, 0, sizeof(bufarg));
276 bufarg.type = 3;
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);
283 bufarg.type = 0;
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));
290 chanarg.type = 4;
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);
324 else
326 channel_found = 1;
327 dmx->channel = channel;
328 dmx->buffer1 = NULL;
329 dmx->buffer2 = NULL;
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);
336 filter_set_t filter;
337 dmx->filter_num = num;
338 dmx->pid = pid;
339 dmx->type = type;
341 memset(&filter, 0, sizeof(filter));
342 filter.length = 12;
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);
359 if(channel_found)
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)))
373 // fill filter item
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);
380 //add filter item
381 ll_append(ll_cool_filter, filter_item);
383 return 0;
386 int32_t coolapi_remove_filter(int32_t fd, int32_t num)
388 dmx_t *dmx = find_demux(fd, 0);
389 if(!dmx)
391 cs_log_dbg(D_DVBAPI, "dmx is NULL!");
392 return -1;
395 if(dmx->pid <= 0)
396 { return -1; }
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);
404 if(dmx->filter)
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);
414 dmx->filter = NULL;
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);
428 filter_on_channel--;
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);
445 break;
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);
487 dmx->pid = -1;
488 return 0;
491 int32_t coolapi_open_device(int32_t demux_index, int32_t demux_id)
493 dmx_t *dmx;
495 coolapi_open();
497 dmx = find_demux(0, demux_index);
498 if(!dmx)
500 cs_log("no free demux found");
501 return 0;
504 if(!ll_cool_filter)
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;
512 dmx->pid = -1;
514 dmx->device = dmx_device[demux_index];
515 dmx->opened = 1;
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);
522 return dmx->fd;
525 int32_t coolapi_close_device(int32_t fd)
527 dmx_t *dmx = find_demux(fd, 0);
528 if(!dmx)
530 cs_log_dbg(D_DVBAPI, "dmx is NULL!");
531 return -1;
534 cs_log_dbg(D_DVBAPI, "closing fd=%08x", fd);
535 dmx->opened = 0;
536 pthread_mutex_destroy(&dmx->mutex);
538 memset(dmx, 0, sizeof(dmx_t));
539 return 0;
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;
546 int32_t result;
547 void *channel;
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];
553 int32_t j;
554 for(j = 0; j < MAX_COOL_DMX; j++)
556 if(mask & (1 << j))
558 result = cnxt_dmx_get_channel_from_pid(dmx_device[j], pid, &channel);
559 if(result == 0)
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);
564 if(result != 0)
566 cs_log("set_channel_key failed for demux %d pid %04x", j, pid);
572 return 0;
575 static int32_t coolapi_read(dmx_t *dmx, dmx_callback_data_t *data)
577 if(!dmx)
579 cs_log_dbg(D_DVBAPI, "dmx is NULL!");
580 return -1;
583 int32_t result;
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);
592 if(bytes_used == 0)
593 { return -1; }
595 result = cnxt_cbuf_read_data(data->buf, buff, 3, &done);
596 coolapi_check_error("cnxt_cbuf_read_data", result);
598 if(done != 3)
599 { return -1; }
601 toread = ((buff[1] << 8) | buff[2]) & 0xFFF;
602 if((toread + 3) > len)
603 { return -1; }
604 result = cnxt_cbuf_read_data(data->buf, buff + 3, toread, &done);
605 coolapi_check_error("cnxt_cbuf_read_data", result);
606 if(done != toread)
607 { return -1; }
608 done += 3;
610 //cs_log_dbg(D_DVBAPI, "bytes read %d\n", done);
612 return 0;
615 void coolapi_open_all(void)
617 cnxt_kal_initialize();
618 cnxt_drv_init();
619 cnxt_smc_init(NULL);
620 cool_kal_opened = 1;
623 static void coolapi_open(void)
625 int32_t result = 0;
626 device_open_arg_t devarg;
628 if(!dmx_opened)
630 int32_t i;
632 cs_log_dbg(D_DVBAPI, "Open Coolstream DMX API");
633 cnxt_cbuf_init(NULL);
634 cnxt_dmx_init(NULL);
636 memset(&devarg, 0, sizeof(device_open_arg_t));
638 devarg.unknown1 = 1;
639 devarg.unknown3 = 3;
640 devarg.unknown6 = 1;
641 for(i = 0; i < MAX_COOL_DMX; i++)
643 devarg.number = i;
644 result = cnxt_dmx_open(&dmx_device[i], &devarg, NULL, NULL);
645 coolapi_check_error("cnxt_dmx_open", result);
647 dmx_opened = 1;
651 void coolapi_close_all(void)
653 if(dmx_opened)
655 int32_t result;
656 int32_t i, j;
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;
676 cool_kal_opened = 0;
677 cnxt_kal_terminate();
678 cnxt_drv_term();
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();
690 cnxt_css_drv_init();
691 cnxt_smc_init(0);
692 cool_kal_opened = 1;
695 void coolapi_close_all(void)
697 cnxt_kal_terminate();
698 cool_kal_opened = 0;
700 #endif