1 | /* Reversed from libcoolstream.so, this comes without any warranty */
|
---|
2 |
|
---|
3 | #define MODULE_LOG_PREFIX "dvbcool"
|
---|
4 |
|
---|
5 | #include "globals.h"
|
---|
6 |
|
---|
7 | #if defined(HAVE_DVBAPI) && (defined(WITH_SU980) || defined(WITH_COOLAPI2) || defined(WITH_COOLAPI))
|
---|
8 | #include "extapi/coolapi.h"
|
---|
9 |
|
---|
10 | #include "module-dvbapi.h"
|
---|
11 | #include "module-dvbapi-coolapi.h"
|
---|
12 | #include "oscam-string.h"
|
---|
13 |
|
---|
14 |
|
---|
15 | #define MAX_COOL_DMX 4
|
---|
16 |
|
---|
17 | //kronos-Plattform (Coolsterem ZEE²)
|
---|
18 | //#define MAX_COOL_DMX 3
|
---|
19 |
|
---|
20 |
|
---|
21 | #define DMX_MAX_FILTERS_PER_CHAN 16
|
---|
22 | #define DMX_MAX_CHANNELS_PER_DMX 192
|
---|
23 | //#define MAX_COOL_DMX_FILTERS 128
|
---|
24 |
|
---|
25 | struct s_cool_chanhandle;
|
---|
26 |
|
---|
27 | typedef struct s_cool_filter
|
---|
28 | {
|
---|
29 | int32_t fd;
|
---|
30 | struct s_cool_chanhandle *chanhandle;
|
---|
31 | void *filter;
|
---|
32 | int32_t filter_num;
|
---|
33 | uchar filter16[16];
|
---|
34 | uchar mask16[16];
|
---|
35 | } S_COOL_FILTER;
|
---|
36 |
|
---|
37 | typedef struct s_cool_chanhandle
|
---|
38 | {
|
---|
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;
|
---|
47 |
|
---|
48 | typedef struct s_cool_dmxhandle
|
---|
49 | {
|
---|
50 | void *handle;
|
---|
51 | uint32_t allocated_channels;
|
---|
52 | } S_COOL_DMXHANDLE;
|
---|
53 |
|
---|
54 | struct cool_dmx
|
---|
55 | {
|
---|
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;
|
---|
63 | };
|
---|
64 | typedef struct cool_dmx dmx_t;
|
---|
65 |
|
---|
66 | typedef struct
|
---|
67 | {
|
---|
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;
|
---|
84 |
|
---|
85 | typedef struct
|
---|
86 | {
|
---|
87 | int32_t type;
|
---|
88 | int32_t unknown[2];
|
---|
89 | } channel_open_arg_t;
|
---|
90 |
|
---|
91 | // Nevis : 13
|
---|
92 | // Apollo: 13
|
---|
93 | typedef struct
|
---|
94 | {
|
---|
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;
|
---|
104 |
|
---|
105 | typedef struct
|
---|
106 | {
|
---|
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;
|
---|
116 |
|
---|
117 |
|
---|
118 | typedef enum
|
---|
119 | {
|
---|
120 | CONTINUOUS_ACQUIRE = 0,
|
---|
121 | ONE_SHOT_ACQUIRE,
|
---|
122 | TOGGLE_ACQUIRE
|
---|
123 | } DATA_ACQUIRE_MODE;
|
---|
124 |
|
---|
125 | typedef enum
|
---|
126 | {
|
---|
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;
|
---|
135 |
|
---|
136 | typedef struct
|
---|
137 | {
|
---|
138 | uint32_t PTSLow;
|
---|
139 | uint32_t PTSHi;
|
---|
140 | } DMX_PTS;
|
---|
141 |
|
---|
142 | typedef struct
|
---|
143 | {
|
---|
144 | void *channel;
|
---|
145 | DATA_ACQUIRE_STATUS type;
|
---|
146 | //
|
---|
147 | DMX_PTS ptssnapshot;
|
---|
148 | void *buf;
|
---|
149 | uint32_t start;
|
---|
150 | //
|
---|
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;
|
---|
157 |
|
---|
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);
|
---|
164 |
|
---|
165 | /* Local coolapi functions */
|
---|
166 | static int32_t coolapi_read(dmx_t *dmx, dmx_callback_data_t *dataa, uchar *buffer);
|
---|
167 |
|
---|
168 | static int8_t dmx_opened;
|
---|
169 | int32_t cool_kal_opened = 0;
|
---|
170 |
|
---|
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;
|
---|
175 |
|
---|
176 | static LLIST *ll_cool_filter = NULL;
|
---|
177 | static LLIST *ll_cool_chanhandle = NULL;
|
---|
178 |
|
---|
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)))
|
---|
184 |
|
---|
185 | #define COOLDEMUX_DATA_RECEIVED 1
|
---|
186 | #define COOLDEMUX_CHANNEL_TIMEOUT 2
|
---|
187 | #define COOLDEMUX_CRC_ERROR 3
|
---|
188 | #define COOLDEMUX_BUFF_OVERFLOW 4
|
---|
189 |
|
---|
190 | static dmx_t *find_demux(int32_t fd, int32_t dmx_dev_num)
|
---|
191 | {
|
---|
192 | if(dmx_dev_num < 0 || dmx_dev_num >= MAX_COOL_DMX)
|
---|
193 | {
|
---|
194 | cs_log("Invalid demux %d", dmx_dev_num);
|
---|
195 | return NULL;
|
---|
196 | }
|
---|
197 |
|
---|
198 | dmx_t *dmx;
|
---|
199 | int32_t i;
|
---|
200 |
|
---|
201 | if(fd == 0) // DEMUX FILTER ALLOCATE
|
---|
202 | {
|
---|
203 | for(i = 0; i < MAX_FILTER; i++)
|
---|
204 | {
|
---|
205 | dmx = &cdemuxes[dmx_dev_num][i];
|
---|
206 | if(!dmx->opened)
|
---|
207 | {
|
---|
208 | dmx->fd = COOLDEMUX_FD(dmx_dev_num, i);
|
---|
209 | cs_log_dbg(D_DVBAPI, "opening new fd: %08x", dmx->fd);
|
---|
210 | return dmx;
|
---|
211 | }
|
---|
212 | }
|
---|
213 | cs_log_dbg(D_DVBAPI, "ERROR: no free demux found");
|
---|
214 | return NULL;
|
---|
215 | }
|
---|
216 |
|
---|
217 | if (!COOLDEMUX_IS_VALID_FD(fd))
|
---|
218 | {
|
---|
219 | cs_log_dbg(D_DVBAPI, "ERROR: invalid FD");
|
---|
220 | return NULL;
|
---|
221 | }
|
---|
222 |
|
---|
223 | dmx_dev_num = COOLDEMUX_DMX_DEV(fd);
|
---|
224 | for(i = 0; i < MAX_FILTER; i++)
|
---|
225 | {
|
---|
226 | dmx = &cdemuxes[dmx_dev_num][i];
|
---|
227 | if(dmx->fd == fd)
|
---|
228 | {
|
---|
229 | return dmx;
|
---|
230 | }
|
---|
231 | }
|
---|
232 |
|
---|
233 | cs_log_dbg(D_DVBAPI, "ERROR: CANT FIND Demux %08x", fd);
|
---|
234 |
|
---|
235 | return NULL;
|
---|
236 | }
|
---|
237 |
|
---|
238 | int32_t coolapi_get_filter_num(int32_t fd)
|
---|
239 | {
|
---|
240 | if (!COOLDEMUX_IS_VALID_FD(fd))
|
---|
241 | {
|
---|
242 | cs_log_dbg(D_DVBAPI, "ERROR: invalid FD");
|
---|
243 | return -1;
|
---|
244 | }
|
---|
245 |
|
---|
246 | return cdemuxes[COOLDEMUX_DMX_DEV(fd)][COOLDEMUX_FLT_IDX(fd)].filter_num;
|
---|
247 | }
|
---|
248 |
|
---|
249 | static S_COOL_CHANHANDLE *find_chanhandle(int32_t demux_index, int32_t pid)
|
---|
250 | {
|
---|
251 | // Find matching channel, if it exists.
|
---|
252 | if(ll_count(ll_cool_chanhandle) > 0)
|
---|
253 | {
|
---|
254 | LL_ITER itr = ll_iter_create(ll_cool_chanhandle);
|
---|
255 | S_COOL_CHANHANDLE *handle_item;
|
---|
256 |
|
---|
257 | while((handle_item = ll_iter_next(&itr)))
|
---|
258 | {
|
---|
259 | if(handle_item->demux_index == demux_index && handle_item->pid == pid)
|
---|
260 | {
|
---|
261 | return handle_item;
|
---|
262 | }
|
---|
263 | }
|
---|
264 | }
|
---|
265 |
|
---|
266 | return NULL;
|
---|
267 | }
|
---|
268 |
|
---|
269 | static int32_t remove_chanhandle(S_COOL_CHANHANDLE *handle)
|
---|
270 | {
|
---|
271 | // Find matching channel, if it exists.
|
---|
272 | if(ll_count(ll_cool_chanhandle) > 0)
|
---|
273 | {
|
---|
274 | LL_ITER itr = ll_iter_create(ll_cool_chanhandle);
|
---|
275 | S_COOL_CHANHANDLE *handle_item;
|
---|
276 |
|
---|
277 | while((handle_item = ll_iter_next(&itr)))
|
---|
278 | {
|
---|
279 | if(handle_item == handle)
|
---|
280 | {
|
---|
281 | ll_iter_remove_data(&itr);
|
---|
282 | return 0;
|
---|
283 | }
|
---|
284 | }
|
---|
285 | }
|
---|
286 |
|
---|
287 | return -1;
|
---|
288 | }
|
---|
289 |
|
---|
290 | static S_COOL_FILTER *find_filter_by_chanhandle(S_COOL_CHANHANDLE *chanhandle, int32_t filter_num)
|
---|
291 | {
|
---|
292 | // Find matching channel, if it exists.
|
---|
293 | if(ll_count(ll_cool_filter) > 0)
|
---|
294 | {
|
---|
295 | LL_ITER itr = ll_iter_create(ll_cool_filter);
|
---|
296 | S_COOL_FILTER *filter_item;
|
---|
297 |
|
---|
298 | while((filter_item = ll_iter_next(&itr)))
|
---|
299 | {
|
---|
300 | if(filter_item->chanhandle == chanhandle && filter_item->filter_num == filter_num)
|
---|
301 | {
|
---|
302 | return filter_item;
|
---|
303 | }
|
---|
304 | }
|
---|
305 | }
|
---|
306 |
|
---|
307 | return NULL;
|
---|
308 | }
|
---|
309 |
|
---|
310 | static S_COOL_FILTER *find_filter_by_channel(void *channel, int32_t filter_num)
|
---|
311 | {
|
---|
312 | // Find matching channel, if it exists.
|
---|
313 | if(ll_count(ll_cool_filter) > 0)
|
---|
314 | {
|
---|
315 | LL_ITER itr = ll_iter_create(ll_cool_filter);
|
---|
316 | S_COOL_FILTER *filter_item;
|
---|
317 |
|
---|
318 | while((filter_item = ll_iter_next(&itr)))
|
---|
319 | {
|
---|
320 | if(filter_item->chanhandle &&
|
---|
321 | filter_item->chanhandle->channel == channel &&
|
---|
322 | filter_item->filter_num == filter_num)
|
---|
323 | {
|
---|
324 | return filter_item;
|
---|
325 | }
|
---|
326 | }
|
---|
327 | }
|
---|
328 |
|
---|
329 | return NULL;
|
---|
330 | }
|
---|
331 |
|
---|
332 | static int32_t remove_filter(S_COOL_FILTER *filter_handle)
|
---|
333 | {
|
---|
334 | if(ll_count(ll_cool_filter) > 0)
|
---|
335 | {
|
---|
336 | LL_ITER itr = ll_iter_create(ll_cool_filter);
|
---|
337 | S_COOL_FILTER *filter_item;
|
---|
338 |
|
---|
339 | while((filter_item = ll_iter_next(&itr)))
|
---|
340 | {
|
---|
341 | if(filter_item == filter_handle)
|
---|
342 | {
|
---|
343 | ll_iter_remove_data(&itr);
|
---|
344 | return 0;
|
---|
345 | }
|
---|
346 | }
|
---|
347 | }
|
---|
348 |
|
---|
349 | return -1;
|
---|
350 | }
|
---|
351 |
|
---|
352 | static void coolapi_read_data(dmx_t *dmx, dmx_callback_data_t *data)
|
---|
353 | {
|
---|
354 | if(!dmx)
|
---|
355 | {
|
---|
356 | cs_log_dbg(D_DVBAPI, "handle is NULL!");
|
---|
357 | return;
|
---|
358 | }
|
---|
359 |
|
---|
360 | int32_t ret;
|
---|
361 | uchar buffer[4096];
|
---|
362 |
|
---|
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);
|
---|
368 |
|
---|
369 | if(ret > -1) {
|
---|
370 | uint16_t filters = data->num;
|
---|
371 | uint16_t flt;
|
---|
372 |
|
---|
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);
|
---|
376 |
|
---|
377 | if (!filter || data->filters[flt] != filter->filter)
|
---|
378 | {
|
---|
379 | cs_log_dbg(D_DVBAPI, "filter not found in notification!!!!");
|
---|
380 | continue;
|
---|
381 | }
|
---|
382 |
|
---|
383 | dvbapi_process_input(dmx->demux_id, n, buffer, data->len);
|
---|
384 | }
|
---|
385 | }
|
---|
386 | }
|
---|
387 |
|
---|
388 | static void dmx_callback(void *channel, dmx_t *dmx, int32_t type, dmx_callback_data_t *data)
|
---|
389 | {
|
---|
390 | if(!dmx)
|
---|
391 | {
|
---|
392 | cs_log_dbg(D_DVBAPI, "wrong dmx pointer !!!");
|
---|
393 | return;
|
---|
394 | }
|
---|
395 |
|
---|
396 | if(data == NULL)
|
---|
397 | return;
|
---|
398 |
|
---|
399 | if (channel != data->channel)
|
---|
400 | return;
|
---|
401 |
|
---|
402 | switch(type)
|
---|
403 | {
|
---|
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);
|
---|
418 | }
|
---|
419 | break;
|
---|
420 | default:
|
---|
421 | break;
|
---|
422 | }
|
---|
423 | }
|
---|
424 |
|
---|
425 | int32_t coolapi_set_filter(int32_t fd, int32_t num, int32_t pid, uchar *flt, uchar *mask, int32_t type)
|
---|
426 | {
|
---|
427 | dmx_t *dmx = find_demux(fd, 0);
|
---|
428 | if(!dmx)
|
---|
429 | {
|
---|
430 | cs_log_dbg(D_DVBAPI, "dmx is NULL!");
|
---|
431 | return -1;
|
---|
432 | }
|
---|
433 |
|
---|
434 | int32_t result, channel_found;
|
---|
435 | SAFE_MUTEX_LOCK(&dmx->mutex);
|
---|
436 |
|
---|
437 | // Find matching channel, if it exists.
|
---|
438 | S_COOL_CHANHANDLE *handle_item = find_chanhandle(COOLDEMUX_DMX_DEV(fd), pid);
|
---|
439 | if(!handle_item)
|
---|
440 | {
|
---|
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;
|
---|
446 |
|
---|
447 | if(!cs_malloc(&handle_item, sizeof(S_COOL_CHANHANDLE)))
|
---|
448 | {
|
---|
449 | return -1;
|
---|
450 | }
|
---|
451 |
|
---|
452 | memset(&bufarg, 0, sizeof(bufarg));
|
---|
453 |
|
---|
454 | #ifdef HAVE_COOLAPI2
|
---|
455 | bufarg.poolid = 5
|
---|
456 | #endif
|
---|
457 | bufarg.type = 3;
|
---|
458 | bufarg.size = uBufferSize;
|
---|
459 | bufarg.hwm = (uBufferSize * 7) / 8;
|
---|
460 |
|
---|
461 | result = cnxt_cbuf_open(&handle_item->buffer1, &bufarg, NULL, NULL);
|
---|
462 | coolapi_check_error("cnxt_cbuf_open", result);
|
---|
463 | bufarg.type = 0;
|
---|
464 |
|
---|
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);
|
---|
470 |
|
---|
471 | channel_open_arg_t chanarg;
|
---|
472 | memset(&chanarg, 0, sizeof(channel_open_arg_t));
|
---|
473 |
|
---|
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);
|
---|
477 |
|
---|
478 | result = cnxt_dmx_set_channel_buffer(handle_item->channel, 0, handle_item->buffer1);
|
---|
479 | coolapi_check_error("cnxt_dmx_set_channel_buffer", result);
|
---|
480 |
|
---|
481 | result = cnxt_dmx_channel_attach(handle_item->channel, 0xB, 0, handle_item->buffer2);
|
---|
482 | coolapi_check_error("cnxt_dmx_channel_attach", result);
|
---|
483 |
|
---|
484 | result = cnxt_cbuf_attach(handle_item->buffer2, 2, handle_item->channel);
|
---|
485 | coolapi_check_error("cnxt_cbuf_attach", result);
|
---|
486 |
|
---|
487 | result = cnxt_dmx_set_channel_pid(handle_item->channel, pid);
|
---|
488 | coolapi_check_error("cnxt_dmx_set_channel_pid", result);
|
---|
489 |
|
---|
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);
|
---|
494 |
|
---|
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);
|
---|
499 |
|
---|
500 | cs_log_dbg(D_DVBAPI, "opened new channel %x", (int32_t) handle_item->channel);;
|
---|
501 | }
|
---|
502 | else
|
---|
503 | {
|
---|
504 | channel_found = 1;
|
---|
505 | }
|
---|
506 |
|
---|
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;
|
---|
511 |
|
---|
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)))
|
---|
515 | {
|
---|
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;
|
---|
518 |
|
---|
519 | has_filter = 1;
|
---|
520 |
|
---|
521 | memcpy(filter_item->filter16, flt, 16);
|
---|
522 | memcpy(filter_item->mask16, mask, 16);
|
---|
523 | }
|
---|
524 | else
|
---|
525 | {
|
---|
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);
|
---|
531 |
|
---|
532 | if(!cs_malloc(&filter_item, sizeof(S_COOL_FILTER)))
|
---|
533 | {
|
---|
534 | SAFE_MUTEX_UNLOCK(&dmx->mutex);
|
---|
535 | return -1;
|
---|
536 | }
|
---|
537 |
|
---|
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);
|
---|
545 |
|
---|
546 | //add filter item
|
---|
547 | ll_append(ll_cool_filter, filter_item);
|
---|
548 | // increase allocated filters
|
---|
549 | handle_item->allocated_filters++;
|
---|
550 | }
|
---|
551 |
|
---|
552 | if (has_filter)
|
---|
553 | {
|
---|
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);
|
---|
558 | }
|
---|
559 |
|
---|
560 | memset(&filterset, 0, sizeof(filterset));
|
---|
561 | filterset.length = 12;
|
---|
562 | memcpy(filterset.filter, flt, 16);
|
---|
563 | memcpy(filterset.mask, mask, 16);
|
---|
564 |
|
---|
565 | result = cnxt_dmx_set_filter(filter_handle, &filterset, (void *)num);
|
---|
566 | coolapi_check_error("cnxt_dmx_set_filter", result);
|
---|
567 |
|
---|
568 | result = cnxt_dmx_channel_attach_filter(handle_item->channel, filter_handle);
|
---|
569 | coolapi_check_error("cnxt_dmx_channel_attach_filter", result);
|
---|
570 |
|
---|
571 | if (has_filter)
|
---|
572 | {
|
---|
573 | result = cnxt_dmx_channel_suspend(handle_item->channel, 0);
|
---|
574 | coolapi_check_error("cnxt_dmx_channel_suspend", result);
|
---|
575 | }
|
---|
576 |
|
---|
577 | if(!channel_found)
|
---|
578 | {
|
---|
579 | // Start channel
|
---|
580 | result = cnxt_dmx_channel_ctrl(handle_item->channel, 2, 0);
|
---|
581 | coolapi_check_error("cnxt_dmx_channel_ctrl", result);
|
---|
582 | }
|
---|
583 |
|
---|
584 | SAFE_MUTEX_UNLOCK(&dmx->mutex);
|
---|
585 |
|
---|
586 | return 0;
|
---|
587 | }
|
---|
588 |
|
---|
589 | int32_t coolapi_remove_filter(int32_t fd, int32_t num)
|
---|
590 | {
|
---|
591 | void * channel = NULL;
|
---|
592 | void * filter = NULL;
|
---|
593 |
|
---|
594 | dmx_t *dmx = find_demux(fd, 0);
|
---|
595 | if(!dmx)
|
---|
596 | {
|
---|
597 | cs_log_dbg(D_DVBAPI, "dmx is NULL!");
|
---|
598 | return -1;
|
---|
599 | }
|
---|
600 |
|
---|
601 | if(dmx->pid <= 0)
|
---|
602 | { return -1; }
|
---|
603 |
|
---|
604 | int32_t result;
|
---|
605 |
|
---|
606 | SAFE_MUTEX_LOCK(&dmx->mutex);
|
---|
607 |
|
---|
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)
|
---|
611 | {
|
---|
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;
|
---|
615 | }
|
---|
616 |
|
---|
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);
|
---|
619 |
|
---|
620 |
|
---|
621 | S_COOL_FILTER *filter_item = find_filter_by_chanhandle(handle_item, num);
|
---|
622 | if(filter_item)
|
---|
623 | {
|
---|
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--;
|
---|
635 | }
|
---|
636 | else
|
---|
637 | {
|
---|
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;
|
---|
641 | }
|
---|
642 |
|
---|
643 | if (!handle_item->allocated_filters)
|
---|
644 | {
|
---|
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);
|
---|
648 |
|
---|
649 | result = cnxt_dmx_set_channel_pid(channel, 0x1FFF);
|
---|
650 | coolapi_check_error("cnxt_dmx_set_channel_pid", result);
|
---|
651 |
|
---|
652 | result = cnxt_cbuf_flush(handle_item->buffer1, 0);
|
---|
653 | coolapi_check_error("cnxt_cbuf_flush", result);
|
---|
654 |
|
---|
655 | result = cnxt_cbuf_flush(handle_item->buffer2, 0);
|
---|
656 | coolapi_check_error("cnxt_cbuf_flush", result);
|
---|
657 |
|
---|
658 | result = cnxt_cbuf_detach(handle_item->buffer2, 2, channel);
|
---|
659 | coolapi_check_error("cnxt_cbuf_detach", result);
|
---|
660 |
|
---|
661 | result = cnxt_dmx_channel_detach(channel, 0xB, 0, handle_item->buffer1);
|
---|
662 | coolapi_check_error("cnxt_dmx_channel_detach", result);
|
---|
663 |
|
---|
664 | #if 0
|
---|
665 | result = cnxt_dmx_channel_close(channel);
|
---|
666 | coolapi_check_error("cnxt_dmx_channel_close", result);
|
---|
667 | #endif
|
---|
668 |
|
---|
669 | result = cnxt_cbuf_close(handle_item->buffer2);
|
---|
670 | coolapi_check_error("cnxt_cbuf_close", result);
|
---|
671 |
|
---|
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;
|
---|
684 | }
|
---|
685 |
|
---|
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);
|
---|
690 | }
|
---|
691 | if (channel) {
|
---|
692 | result = cnxt_dmx_channel_close(channel);
|
---|
693 | coolapi_check_error("cnxt_dmx_channel_close", result);
|
---|
694 | }
|
---|
695 |
|
---|
696 | return 0;
|
---|
697 | }
|
---|
698 |
|
---|
699 | int32_t coolapi_open_device(int32_t demux_index, int32_t demux_id)
|
---|
700 | {
|
---|
701 | dmx_t *dmx;
|
---|
702 |
|
---|
703 | SAFE_MUTEX_LOCK(&demux_lock);
|
---|
704 |
|
---|
705 | dmx = find_demux(0, demux_index);
|
---|
706 | if(!dmx)
|
---|
707 | {
|
---|
708 | SAFE_MUTEX_UNLOCK(&demux_lock);
|
---|
709 | cs_log("no free demux found");
|
---|
710 | return 0;
|
---|
711 | }
|
---|
712 |
|
---|
713 | if(!ll_cool_filter)
|
---|
714 | { ll_cool_filter = ll_create("ll_cool_filter"); }
|
---|
715 |
|
---|
716 | if(!ll_cool_chanhandle)
|
---|
717 | { ll_cool_chanhandle = ll_create("ll_cool_chanhandle"); }
|
---|
718 |
|
---|
719 | dmx->demux_id = demux_id;
|
---|
720 | dmx->pid = -1;
|
---|
721 |
|
---|
722 | //dmx->device = dmx_handles[demux_index].handle;
|
---|
723 | dmx->opened = 1;
|
---|
724 |
|
---|
725 | pthread_mutexattr_t attr;
|
---|
726 | SAFE_MUTEXATTR_INIT(&attr);
|
---|
727 | SAFE_MUTEXATTR_SETTYPE(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
|
---|
728 | SAFE_MUTEX_INIT(&dmx->mutex, &attr);
|
---|
729 |
|
---|
730 | SAFE_MUTEX_UNLOCK(&demux_lock);
|
---|
731 |
|
---|
732 | return dmx->fd;
|
---|
733 | }
|
---|
734 |
|
---|
735 | int32_t coolapi_close_device(int32_t fd)
|
---|
736 | {
|
---|
737 | dmx_t *dmx = find_demux(fd, 0);
|
---|
738 | if(!dmx)
|
---|
739 | {
|
---|
740 | cs_log_dbg(D_DVBAPI, "dmx is NULL!");
|
---|
741 | SAFE_MUTEX_UNLOCK(&demux_lock);
|
---|
742 | return -1;
|
---|
743 | }
|
---|
744 |
|
---|
745 | cs_log_dbg(D_DVBAPI, "closing fd=%08x", fd);
|
---|
746 | dmx->opened = 0;
|
---|
747 | pthread_mutex_destroy(&dmx->mutex);
|
---|
748 |
|
---|
749 | memset(dmx, 0, sizeof(dmx_t));
|
---|
750 | return 0;
|
---|
751 | }
|
---|
752 |
|
---|
753 | /* write cw to all demuxes in mask with passed index */
|
---|
754 | int32_t coolapi_write_cw(int32_t mask, uint16_t *STREAMpids, int32_t count, ca_descr_t *ca_descr)
|
---|
755 | {
|
---|
756 | int32_t i;
|
---|
757 | uint32_t idx = ca_descr->index;
|
---|
758 | int32_t result;
|
---|
759 | void *channel;
|
---|
760 |
|
---|
761 | cs_log_dbg(D_DVBAPI, "cw%d: mask %d index %d pid count %d", ca_descr->parity, mask, idx, count);
|
---|
762 | for(i = 0; i < count; i++)
|
---|
763 | {
|
---|
764 | int32_t pid = STREAMpids[i];
|
---|
765 | int32_t j;
|
---|
766 | for(j = 0; j < MAX_COOL_DMX; j++)
|
---|
767 | {
|
---|
768 | if(mask & (1 << j))
|
---|
769 | {
|
---|
770 | result = cnxt_dmx_get_channel_from_pid(dmx_handles[j].handle, pid, &channel);
|
---|
771 | if(result == 0)
|
---|
772 | {
|
---|
773 | cs_log_dbg(D_DVBAPI, "Found demux %d channel %x for pid %04x", j, (int32_t) channel, pid);
|
---|
774 | result = cnxt_dmx_set_channel_key(channel, 0, ca_descr->parity, ca_descr->cw, 8);
|
---|
775 | coolapi_check_error("cnxt_dmx_set_channel_key", result);
|
---|
776 | if(result != 0)
|
---|
777 | {
|
---|
778 | cs_log("set_channel_key failed for demux %d pid %04x", j, pid);
|
---|
779 | }
|
---|
780 | }
|
---|
781 | }
|
---|
782 | }
|
---|
783 | }
|
---|
784 | return 0;
|
---|
785 | }
|
---|
786 |
|
---|
787 | static int32_t coolapi_read(dmx_t *dmx, dmx_callback_data_t *data, uchar *buffer)
|
---|
788 | {
|
---|
789 | if(!dmx)
|
---|
790 | {
|
---|
791 | cs_log_dbg(D_DVBAPI, "dmx is NULL!");
|
---|
792 | return -1;
|
---|
793 | }
|
---|
794 |
|
---|
795 | int32_t result;
|
---|
796 | uint32_t done = 0, toread, len = data->len;
|
---|
797 | uint32_t bytes_used = 0;
|
---|
798 |
|
---|
799 | //cs_log_dbg(D_DVBAPI, "dmx channel %x pid %x len %d", (int) dmx->channel, dmx->pid, len);
|
---|
800 |
|
---|
801 | result = cnxt_cbuf_get_used(data->buf, &bytes_used);
|
---|
802 | coolapi_check_error("cnxt_cbuf_get_used", result);
|
---|
803 | if(bytes_used == 0)
|
---|
804 | { return -1; }
|
---|
805 |
|
---|
806 | result = cnxt_cbuf_read_data(data->buf, buffer, 3, &done);
|
---|
807 | coolapi_check_error("cnxt_cbuf_read_data", result);
|
---|
808 |
|
---|
809 | if(done != 3)
|
---|
810 | { return -1; }
|
---|
811 |
|
---|
812 | toread = ((buffer[1] << 8) | buffer[2]) & 0xFFF;
|
---|
813 | if((toread + 3) > len)
|
---|
814 | { return -1; }
|
---|
815 | result = cnxt_cbuf_read_data(data->buf, buffer + 3, toread, &done);
|
---|
816 | coolapi_check_error("cnxt_cbuf_read_data", result);
|
---|
817 | if(done != toread)
|
---|
818 | { return -1; }
|
---|
819 | done += 3;
|
---|
820 |
|
---|
821 | //cs_log_dbg(D_DVBAPI, "bytes read %d\n", done);
|
---|
822 |
|
---|
823 | return 0;
|
---|
824 | }
|
---|
825 |
|
---|
826 | static void coolapi_dmx_open(void)
|
---|
827 | {
|
---|
828 | int32_t result = 0;
|
---|
829 | device_open_arg_t devarg;
|
---|
830 |
|
---|
831 | if(!dmx_opened)
|
---|
832 | {
|
---|
833 | int32_t i;
|
---|
834 |
|
---|
835 | cs_log_dbg(D_DVBAPI, "Open Coolstream DMX API");
|
---|
836 |
|
---|
837 | memset(&devarg, 0, sizeof(device_open_arg_t));
|
---|
838 |
|
---|
839 | devarg.unknown1 = 1;
|
---|
840 | devarg.unknown3 = 3;
|
---|
841 | devarg.unknown6 = 1;
|
---|
842 | for(i = 0; i < MAX_COOL_DMX; i++)
|
---|
843 | {
|
---|
844 | devarg.number = i;
|
---|
845 | result = cnxt_dmx_open(&dmx_handles[i].handle, &devarg, NULL, NULL);
|
---|
846 | coolapi_check_error("cnxt_dmx_open", result);
|
---|
847 | }
|
---|
848 | dmx_opened = 1;
|
---|
849 | }
|
---|
850 | }
|
---|
851 |
|
---|
852 | static void coolapi_dmx_close(void)
|
---|
853 | {
|
---|
854 | if(dmx_opened)
|
---|
855 | {
|
---|
856 | int32_t result;
|
---|
857 | int32_t i;
|
---|
858 |
|
---|
859 | for(i = 0; i < MAX_COOL_DMX; i++)
|
---|
860 | {
|
---|
861 | result = cnxt_dmx_close(dmx_handles[i].handle);
|
---|
862 | coolapi_check_error("cnxt_dmx_close", result);
|
---|
863 | dmx_handles[i].handle = NULL;
|
---|
864 | }
|
---|
865 | dmx_opened = 0;
|
---|
866 | }
|
---|
867 | }
|
---|
868 |
|
---|
869 | static void coolapi_start_api(void);
|
---|
870 | static void coolapi_stop_api(void);
|
---|
871 |
|
---|
872 | void coolapi_open_all(void)
|
---|
873 | {
|
---|
874 | SAFE_MUTEX_LOCK(&demux_lock);
|
---|
875 |
|
---|
876 | coolapi_start_api();
|
---|
877 | cool_kal_opened = 1;
|
---|
878 | coolapi_dmx_open();
|
---|
879 |
|
---|
880 | SAFE_MUTEX_UNLOCK(&demux_lock);
|
---|
881 | }
|
---|
882 |
|
---|
883 | void coolapi_close_all(void)
|
---|
884 | {
|
---|
885 | SAFE_MUTEX_LOCK(&demux_lock);
|
---|
886 |
|
---|
887 | if(!dmx_opened) {
|
---|
888 | SAFE_MUTEX_UNLOCK(&demux_lock);
|
---|
889 | return;
|
---|
890 | }
|
---|
891 |
|
---|
892 | int32_t i, j;
|
---|
893 |
|
---|
894 | for(i = 0; i < MAX_COOL_DMX; i++)
|
---|
895 | {
|
---|
896 | for(j = 0; j < MAX_FILTER; j++)
|
---|
897 | {
|
---|
898 | if(cdemuxes[i][j].fd > 0)
|
---|
899 | {
|
---|
900 | coolapi_remove_filter(cdemuxes[i][j].fd, cdemuxes[i][j].filter_num);
|
---|
901 | coolapi_close_device(cdemuxes[i][j].fd);
|
---|
902 | }
|
---|
903 | }
|
---|
904 | }
|
---|
905 |
|
---|
906 | coolapi_dmx_close();
|
---|
907 | coolapi_stop_api();
|
---|
908 | cool_kal_opened = 0;
|
---|
909 |
|
---|
910 | SAFE_MUTEX_UNLOCK(&demux_lock);
|
---|
911 | }
|
---|
912 | #endif
|
---|
913 |
|
---|
914 | #if defined(HAVE_DVBAPI) && (defined(WITH_SU980) || defined(WITH_COOLAPI2))
|
---|
915 | #include "extapi/coolapi.h"
|
---|
916 | extern void cnxt_css_drv_init(void);
|
---|
917 | extern void cnxt_css_drv_term(void);
|
---|
918 | extern void cnxt_smc_term(void);
|
---|
919 |
|
---|
920 | static void coolapi_start_api(void)
|
---|
921 | {
|
---|
922 | cnxt_kal_initialize();
|
---|
923 | cnxt_css_drv_init();
|
---|
924 | cnxt_cbuf_init(NULL);
|
---|
925 | cnxt_dmx_init(NULL);
|
---|
926 | cnxt_smc_init(NULL);
|
---|
927 | }
|
---|
928 |
|
---|
929 | static void coolapi_stop_api(void)
|
---|
930 | {
|
---|
931 | cnxt_css_drv_term();
|
---|
932 | cnxt_kal_terminate();
|
---|
933 | }
|
---|
934 | #elif defined(HAVE_DVBAPI) && defined(WITH_COOLAPI)
|
---|
935 | static void coolapi_start_api(void)
|
---|
936 | {
|
---|
937 | cnxt_kal_initialize();
|
---|
938 | cnxt_drv_init();
|
---|
939 | cnxt_smc_init(NULL);
|
---|
940 | }
|
---|
941 |
|
---|
942 | static void coolapi_stop_api(void)
|
---|
943 | {
|
---|
944 | cnxt_kal_terminate();
|
---|
945 | cnxt_drv_term();
|
---|
946 | }
|
---|
947 | #endif
|
---|