source: trunk/module-coolapi.c@ 4149

Last change on this file since 4149 was 4143, checked in by dingo35, 13 years ago

module-coolapi.c : fix compiling problem

File size: 11.2 KB
Line 
1/* Reversed from libcoolstream.so, this comes without any warranty */
2
3#ifdef COOL
4#define _GNU_SOURCE
5
6#include <pthread.h>
7#include <stdio.h>
8#include <stdbool.h>
9#include <poll.h>
10#include <string.h>
11#include <unistd.h>
12#include <sys/time.h>
13
14#include "module-coolapi.h"
15#include "globals.h"
16
17#define MAX_PIDS 20
18#define MAX_FILTER 10
19
20#define MAX_DEMUX 3
21
22int cooldebug = 0;
23static bool dmx_opened = false;
24
25#define check_error(label, ret) \
26{ \
27 if(ret != 0) { \
28 cs_log("[%s:%d] %s: API ERROR %d", \
29 __FUNCTION__, __LINE__ , \
30 label, ret); \
31 } \
32}
33
34typedef struct ca_descr {
35 unsigned int index;
36 unsigned int parity; /* 0 == even, 1 == odd */
37 unsigned char cw[8];
38} ca_descr_t;
39
40struct cool_dmx
41{
42 bool opened;
43 bool filter_attached;
44 int fd;
45 void * buffer1;
46 void * buffer2;
47 void * channel;
48 void * filter;
49 void * device;
50 int pid;
51 pthread_mutex_t mutex;
52 int demux_id;
53 int demux_index;
54 int filter_num;
55};
56typedef struct cool_dmx dmx_t;
57
58static void * dmx_device[MAX_DEMUX];
59static dmx_t cdemuxes[MAX_DEMUX][MAX_FILTER];
60
61int coolapi_read(int fd, unsigned char * buffer, unsigned int len);
62void coolapi_open();
63
64extern void dvbapi_process_input(int demux_num, int filter_num, unsigned char *buffer, int len);
65extern pthread_key_t getclient;
66extern void * dvbapi_client;
67
68#define COOLDEMUX_FD(device, num) (('O' << 24) | ('S' << 16) | (device << 8) | num)
69#define COOLDEMUX_DMX_DEV(fd) (((fd) >> 8) & 0xFF)
70#define COOLDEMUX_DMX(fd) ((fd) & 0xFF)
71
72static dmx_t *find_demux(int fd, int dmx_dev_num)
73{
74 int i, idx;
75
76 if(dmx_dev_num < 0 || dmx_dev_num >= MAX_DEMUX) {
77 cs_log("Invalid demux %d", dmx_dev_num);
78 return NULL;
79 }
80 idx = dmx_dev_num;
81
82 if(fd == 0) {
83 for(i = 0; i < MAX_FILTER; i++) {
84 if (cdemuxes[idx][i].opened == false) {
85 cdemuxes[idx][i].fd = COOLDEMUX_FD(dmx_dev_num, i);
86 cs_debug_mask(D_DVBAPI, "opening new fd: %08x", cdemuxes[idx][i].fd);
87 cdemuxes[idx][i].demux_index = dmx_dev_num;
88 return &cdemuxes[idx][i];
89 }
90 }
91 cs_debug_mask(D_DVBAPI, "ERROR: no free demux found");
92 return NULL;
93 }
94
95 idx = COOLDEMUX_DMX_DEV(fd);
96 for(i = 0; i < MAX_FILTER; i++) {
97 if(cdemuxes[idx][i].fd == fd)
98 return &cdemuxes[idx][i];
99 }
100
101 cs_debug_mask(D_DVBAPI, "ERROR: CANT FIND Demux %x", fd);
102
103 return NULL;
104}
105
106void coolapi_read_data(int fd, int len)
107{
108 int ret;
109 unsigned char buffer[4096];
110 dmx_t * dmx = find_demux(fd, 0);
111
112 if(!dmx) {
113 cs_debug_mask(D_DVBAPI, "handle is NULL!");
114 return;
115 }
116
117 pthread_mutex_lock(&dmx->mutex);
118 pthread_setspecific(getclient, dvbapi_client);
119 ret = coolapi_read(dmx->fd, buffer, len);
120 pthread_mutex_unlock(&dmx->mutex);
121 dvbapi_process_input(dmx->demux_id, dmx->filter_num, buffer, len);
122}
123
124static void dmx_callback(void * unk, dmx_t * dmx, int type, void * data)
125{
126 dmx_callback_data_t * cdata = (dmx_callback_data_t *) data;
127 unk = unk;
128
129 if(!dmx) {
130 cs_debug_mask(D_DVBAPI, "wrong dmx pointer !!!");
131 return;
132 }
133 if(cdata != NULL) {
134 switch(type) {
135 case 0xE:
136 if(cdata->type == 1) {
137 coolapi_read_data(dmx->fd, cdata->len);
138 } else
139 cs_debug_mask(D_DVBAPI, "unknown callback data %d len %d", cdata->type, cdata->len);
140 break;
141 default:
142 break;
143
144 }
145 }
146}
147
148int coolapi_set_filter (int fd, int num, int pid, unsigned char * flt, unsigned char * mask)
149{
150 int result;
151 filter_set_t filter;
152
153 dmx_t * dmx = find_demux(fd, 0);
154
155 if(!dmx) {
156 cs_debug_mask(D_DVBAPI, "dmx is NULL!");
157 return -1;
158 }
159
160 dmx->filter_num = num;
161 cs_debug_mask(D_DVBAPI, "fd %08x demux %d channel %x num %d pid %x flt %x mask %x", fd, dmx->demux_index, (int) dmx->channel, num, pid, flt[0], mask[0]);
162
163 memset(&filter, 0, sizeof(filter));
164
165 filter.length = 12;
166 memcpy(filter.filter, flt, 12);
167 memcpy(filter.mask, mask, 12);
168
169 pthread_mutex_lock(&dmx->mutex);
170 if(dmx->filter == NULL) {
171 dmx->filter_attached = false;
172 result = cnxt_dmx_open_filter(dmx->device, &dmx->filter);
173 check_error ("cnxt_dmx_open_filter", result);
174 }
175
176 result = cnxt_dmx_set_filter(dmx->filter, &filter, NULL);
177 check_error ("cnxt_dmx_set_filter", result);
178
179 if(!dmx->filter_attached) {
180 result = cnxt_dmx_channel_attach_filter(dmx->channel, dmx->filter);
181 check_error ("cnxt_dmx_channel_attach_filter", result);
182 }
183
184 if(dmx->pid != pid) {
185 result = cnxt_dmx_set_channel_pid(dmx->channel, pid);
186 check_error ("cnxt_dmx_set_channel_pid", result);
187 }
188
189 result = cnxt_cbuf_flush (dmx->buffer1, 0);
190 check_error ("cnxt_cbuf_flush", result);
191 result = cnxt_cbuf_flush (dmx->buffer2, 0);
192 check_error ("cnxt_cbuf_flush", result);
193
194 result = cnxt_dmx_channel_ctrl(dmx->channel, 2, 0);
195 check_error ("cnxt_dmx_channel_ctrl", result);
196 dmx->pid = pid;
197 pthread_mutex_unlock(&dmx->mutex);
198 return 0;
199}
200
201int coolapi_remove_filter (int fd, int num)
202{
203 int result;
204 dmx_t * dmx = find_demux(fd, 0);
205 if(!dmx) {
206 cs_debug_mask(D_DVBAPI, "dmx is NULL!");
207 return -1;
208 }
209
210 if(dmx->pid <= 0)
211 return -1;
212
213 cs_debug_mask(D_DVBAPI, "fd %08x channel %x num %d pid %x opened %s", fd, (int) dmx->channel, num, dmx->pid, dmx->opened ? "yes" : "no");
214
215 pthread_mutex_lock(&dmx->mutex);
216 result = cnxt_dmx_channel_ctrl(dmx->channel, 0, 0);
217 check_error ("cnxt_dmx_channel_ctrl", result);
218
219 result = cnxt_dmx_set_channel_pid(dmx->channel, 0x1FFF);
220 check_error ("cnxt_dmx_set_channel_pid", result);
221
222 result = cnxt_cbuf_flush (dmx->buffer1, 0);
223 check_error ("cnxt_cbuf_flush", result);
224 result = cnxt_cbuf_flush (dmx->buffer2, 0);
225 check_error ("cnxt_cbuf_flush", result);
226 pthread_mutex_unlock(&dmx->mutex);
227
228 dmx->pid = -1;
229 return 0;
230}
231
232int coolapi_open_device (int demux_index, int demux_id)
233{
234 int result = 0;
235 buffer_open_arg_t bufarg;
236 channel_open_arg_t chanarg;
237 int uBufferSize = 8256;
238 dmx_t * dmx;
239
240 coolapi_open();
241
242 dmx = find_demux(0, demux_index);
243 if(dmx == 0) {
244 cs_log("no free demux found");
245 return 0;
246 }
247
248 dmx->demux_index = demux_index;
249 dmx->demux_id = demux_id;
250 dmx->pid = -1;
251
252 memset(&bufarg, 0, sizeof(bufarg));
253
254 dmx->device = dmx_device[demux_index];
255 dmx->opened = true;
256
257 bufarg.type = 3;
258 bufarg.size = uBufferSize;
259 bufarg.unknown3 = (uBufferSize * 7) / 8;
260
261 result = cnxt_cbuf_open(&dmx->buffer1, &bufarg, NULL, NULL);
262 check_error ("cnxt_cbuf_open", result);
263
264 bufarg.type = 0;
265
266 result = cnxt_cbuf_open(&dmx->buffer2, &bufarg, NULL, NULL);
267 check_error ("cnxt_cbuf_open", result);
268
269 memset(&chanarg, 0, sizeof(channel_open_arg_t));
270 chanarg.type = 4;
271
272 result = cnxt_dmx_channel_open(dmx->device, &dmx->channel, &chanarg, dmx_callback, dmx);
273 check_error ("cnxt_dmx_channel_open", result);
274
275 result = cnxt_dmx_set_channel_buffer(dmx->channel, 0, dmx->buffer1);
276 check_error ("cnxt_dmx_set_channel_buffer", result);
277
278 result = cnxt_dmx_channel_attach(dmx->channel, 0xB, 0, dmx->buffer2);
279 check_error ("cnxt_dmx_channel_attach", result);
280
281 result = cnxt_cbuf_attach(dmx->buffer2, 2, dmx->channel);
282 check_error ("cnxt_cbuf_attach", result);
283
284 pthread_mutexattr_t attr;
285 pthread_mutexattr_init(&attr);
286 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
287 pthread_mutex_init(&dmx->mutex, &attr);
288
289 cs_debug_mask(D_DVBAPI, "fd %08x demux #%d demux_id %d channel %x", dmx->fd, demux_index, demux_id, (int) dmx->channel);
290 return dmx->fd;
291}
292
293int coolapi_close_device(int fd)
294{
295 int result;
296 dmx_t * dmx = find_demux(fd, 0);
297 if(!dmx) {
298 cs_debug_mask(D_DVBAPI, "dmx is NULL!");
299 return -1;
300 }
301 cs_debug_mask(D_DVBAPI, "fd %08x channel %x pid %x", fd, (int) dmx->channel, dmx->pid);
302
303 if(dmx->filter != NULL) {
304 result = cnxt_dmx_channel_detach_filter(dmx->channel, dmx->filter);
305 check_error ("cnxt_dmx_channel_detach_filter", result);
306 result = cnxt_dmx_close_filter(dmx->filter);
307 check_error ("cnxt_dmx_close_filter", result);
308 dmx->filter = NULL;
309 dmx->filter_attached = false;
310 }
311
312 result = cnxt_cbuf_detach(dmx->buffer2, 2, dmx->channel);
313 check_error ("cnxt_cbuf_detach", result);
314 result = cnxt_dmx_channel_detach(dmx->channel, 0xB, 0, dmx->buffer2);
315 check_error ("cnxt_dmx_channel_detach", result);
316
317 result = cnxt_dmx_channel_detach(dmx->channel, 0xB, 0, dmx->buffer1);
318 check_error ("cnxt_dmx_channel_detach", result);
319 result = cnxt_dmx_channel_close(dmx->channel);
320 check_error ("cnxt_dmx_channel_close", result);
321
322 result = cnxt_cbuf_close(dmx->buffer2);
323 check_error ("cnxt_cbuf_close", result);
324
325 result = cnxt_cbuf_close(dmx->buffer1);
326 check_error ("cnxt_cbuf_close", result);
327
328 dmx->opened = false;
329
330 pthread_mutex_destroy(&dmx->mutex);
331
332 memset(dmx, 0, sizeof(dmx_t));
333 return 0;
334}
335
336/* write cw to all demuxes in mask with passed index */
337int coolapi_write_cw(int mask, unsigned short *STREAMpids, int count, ca_descr_t * ca_descr)
338{
339 int i, index = ca_descr->index;
340 int result;
341 void * channel;
342
343 cs_debug_mask(D_DVBAPI, "cw%d: mask %d index %d pid count %d", ca_descr->parity, mask, index, count);
344 for(i = 0; i < count; i++) {
345 int pid = STREAMpids[i];
346 int j;
347 for(j = 0; j < 3; j++) {
348 if(mask & (1 << j))
349 {
350 result = cnxt_dmx_get_channel_from_pid(dmx_device[j], pid, &channel);
351 if(result == 0) {
352 cs_debug_mask(D_DVBAPI, "Found demux %d channel %x for pid %x", j, (int) channel, pid);
353 result = cnxt_dmx_set_channel_key(channel, 0, ca_descr->parity, ca_descr->cw, 8);
354 check_error ("cnxt_dmx_set_channel_key", result);
355 if(result != 0) {
356 cs_log("set_channel_key failed for demux %d pid 0x%x", j, pid);
357 }
358 }
359 }
360 }
361 }
362 return 0;
363}
364
365int coolapi_read(int fd, unsigned char * buffer, unsigned int len)
366{
367 int result;
368 unsigned int done = 0, toread;
369 unsigned char * buff = &buffer[0];
370
371 dmx_t * dmx = find_demux(fd, 0);
372 if(!dmx) {
373 cs_debug_mask(D_DVBAPI, "dmx is NULL!");
374 return 0;
375 }
376 cs_debug_mask(D_DVBAPI, "dmx channel %x pid %x len %d", (int) dmx->channel, dmx->pid, len);
377
378 result = cnxt_cbuf_read_data(dmx->buffer2, buff, 3, &done);
379 check_error ("cnxt_cbuf_read_data", result);
380
381 if(done != 3)
382 return 0;
383
384 toread = ((buff[1] << 8) | buff[2]) & 0xFFF;
385 if((toread+3) > len)
386 return 0;
387 result = cnxt_cbuf_read_data(dmx->buffer2, buff+3, toread, &done);
388 check_error ("cnxt_cbuf_read_data", result);
389 if(done != toread)
390 return 0;
391 done += 3;
392
393 cs_debug_mask(D_DVBAPI, "bytes read %d\n", done);
394 return done;
395}
396
397void coolapi_open()
398{
399 int result = 0;
400 device_open_arg_t devarg;
401
402 if(!dmx_opened) {
403 int i;
404
405 cs_log("Open coolstream dmx api");
406
407 cnxt_kal_initialize();
408 cnxt_drv_init();
409 cnxt_cbuf_init(NULL);
410 cnxt_dmx_init(NULL);
411
412 memset(&devarg, 0, sizeof(device_open_arg_t));
413
414 devarg.unknown1 = 1;
415 devarg.unknown3 = 3;
416 devarg.unknown6 = 1;
417 for(i = 0; i < MAX_DEMUX; i++) {
418 devarg.number = i;
419 result = cnxt_dmx_open (&dmx_device[i], &devarg, NULL, NULL);
420 check_error ("cnxt_dmx_open", result);
421 }
422 dmx_opened = true;
423 }
424}
425
426void coolapi_close_all()
427{
428 int result;
429 int i, j;
430
431 if(!dmx_opened)
432 return;
433
434 for(i = 0; i < MAX_DEMUX; i++) {
435 for(j = 0; j < MAX_FILTER; j++) {
436 if(cdemuxes[i][j].fd > 0) {
437 coolapi_remove_filter(cdemuxes[i][j].fd, cdemuxes[i][j].filter_num);
438 coolapi_close_device(cdemuxes[i][j].fd);
439 }
440 }
441 }
442 for(i = 0; i < MAX_DEMUX; i++) {
443 result = cnxt_dmx_close(dmx_device[i]);
444 check_error ("cnxt_dmx_close", result);
445 dmx_device[i] = NULL;
446 }
447 cnxt_kal_terminate();
448 cnxt_drv_term();
449}
450#endif
Note: See TracBrowser for help on using the repository browser.