source: trunk/module-dvbapi-coolapi.c@ 8119

Last change on this file since 8119 was 8119, checked in by depp0n, 9 years ago
  • take reader->auprovid into account when starting emm filter
  • cryptoworks & viaccess: emm support for multiple cards for same channel and same caid but different provid
  • viaccess: return written instead of error after writing an emm to a card (even if the answer is not 90 00) .. otherwise some cards like 0500:040810 get valid updates, but oscam always returns error.
  • coolapi: removed emm workaround because it is no longer needed since the new filter handling in r8084
  • Property svn:eol-style set to LF
File size: 12.9 KB
Line 
1/* Reversed from libcoolstream.so, this comes without any warranty */
2
3#include "globals.h"
4
5#if defined(HAVE_DVBAPI) && defined(WITH_COOLAPI)
6
7#include "extapi/coolapi.h"
8
9#include "module-dvbapi.h"
10#include "module-dvbapi-coolapi.h"
11#include "oscam-string.h"
12
13static int8_t dmx_opened = 0;
14int8_t cool_kal_opened = 0;
15
16static void * dmx_device[MAX_COOL_DMX];
17static dmx_t cdemuxes[MAX_COOL_DMX][MAX_FILTER];
18
19extern void * dvbapi_client;
20
21LLIST *ll_cool_filter = NULL;
22LLIST *ll_cool_chanhandle = NULL;
23
24#define COOLDEMUX_FD(device, num) (('O' << 24) | ('S' << 16) | (device << 8) | num)
25#define COOLDEMUX_DMX_DEV(fd) (((fd) >> 8) & 0xFF)
26
27static dmx_t *find_demux(int32_t fd, int32_t dmx_dev_num)
28{
29 if(dmx_dev_num < 0 || dmx_dev_num >= MAX_COOL_DMX) {
30 cs_log("Invalid demux %d", dmx_dev_num);
31 return NULL;
32 }
33
34 int32_t i, idx;
35
36 idx = dmx_dev_num;
37 if(fd == 0) {
38 for(i = 0; i < MAX_FILTER; i++) {
39 if (!cdemuxes[idx][i].opened) {
40 cdemuxes[idx][i].fd = COOLDEMUX_FD(dmx_dev_num, i);
41 cs_debug_mask(D_DVBAPI, "opening new fd: %08x", cdemuxes[idx][i].fd);
42 cdemuxes[idx][i].demux_index = dmx_dev_num;
43 return &cdemuxes[idx][i];
44 }
45 }
46 cs_debug_mask(D_DVBAPI, "ERROR: no free demux found");
47 return NULL;
48 }
49
50 idx = COOLDEMUX_DMX_DEV(fd);
51 for(i = 0; i < MAX_FILTER; i++) {
52 if(cdemuxes[idx][i].fd == fd)
53 return &cdemuxes[idx][i];
54 }
55
56 cs_debug_mask(D_DVBAPI, "ERROR: CANT FIND Demux %08x", fd);
57
58 return NULL;
59}
60
61void coolapi_read_data(dmx_t * dmx, dmx_callback_data_t * data)
62{
63 if(!dmx) {
64 cs_debug_mask(D_DVBAPI, "handle is NULL!");
65 return;
66 }
67
68 int32_t ret;
69
70 pthread_setspecific(getclient, dvbapi_client);
71 pthread_mutex_lock(&dmx->mutex);
72 memset(dmx->buffer,0,4096);
73 ret = coolapi_read(dmx, data);
74 pthread_mutex_unlock(&dmx->mutex);
75 if (ret > -1)
76 dvbapi_process_input(dmx->demux_id, dmx->filter_num, dmx->buffer, data->len);
77}
78
79static void dmx_callback(void * UNUSED(unk), dmx_t * dmx, int32_t type, dmx_callback_data_t * data)
80{
81 if(!dmx) {
82 cs_debug_mask(D_DVBAPI, "wrong dmx pointer !!!");
83 return;
84 }
85
86 if(data != NULL) {
87 switch(type) {
88 case 0xE:
89 if(data->type == 1 && data->len > 0) {
90 coolapi_read_data(dmx, data);
91 } else
92 cs_debug_mask(D_DVBAPI, "unknown callback data %d len %d", data->type, data->len);
93 break;
94 default:
95 break;
96
97 }
98 }
99}
100
101int32_t coolapi_set_filter (int32_t fd, int32_t num, int32_t pid, uchar * flt, uchar * mask, int32_t type)
102{
103 dmx_t * dmx = find_demux(fd, 0);
104 if(!dmx) {
105 cs_debug_mask(D_DVBAPI, "dmx is NULL!");
106 return -1;
107 }
108
109 int32_t result, channel_found=0;
110
111 void * channel = NULL;
112
113 if (ll_count(ll_cool_chanhandle) > 0) {
114 LL_ITER itr = ll_iter_create(ll_cool_chanhandle);
115 S_COOL_CHANHANDLE *handle_item;
116 while ((handle_item=ll_iter_next(&itr))) {
117 if (handle_item->demux_index == dmx->demux_index && handle_item->pid == pid) {
118 channel = handle_item->channel;
119 channel_found=1;
120 break;
121 }
122 }
123 }
124
125 if (!channel) {
126 buffer_open_arg_t bufarg;
127 int32_t uBufferSize = 8256;
128 memset(&bufarg, 0, sizeof(bufarg));
129
130 bufarg.type = 3;
131 bufarg.size = uBufferSize;
132 bufarg.unknown3 = (uBufferSize * 7) / 8;
133
134 result = cnxt_cbuf_open(&dmx->buffer1, &bufarg, NULL, NULL);
135 coolapi_check_error("cnxt_cbuf_open", result);
136
137 bufarg.type = 0;
138
139 result = cnxt_cbuf_open(&dmx->buffer2, &bufarg, NULL, NULL);
140 coolapi_check_error("cnxt_cbuf_open", result);
141
142 channel_open_arg_t chanarg;
143 memset(&chanarg, 0, sizeof(channel_open_arg_t));
144 chanarg.type = 4;
145
146 result = cnxt_dmx_channel_open(dmx->device, &dmx->channel, &chanarg, dmx_callback, dmx);
147 coolapi_check_error("cnxt_dmx_channel_open", result);
148
149 result = cnxt_dmx_set_channel_buffer(dmx->channel, 0, dmx->buffer1);
150 coolapi_check_error("cnxt_dmx_set_channel_buffer", result);
151
152 result = cnxt_dmx_channel_attach(dmx->channel, 0xB, 0, dmx->buffer2);
153 coolapi_check_error("cnxt_dmx_channel_attach", result);
154
155 result = cnxt_cbuf_attach(dmx->buffer2, 2, dmx->channel);
156 coolapi_check_error("cnxt_cbuf_attach", result);
157
158 result = cnxt_dmx_set_channel_pid(dmx->channel, pid);
159 coolapi_check_error("cnxt_dmx_set_channel_pid", result);
160
161 result = cnxt_cbuf_flush (dmx->buffer1, 0);
162 coolapi_check_error("cnxt_cbuf_flush", result);
163 result = cnxt_cbuf_flush (dmx->buffer2, 0);
164 coolapi_check_error("cnxt_cbuf_flush", result);
165
166 S_COOL_CHANHANDLE *handle_item;
167 if (cs_malloc(&handle_item,sizeof(S_COOL_CHANHANDLE))) {
168 handle_item->pid = pid;
169 handle_item->channel = dmx->channel;
170 handle_item->buffer1 = dmx->buffer1;
171 handle_item->buffer2 = dmx->buffer2;
172 handle_item->demux_index = dmx->demux_index;
173 ll_append(ll_cool_chanhandle, handle_item);
174 }
175 cs_debug_mask(D_DVBAPI, "opened new channel %x", (int32_t) dmx->channel);
176 } else {
177 channel_found=1;
178 dmx->channel = channel;
179 dmx->buffer1 = NULL;
180 dmx->buffer2 = NULL;
181 }
182
183 cs_debug_mask(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]);
184
185 pthread_mutex_lock(&dmx->mutex);
186
187 filter_set_t filter;
188 dmx->filter_num = num;
189 dmx->pid = pid;
190 dmx->type = type;
191
192 memset(&filter, 0, sizeof(filter));
193 filter.length = 12;
194 memcpy(filter.filter, flt, 16);
195 memcpy(filter.mask, mask, 16);
196
197 result = cnxt_dmx_open_filter(dmx->device, &dmx->filter);
198 coolapi_check_error("cnxt_dmx_open_filter", result);
199
200 result = cnxt_dmx_set_filter(dmx->filter, &filter, NULL);
201 coolapi_check_error("cnxt_dmx_set_filter", result);
202
203 result = cnxt_dmx_channel_attach_filter(dmx->channel, dmx->filter);
204 coolapi_check_error("cnxt_dmx_channel_attach_filter", result);
205
206 if (channel_found) {
207 result = cnxt_dmx_channel_ctrl(dmx->channel, 0, 0);
208 coolapi_check_error("cnxt_dmx_channel_ctrl", result);
209 }
210
211 result = cnxt_dmx_channel_ctrl(dmx->channel, 2, 0);
212 coolapi_check_error("cnxt_dmx_channel_ctrl", result);
213
214 pthread_mutex_unlock(&dmx->mutex);
215
216 S_COOL_FILTER *filter_item;
217 if (cs_malloc(&filter_item,sizeof(S_COOL_FILTER))) {
218 // fill filter item
219 filter_item->fd = fd;
220 filter_item->pid = pid;
221 filter_item->channel = (int32_t) dmx->channel;
222 memcpy(filter_item->filter16, flt, 16);
223 memcpy(filter_item->mask16, mask, 16);
224
225 //add filter item
226 ll_append(ll_cool_filter, filter_item);
227 }
228 return 0;
229}
230
231int32_t coolapi_remove_filter (int32_t fd, int32_t num)
232{
233 dmx_t * dmx = find_demux(fd, 0);
234 if(!dmx) {
235 cs_debug_mask(D_DVBAPI, "dmx is NULL!");
236 return -1;
237 }
238
239 if(dmx->pid <= 0)
240 return -1;
241
242 int32_t result, filter_on_channel=0;
243
244 cs_debug_mask(D_DVBAPI, "removing filter fd=%08x num=%d pid=%04x on channel=%x", fd, num, dmx->pid, (int32_t) dmx->channel);
245
246 pthread_mutex_lock(&dmx->mutex);
247
248 if(dmx->filter) {
249 result = cnxt_dmx_channel_detach_filter(dmx->channel, dmx->filter);
250 coolapi_check_error("cnxt_dmx_channel_detach_filter", result);
251 result = cnxt_dmx_close_filter(dmx->filter);
252 coolapi_check_error("cnxt_dmx_close_filter", result);
253 dmx->filter = NULL;
254 result = cnxt_dmx_channel_ctrl(dmx->channel, 0, 0);
255 coolapi_check_error("cnxt_dmx_channel_ctrl", result);
256 }
257
258 LL_ITER itr = ll_iter_create(ll_cool_filter);
259 S_COOL_FILTER *filter_item;
260 while ((filter_item=ll_iter_next(&itr))) {
261 if (filter_item->channel == (int32_t) dmx->channel)
262 filter_on_channel++;
263 if (filter_item->fd == fd) {
264 ll_iter_remove_data(&itr);
265 filter_on_channel--;
266 }
267 }
268
269 if (!filter_on_channel) {
270 cs_debug_mask(D_DVBAPI, "closing channel %x", (int32_t) dmx->channel);
271
272 itr = ll_iter_create(ll_cool_chanhandle);
273 S_COOL_CHANHANDLE *handle_item;
274 while ((handle_item=ll_iter_next(&itr))) {
275 if (handle_item->demux_index == dmx->demux_index && handle_item->pid == dmx->pid) {
276 dmx->buffer1=handle_item->buffer1;
277 dmx->buffer2=handle_item->buffer2;
278 ll_iter_remove_data(&itr);
279 break;
280 }
281 }
282
283 if (!dmx->buffer1 || !dmx->buffer2)
284 cs_debug_mask(D_DVBAPI, "WARNING: buffer handle not found!");
285
286 result = cnxt_dmx_channel_ctrl(dmx->channel, 0, 0);
287 coolapi_check_error("cnxt_dmx_channel_ctrl", result);
288
289 result = cnxt_dmx_set_channel_pid(dmx->channel, 0x1FFF);
290 coolapi_check_error("cnxt_dmx_set_channel_pid", result);
291
292 result = cnxt_cbuf_flush (dmx->buffer1, 0);
293 coolapi_check_error("cnxt_cbuf_flush", result);
294
295 result = cnxt_cbuf_flush (dmx->buffer2, 0);
296 coolapi_check_error("cnxt_cbuf_flush", result);
297
298 result = cnxt_cbuf_detach(dmx->buffer2, 2, dmx->channel);
299 coolapi_check_error("cnxt_cbuf_detach", result);
300 result = cnxt_dmx_channel_detach(dmx->channel, 0xB, 0, dmx->buffer1);
301 coolapi_check_error("cnxt_dmx_channel_detach", result);
302
303 result = cnxt_dmx_channel_close(dmx->channel);
304 coolapi_check_error("cnxt_dmx_channel_close", result);
305
306 result = cnxt_cbuf_close(dmx->buffer2);
307 coolapi_check_error("cnxt_cbuf_close", result);
308
309 result = cnxt_cbuf_close(dmx->buffer1);
310 coolapi_check_error("cnxt_cbuf_close", result);
311 }
312
313 if (filter_on_channel) {
314 result = cnxt_dmx_channel_ctrl(dmx->channel, 2, 0);
315 coolapi_check_error("cnxt_dmx_channel_ctrl", result);
316 }
317
318 pthread_mutex_unlock(&dmx->mutex);
319
320 dmx->pid = -1;
321 return 0;
322}
323
324int32_t coolapi_open_device (int32_t demux_index, int32_t demux_id)
325{
326 dmx_t * dmx;
327
328 coolapi_open();
329
330 dmx = find_demux(0, demux_index);
331 if(!dmx) {
332 cs_log("no free demux found");
333 return 0;
334 }
335
336 if (!ll_cool_filter)
337 ll_cool_filter = ll_create("ll_cool_filter");
338
339 if (!ll_cool_chanhandle)
340 ll_cool_chanhandle = ll_create("ll_cool_chanhandle");
341
342 dmx->demux_index = demux_index;
343 dmx->demux_id = demux_id;
344 dmx->pid = -1;
345
346 dmx->device = dmx_device[demux_index];
347 dmx->opened = 1;
348
349 pthread_mutexattr_t attr;
350 pthread_mutexattr_init(&attr);
351 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
352 pthread_mutex_init(&dmx->mutex, &attr);
353
354 return dmx->fd;
355}
356
357int32_t coolapi_close_device(int32_t fd)
358{
359 dmx_t * dmx = find_demux(fd, 0);
360 if(!dmx) {
361 cs_debug_mask(D_DVBAPI, "dmx is NULL!");
362 return -1;
363 }
364
365 cs_debug_mask(D_DVBAPI, "closing fd=%08x", fd);
366 dmx->opened = 0;
367 pthread_mutex_destroy(&dmx->mutex);
368
369 memset(dmx, 0, sizeof(dmx_t));
370 return 0;
371}
372
373/* write cw to all demuxes in mask with passed index */
374int32_t coolapi_write_cw(int32_t mask, uint16_t *STREAMpids, int32_t count, ca_descr_t * ca_descr)
375{
376 int32_t i, idx = ca_descr->index;
377 int32_t result;
378 void * channel;
379
380 cs_debug_mask(D_DVBAPI, "cw%d: mask %d index %d pid count %d", ca_descr->parity, mask, idx, count);
381 for(i = 0; i < count; i++) {
382 int32_t pid = STREAMpids[i];
383 int32_t j;
384 for(j = 0; j < MAX_COOL_DMX; j++) {
385 if(mask & (1 << j))
386 {
387 result = cnxt_dmx_get_channel_from_pid(dmx_device[j], pid, &channel);
388 if(result == 0) {
389 cs_debug_mask(D_DVBAPI, "Found demux %d channel %x for pid %04x", j, (int32_t) channel, pid);
390 result = cnxt_dmx_set_channel_key(channel, 0, ca_descr->parity, ca_descr->cw, 8);
391 coolapi_check_error("cnxt_dmx_set_channel_key", result);
392 if(result != 0) {
393 cs_log("set_channel_key failed for demux %d pid %04x", j, pid);
394 }
395 }
396 }
397 }
398 }
399 return 0;
400}
401
402int32_t coolapi_read(dmx_t * dmx, dmx_callback_data_t * data)
403{
404 if(!dmx) {
405 cs_debug_mask(D_DVBAPI, "dmx is NULL!");
406 return -1;
407 }
408
409 int32_t result;
410 uint32_t done = 0, toread, len=data->len;
411 uchar * buff = &dmx->buffer[0];
412 uint32_t bytes_used = 0;
413
414 //cs_debug_mask(D_DVBAPI, "dmx channel %x pid %x len %d", (int) dmx->channel, dmx->pid, len);
415
416 result = cnxt_cbuf_get_used(data->buf, &bytes_used);
417 coolapi_check_error("cnxt_cbuf_get_used", result);
418 if(bytes_used == 0)
419 return -1;
420
421 result = cnxt_cbuf_read_data(data->buf, buff, 3, &done);
422 coolapi_check_error("cnxt_cbuf_read_data", result);
423
424 if(done != 3)
425 return -1;
426
427 toread = ((buff[1] << 8) | buff[2]) & 0xFFF;
428 if((toread+3) > len)
429 return -1;
430 result = cnxt_cbuf_read_data(data->buf, buff+3, toread, &done);
431 coolapi_check_error("cnxt_cbuf_read_data", result);
432 if(done != toread)
433 return -1;
434 done += 3;
435
436 //cs_debug_mask(D_DVBAPI, "bytes read %d\n", done);
437
438 return 0;
439}
440
441void coolapi_open_all(void)
442{
443 cnxt_kal_initialize();
444 cnxt_drv_init();
445 cnxt_smc_init (NULL);
446 cool_kal_opened = 1;
447}
448
449void coolapi_open(void)
450{
451 int32_t result = 0;
452 device_open_arg_t devarg;
453
454 if(!dmx_opened) {
455 int32_t i;
456
457 cs_debug_mask(D_DVBAPI, "Open Coolstream DMX API");
458 cnxt_cbuf_init(NULL);
459 cnxt_dmx_init(NULL);
460
461 memset(&devarg, 0, sizeof(device_open_arg_t));
462
463 devarg.unknown1 = 1;
464 devarg.unknown3 = 3;
465 devarg.unknown6 = 1;
466 for(i = 0; i < MAX_COOL_DMX; i++) {
467 devarg.number = i;
468 result = cnxt_dmx_open (&dmx_device[i], &devarg, NULL, NULL);
469 coolapi_check_error("cnxt_dmx_open", result);
470 }
471 dmx_opened = 1;
472 }
473}
474
475void coolapi_close_all(void)
476{
477 if(dmx_opened) {
478 int32_t result;
479 int32_t i, j;
480
481 for(i = 0; i < MAX_COOL_DMX; i++) {
482 for(j = 0; j < MAX_FILTER; j++) {
483 if(cdemuxes[i][j].fd > 0) {
484 coolapi_remove_filter(cdemuxes[i][j].fd, cdemuxes[i][j].filter_num);
485 coolapi_close_device(cdemuxes[i][j].fd);
486 }
487 }
488 }
489 for(i = 0; i < MAX_COOL_DMX; i++) {
490 result = cnxt_dmx_close(dmx_device[i]);
491 coolapi_check_error("cnxt_dmx_close", result);
492 dmx_device[i] = NULL;
493 }
494 }
495 cool_kal_opened = 0;
496 cnxt_kal_terminate();
497 cnxt_drv_term();
498}
499#endif
Note: See TracBrowser for help on using the repository browser.