Annotation of margi2/dvb_demux.c, revision 1.10
1.1 mocm 1: /*
2: * dvb_demux.c - DVB kernel demux API
3: *
1.3 mocm 4: * Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
5: * & Marcus Metzler <marcus@convergence.de>
6: * for convergence integrated media GmbH
1.1 mocm 7: *
8: * This program is free software; you can redistribute it and/or
9: * modify it under the terms of the GNU Lesser General Public License
10: * as published by the Free Software Foundation; either version 2.1
11: * of the License, or (at your option) any later version.
12: *
13: * This program is distributed in the hope that it will be useful,
14: * but WITHOUT ANY WARRANTY; without even the implied warranty of
15: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: * GNU General Public License for more details.
17: *
18: * You should have received a copy of the GNU Lesser General Public License
19: * along with this program; if not, write to the Free Software
20: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21: *
22: */
23:
24: #include <linux/vmalloc.h>
25: #include <linux/module.h>
26: #include <linux/poll.h>
27: #include <asm/uaccess.h>
28:
29: #include "dvb_demux.h"
30:
1.8 mocm 31: #ifdef MODULE
32: MODULE_DESCRIPTION("");
33: MODULE_AUTHOR("Ralph Metzler, Marcus Metzler");
34: #ifdef MODULE_LICENSE
35: MODULE_LICENSE("GPL");
36: #endif
37: #endif
38:
1.7 mocm 39: #define NOBUFS
40:
1.1 mocm 41: LIST_HEAD(dmx_muxs);
42:
43: int dmx_register_demux(dmx_demux_t *demux)
44: {
45: struct list_head *pos, *head=&dmx_muxs;
46:
47: if (!(demux->id && demux->vendor && demux->model))
48: return -EINVAL;
49: list_for_each(pos, head)
50: {
51: if (!strcmp(DMX_DIR_ENTRY(pos)->id, demux->id))
52: return -EEXIST;
53: }
54: demux->users=0;
55: list_add(&(demux->reg_list), head);
56: MOD_INC_USE_COUNT;
57: return 0;
58: }
59:
60: int dmx_unregister_demux(dmx_demux_t* demux)
61: {
62: struct list_head *pos, *head=&dmx_muxs;
63:
64: list_for_each(pos, head)
65: {
66: if (DMX_DIR_ENTRY(pos)==demux)
67: {
1.8 mocm 68: if (demux->users>0)
1.1 mocm 69: return -EINVAL;
70: list_del(pos);
71: MOD_DEC_USE_COUNT;
72: return 0;
73: }
74: }
75: return -ENODEV;
76: }
77:
78:
79: struct list_head *dmx_get_demuxes(void)
80: {
81: if (list_empty(&dmx_muxs))
82: return NULL;
83:
84: return &dmx_muxs;
85: }
86:
87: /******************************************************************************
88: * static inlined helper functions
89: ******************************************************************************/
90:
91: static inline u16
92: section_length(const u8 *buf)
93: {
1.2 mocm 94: return 3+((buf[1]&0x0f)<<8)+buf[2];
1.1 mocm 95: }
96:
97: static inline u16
98: ts_pid(const u8 *buf)
99: {
1.2 mocm 100: return ((buf[1]&0x1f)<<8)+buf[2];
1.1 mocm 101: }
102:
103: static inline int
1.2 mocm 104: payload(const u8 *tsp)
1.1 mocm 105: {
106: if (!(tsp[3]&0x10)) // no payload?
107: return 0;
1.9 mocm 108: if (tsp[3]&0x20) { // adaptation field?
109: if (tsp[4]>183) // corrupted data?
110: return 0;
111: else
112: return 184-1-tsp[4];
113: }
1.2 mocm 114: return 184;
1.1 mocm 115: }
116:
1.7 mocm 117:
118: static u32
119: dvb_crc_table[256] = {
120: 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
121: 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
122: 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
123: 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
124: 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
125: 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
126: 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
127: 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
128: 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
129: 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
130: 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
131: 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
132: 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
133: 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
134: 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
135: 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
136: 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
137: 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
138: 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
139: 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
140: 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
141: 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
142: 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
143: 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
144: 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
145: 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
146: 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
147: 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
148: 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
149: 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
150: 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
151: 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
152: 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
153: 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
154: 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
155: 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
156: 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
157: 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
158: 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
159: 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
160: 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
161: 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
162: 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
163:
164: u32 dvb_crc32(u8 *data, int len)
165: {
166: int i;
167: u32 crc = 0xffffffff;
168:
169: for (i=0; i<len; i++)
170: crc = (crc << 8) ^ dvb_crc_table[((crc >> 24) ^ *data++) & 0xff];
171: return crc;
172: }
173:
174: void dvb_set_crc32(u8 *data, int length)
175: {
176: u32 crc;
177:
178: crc=dvb_crc32(data,length);
179: data[length] = (crc>>24)&0xff;
180: data[length+1] = (crc>>16)&0xff;
181: data[length+2] = (crc>>8)&0xff;
182: data[length+3] = (crc)&0xff;
183: }
184:
185:
1.1 mocm 186: /******************************************************************************
187: * Software filter functions
188: ******************************************************************************/
189:
190: static inline int
191: DvbDmxSWFilterPayload(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf)
192: {
1.9 mocm 193: int p, count;
194: //int ccok;
195: //u8 cc;
1.1 mocm 196:
1.2 mocm 197: if (!(count=payload(buf)))
1.1 mocm 198: return -1;
1.2 mocm 199: p=188-count;
200: /*
1.9 mocm 201: cc=buf[3]&0x0f;
202: ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0;
203: dvbdmxfeed->cc=cc;
1.1 mocm 204: if (!ccok)
205: printk("missed packet!\n");
206: */
1.2 mocm 207: if (buf[1]&0x40) // PUSI ?
1.1 mocm 208: dvbdmxfeed->peslen=0xfffa;
209: dvbdmxfeed->peslen+=count;
210:
211: return dvbdmxfeed->cb.ts((u8 *)&buf[p], count, 0, 0,
212: &dvbdmxfeed->feed.ts, DMX_OK);
213: }
214:
215:
216: static int
217: DvbDmxSWFilterSectionFilter(dvb_demux_feed_t *dvbdmxfeed,
218: dvb_demux_filter_t *dvbdmxfilter)
219: {
220: dmx_section_filter_t *filter=&dvbdmxfilter->filter;
1.10 ! mocm 221: #if 1
1.1 mocm 222: int i;
223:
224: for (i=0; i<DVB_DEMUX_MASK_MAX; i++)
225: if (filter->filter_mask[i]&
226: (filter->filter_value[i]^dvbdmxfeed->secbuf[i]))
227: return 0;
228: #else
229: u32 res;
230: u32 *val=(u32 *)(filter->filter_value);
231: u32 *mask=(u32 *)(filter->filter_mask);
232: u32 *data=(u32 *)(dvbdmxfeed->secbuf);
233:
234: res=mask[0]&(val[0]^data[0]);
235: if (res) return 0;
236:
237: res=mask[1]&(val[1]^data[1]);
238: if (res) return 0;
239:
240: res=mask[2]&(val[2]^data[2]);
241: if (res) return 0;
242:
243: res=mask[3]&(val[3]^data[3]);
244: if (res) return 0;
245:
246: res=*(u16 *)(4+mask) & (*(u16 *)(4+val) ^ *(u16 *)(4+data));
247: if (res) return 0;
248: #endif
1.10 ! mocm 249:
1.1 mocm 250: return dvbdmxfeed->cb.sec(dvbdmxfeed->secbuf, dvbdmxfeed->seclen,
251: 0, 0, filter, DMX_OK);
252: }
253:
254: static inline int
255: DvbDmxSWFilterSectionFeed(dvb_demux_feed_t *dvbdmxfeed)
256: {
257: u8 *buf=dvbdmxfeed->secbuf;
258: dvb_demux_filter_t *f;
259:
260: if (dvbdmxfeed->secbufp!=dvbdmxfeed->seclen)
261: return -1;
262: if (!dvbdmxfeed->feed.sec.is_filtering)
263: return 0;
264: if (!(f=dvbdmxfeed->filter))
265: return 0;
266: do
267: if (DvbDmxSWFilterSectionFilter(dvbdmxfeed, f)<0)
268: return -1;
269: while ((f=f->next) && dvbdmxfeed->feed.sec.is_filtering);
270:
271: dvbdmxfeed->secbufp=dvbdmxfeed->seclen=0;
272: memset(buf, 0, DVB_DEMUX_MASK_MAX);
273: return 0;
274: }
275:
276: static inline int
277: DvbDmxSWFilterSectionPacket(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf)
278: {
1.2 mocm 279: int p, count;
280: int ccok, rest;
1.9 mocm 281: u8 cc;
1.1 mocm 282:
1.2 mocm 283: if (!(count=payload(buf)))
1.1 mocm 284: return -1;
1.2 mocm 285: p=188-count;
1.1 mocm 286:
1.9 mocm 287: cc=buf[3]&0x0f;
288: ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0;
289: dvbdmxfeed->cc=cc;
1.1 mocm 290:
1.4 mocm 291: if (buf[1]&0x40) { // PUSI set
1.2 mocm 292: // offset to start of first section is in buf[p]
1.9 mocm 293: if (p+buf[p]>187) // trash if it points beyond packet
294: return -1;
1.2 mocm 295: if (buf[p] && ccok) { // rest of previous section?
296: // did we have enough data in last packet to calc length?
297: if (dvbdmxfeed->secbufp && dvbdmxfeed->secbufp<3) {
298: memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp,
299: buf+p+1,
300: 3-dvbdmxfeed->secbufp);
301: dvbdmxfeed->seclen=section_length(dvbdmxfeed->secbuf);
1.9 mocm 302: if (dvbdmxfeed->seclen>4096)
303: return -1;
1.2 mocm 304: }
1.1 mocm 305: rest=dvbdmxfeed->seclen-dvbdmxfeed->secbufp;
306: if (rest==buf[p] && dvbdmxfeed->seclen) {
307: memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp,
308: buf+p+1, buf[p]);
309: dvbdmxfeed->secbufp+=buf[p];
310: DvbDmxSWFilterSectionFeed(dvbdmxfeed);
311: }
312: }
1.2 mocm 313: p+=buf[p]+1; // skip rest of last section
314: count=188-p;
1.1 mocm 315: while (count>0) {
1.2 mocm 316: if ((count>2) && // enough data to determine sec length?
1.1 mocm 317: ((dvbdmxfeed->seclen=section_length(buf+p))<=count)) {
1.9 mocm 318: if (dvbdmxfeed->seclen>4096)
319: return -1;
1.1 mocm 320: memcpy(dvbdmxfeed->secbuf, buf+p,
321: dvbdmxfeed->seclen);
322: dvbdmxfeed->secbufp=dvbdmxfeed->seclen;
323: p+=dvbdmxfeed->seclen;
1.2 mocm 324: count=188-p;
1.1 mocm 325: DvbDmxSWFilterSectionFeed(dvbdmxfeed);
1.2 mocm 326:
327: // filling bytes until packet end?
1.9 mocm 328: if (count && buf[p]==0xff)
1.2 mocm 329: count=0;
1.9 mocm 330: } else { // section continues to following TS packet
1.1 mocm 331: memcpy(dvbdmxfeed->secbuf, buf+p, count);
1.2 mocm 332: dvbdmxfeed->secbufp+=count;
1.1 mocm 333: count=0;
334: }
335: }
1.2 mocm 336: } else { // section continued below
1.1 mocm 337: if (!ccok)
338: return -1;
1.2 mocm 339: if (!dvbdmxfeed->secbufp) // any data in last ts packet?
340: return -1;
341: // did we have enough data in last packet to calc section length?
1.1 mocm 342: if (dvbdmxfeed->secbufp<3) {
1.2 mocm 343: memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p,
344: 3-dvbdmxfeed->secbufp);
1.1 mocm 345: dvbdmxfeed->seclen=section_length(dvbdmxfeed->secbuf);
1.9 mocm 346: if (dvbdmxfeed->seclen>4096)
347: return -1;
1.1 mocm 348: }
349: rest=dvbdmxfeed->seclen-dvbdmxfeed->secbufp;
1.2 mocm 350: if (rest<0)
1.1 mocm 351: return -1;
1.9 mocm 352: if (rest<=count) { // section completed in this TS packet
1.2 mocm 353: memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, rest);
354: dvbdmxfeed->secbufp+=rest;
355: DvbDmxSWFilterSectionFeed(dvbdmxfeed);
356: } else { // section continues in following ts block
357: memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, count);
358: dvbdmxfeed->secbufp+=count;
359: }
360:
1.1 mocm 361: }
362: return 0;
363: }
364:
1.5 mocm 365: static inline void
1.1 mocm 366: DvbDmxSWFilterPacketType(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf)
367: {
368: switch(dvbdmxfeed->type) {
369: case DMX_TYPE_TS:
370: if (!dvbdmxfeed->feed.ts.is_filtering)
371: break;
372: if (dvbdmxfeed->ts_type & TS_PACKET) {
373: if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
374: DvbDmxSWFilterPayload(dvbdmxfeed, buf);
375: else
376: dvbdmxfeed->cb.ts((u8 *)buf, 188, 0, 0,
377: &dvbdmxfeed->feed.ts, DMX_OK);
378: }
379: if (dvbdmxfeed->ts_type & TS_DECODER)
380: if (dvbdmxfeed->demux->write_to_decoder)
381: dvbdmxfeed->demux->
382: write_to_decoder(dvbdmxfeed, (u8 *)buf, 188);
383: break;
384:
385: case DMX_TYPE_SEC:
386: if (!dvbdmxfeed->feed.sec.is_filtering)
387: break;
388: if (DvbDmxSWFilterSectionPacket(dvbdmxfeed, buf)<0)
389: dvbdmxfeed->seclen=dvbdmxfeed->secbufp=0;
390: break;
391:
392: default:
393: break;
394: }
395: }
396:
397: void inline
398: DvbDmxSWFilterPacket(dvb_demux_t *dvbdmx, const u8 *buf)
399: {
400: dvb_demux_feed_t *dvbdmxfeed;
401:
402: if (!(dvbdmxfeed=dvbdmx->pid2feed[ts_pid(buf)]))
403: return;
404: DvbDmxSWFilterPacketType(dvbdmxfeed, buf);
405: }
406:
407: void
408: DvbDmxSWFilterPackets(dvb_demux_t *dvbdmx, const u8 *buf, int count)
409: {
410: dvb_demux_feed_t *dvbdmxfeed;
411:
1.8 mocm 412: if ((dvbdmxfeed=dvbdmx->pid2feed[0x2000]))
413: dvbdmxfeed->cb.ts((u8 *)buf, count*188, 0, 0,
414: &dvbdmxfeed->feed.ts, DMX_OK);
1.9 mocm 415: while (count) {
416: DvbDmxSWFilterPacket(dvbdmx, buf);
417: count--;
418: buf+=188;
1.5 mocm 419: }
1.1 mocm 420: }
421:
422: static inline void
423: DvbDmxSWFilter(dvb_demux_t *dvbdmx, const u8 *buf, size_t count)
424: {
425: int p=0,i, j;
426:
427: if ((i=dvbdmx->tsbufp)) {
428: if (count<(j=188-i)) {
429: memcpy(&dvbdmx->tsbuf[i], buf, count);
430: dvbdmx->tsbufp+=count;
431: return;
432: }
433: memcpy(&dvbdmx->tsbuf[i], buf, j);
434: DvbDmxSWFilterPacket(dvbdmx, dvbdmx->tsbuf);
435: dvbdmx->tsbufp=0;
436: p+=j;
437: }
438:
439: while (p<count) {
440: if (buf[p]==0x47) {
441: if (count-p>=188) {
442: DvbDmxSWFilterPacket(dvbdmx, buf+p);
443: p+=188;
444: } else {
445: i=count-p;
446: memcpy(dvbdmx->tsbuf, buf+p, i);
447: dvbdmx->tsbufp=i;
1.10 ! mocm 448: return;
1.1 mocm 449: }
450: } else
451: p++;
1.10 ! mocm 452: }
1.1 mocm 453: }
454:
455:
456: /******************************************************************************
457: ******************************************************************************
458: * DVB DEMUX API LEVEL FUNCTIONS
459: ******************************************************************************
460: ******************************************************************************/
461:
462: static dvb_demux_filter_t *
463: DvbDmxFilterAlloc(dvb_demux_t *dvbdmx)
464: {
465: int i;
466:
1.4 mocm 467: for (i=0; i<dvbdmx->filternum; i++)
1.1 mocm 468: if (dvbdmx->filter[i].state==DMX_STATE_FREE)
469: break;
1.8 mocm 470: if (i==dvbdmx->filternum)
1.1 mocm 471: return 0;
472: dvbdmx->filter[i].state=DMX_STATE_ALLOCATED;
473: return &dvbdmx->filter[i];
474: }
475:
476: static dvb_demux_feed_t *
477: DvbDmxFeedAlloc(dvb_demux_t *dvbdmx)
478: {
479: int i;
480:
1.4 mocm 481: for (i=0; i<dvbdmx->feednum; i++)
1.1 mocm 482: if (dvbdmx->feed[i].state==DMX_STATE_FREE)
483: break;
1.4 mocm 484: if (i==dvbdmx->feednum)
1.1 mocm 485: return 0;
486: dvbdmx->feed[i].state=DMX_STATE_ALLOCATED;
487: return &dvbdmx->feed[i];
488: }
489:
490:
491: /******************************************************************************
492: * dmx_ts_feed API calls
493: ******************************************************************************/
494:
495: static int
496: dmx_ts_feed_set_type(dmx_ts_feed_t *feed, int type, dmx_ts_pes_t pes_type)
497: {
498: dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
499: dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
500:
1.10 ! mocm 501: down(&dvbdmx->mutex);
1.1 mocm 502: dvbdmxfeed->ts_type=type;
503: dvbdmxfeed->pes_type=pes_type;
504:
505: if (dvbdmxfeed->ts_type & TS_DECODER) {
1.8 mocm 506: if (pes_type >= DMX_TS_PES_OTHER) {
507: up(&dvbdmx->mutex);
1.1 mocm 508: return -EINVAL;
1.8 mocm 509: }
1.1 mocm 510: if (dvbdmx->pesfilter[pes_type] &&
1.8 mocm 511: (dvbdmx->pesfilter[pes_type]!=dvbdmxfeed)) {
512: up(&dvbdmx->mutex);
1.1 mocm 513: return -EINVAL;
1.8 mocm 514: }
1.1 mocm 515: dvbdmx->pesfilter[pes_type]=dvbdmxfeed;
516: dvbdmx->pids[pes_type]=dvbdmxfeed->pid;
517: }
1.8 mocm 518: up(&dvbdmx->mutex);
1.1 mocm 519: return 0;
520: }
521:
522: static int
1.8 mocm 523: dmx_pid_set(u16 pid, dvb_demux_feed_t *dvbdmxfeed)
1.6 mocm 524: {
525: dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
526: dvb_demux_feed_t **pid2feed=dvbdmx->pid2feed;
527:
1.8 mocm 528: if (pid>DMX_MAX_PID)
1.6 mocm 529: return -EINVAL;
530: if (dvbdmxfeed->pid!=0xffff) {
1.8 mocm 531: if (dvbdmxfeed->pid<=DMX_MAX_PID)
1.6 mocm 532: pid2feed[dvbdmxfeed->pid]=0;
533: dvbdmxfeed->pid=0xffff;
534: }
1.8 mocm 535: if (pid2feed[pid]) {
1.6 mocm 536: return -EBUSY;
1.8 mocm 537: }
1.6 mocm 538: pid2feed[pid]=dvbdmxfeed;
539: dvbdmxfeed->pid=pid;
540: return 0;
541: }
542:
543:
544: static int
1.1 mocm 545: dmx_ts_feed_set(struct dmx_ts_feed_s* feed,
1.8 mocm 546: u16 pid,
1.1 mocm 547: size_t callback_length,
548: size_t circular_buffer_size,
549: int descramble,
550: struct timespec timeout
551: )
552: {
553: dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
554: dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
1.6 mocm 555: int ret;
556:
1.10 ! mocm 557: down(&dvbdmx->mutex);
1.6 mocm 558: ret=dmx_pid_set(pid, dvbdmxfeed);
1.8 mocm 559: if (ret<0) {
560: up(&dvbdmx->mutex);
561: return ret;
562: }
1.1 mocm 563: dvbdmxfeed->buffer_size=circular_buffer_size;
564: dvbdmxfeed->descramble=descramble;
565: dvbdmxfeed->timeout=timeout;
566: dvbdmxfeed->cb_length=callback_length;
567: dvbdmxfeed->ts_type=TS_PACKET;
568:
1.8 mocm 569: if (dvbdmxfeed->descramble) {
570: up(&dvbdmx->mutex);
1.1 mocm 571: return -ENOSYS;
1.8 mocm 572: }
1.1 mocm 573:
574: if (dvbdmxfeed->buffer_size) {
1.7 mocm 575: #ifdef NOBUFS
576: dvbdmxfeed->buffer=0;
577: #else
1.1 mocm 578: dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size);
1.8 mocm 579: if (!dvbdmxfeed->buffer) {
580: up(&dvbdmx->mutex);
1.7 mocm 581: return -ENOMEM;
1.8 mocm 582: }
1.7 mocm 583: #endif
1.1 mocm 584: }
585: dvbdmxfeed->state=DMX_STATE_READY;
1.8 mocm 586: up(&dvbdmx->mutex);
1.1 mocm 587: return 0;
588: }
589:
590: static int
591: dmx_ts_feed_start_filtering(struct dmx_ts_feed_s* feed)
592: {
593: dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
594: dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
595: int ret;
596:
1.10 ! mocm 597: down(&dvbdmx->mutex);
1.8 mocm 598: if (dvbdmxfeed->state!=DMX_STATE_READY ||
599: dvbdmxfeed->type!=DMX_TYPE_TS) {
600: up(&dvbdmx->mutex);
1.1 mocm 601: return -EINVAL;
1.8 mocm 602: }
603: if (!dvbdmx->start_feed) {
604: up(&dvbdmx->mutex);
1.3 mocm 605: return -1;
1.8 mocm 606: }
1.1 mocm 607: ret=dvbdmx->start_feed(dvbdmxfeed);
1.8 mocm 608: if (ret<0) {
609: up(&dvbdmx->mutex);
610: return ret;
611: }
1.1 mocm 612: feed->is_filtering=1;
613: dvbdmxfeed->state=DMX_STATE_GO;
1.8 mocm 614: up(&dvbdmx->mutex);
1.1 mocm 615: return 0;
616: }
617:
618: static int
619: dmx_ts_feed_stop_filtering(struct dmx_ts_feed_s* feed)
620: {
621: dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
622: dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
623: int ret;
624:
1.10 ! mocm 625: down(&dvbdmx->mutex);
1.8 mocm 626: if (dvbdmxfeed->state<DMX_STATE_GO) {
627: up(&dvbdmx->mutex);
1.1 mocm 628: return -EINVAL;
1.8 mocm 629: }
630: if (!dvbdmx->stop_feed) {
631: up(&dvbdmx->mutex);
1.3 mocm 632: return -1;
1.8 mocm 633: }
1.1 mocm 634: ret=dvbdmx->stop_feed(dvbdmxfeed);
635: feed->is_filtering=0;
636: dvbdmxfeed->state=DMX_STATE_ALLOCATED;
637:
1.8 mocm 638: up(&dvbdmx->mutex);
1.1 mocm 639: return ret;
640: }
641:
642: static int dvbdmx_allocate_ts_feed(dmx_demux_t *demux,
643: dmx_ts_feed_t **feed,
644: dmx_ts_cb callback)
645: {
646: dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
647: dvb_demux_feed_t *dvbdmxfeed;
648:
1.10 ! mocm 649: down(&dvbdmx->mutex);
1.8 mocm 650: if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx))) {
651: up(&dvbdmx->mutex);
1.1 mocm 652: return -EBUSY;
1.8 mocm 653: }
1.1 mocm 654: dvbdmxfeed->type=DMX_TYPE_TS;
655: dvbdmxfeed->cb.ts=callback;
656: dvbdmxfeed->demux=dvbdmx;
657: dvbdmxfeed->pid=0xffff;
658: dvbdmxfeed->peslen=0xfffa;
1.8 mocm 659: dvbdmxfeed->buffer=0;
1.1 mocm 660:
661: (*feed)=&dvbdmxfeed->feed.ts;
662: (*feed)->is_filtering=0;
663: (*feed)->parent=demux;
664: (*feed)->priv=0;
665: (*feed)->set=dmx_ts_feed_set;
666: (*feed)->set_type=dmx_ts_feed_set_type;
667: (*feed)->start_filtering=dmx_ts_feed_start_filtering;
668: (*feed)->stop_filtering=dmx_ts_feed_stop_filtering;
669:
670:
671: if (!(dvbdmxfeed->filter=DvbDmxFilterAlloc(dvbdmx))) {
672: dvbdmxfeed->state=DMX_STATE_FREE;
1.8 mocm 673: up(&dvbdmx->mutex);
1.1 mocm 674: return -EBUSY;
675: }
676:
677: dvbdmxfeed->filter->type=DMX_TYPE_TS;
678: dvbdmxfeed->filter->feed=dvbdmxfeed;
679: dvbdmxfeed->filter->state=DMX_STATE_READY;
680:
1.8 mocm 681: up(&dvbdmx->mutex);
1.1 mocm 682: return 0;
683: }
684:
685: static int dvbdmx_release_ts_feed(dmx_demux_t *demux, dmx_ts_feed_t *feed)
686: {
1.8 mocm 687: dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
1.1 mocm 688: dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
689:
1.10 ! mocm 690: down(&dvbdmx->mutex);
1.8 mocm 691: if (dvbdmxfeed->state==DMX_STATE_FREE) {
692: up(&dvbdmx->mutex);
1.1 mocm 693: return -EINVAL;
1.8 mocm 694: }
695: #ifndef NOBUFS
1.3 mocm 696: if (dvbdmxfeed->buffer) {
1.1 mocm 697: vfree(dvbdmxfeed->buffer);
1.3 mocm 698: dvbdmxfeed->buffer=0;
699: }
1.8 mocm 700: #endif
1.1 mocm 701: dvbdmxfeed->state=DMX_STATE_FREE;
702: dvbdmxfeed->filter->state=DMX_STATE_FREE;
703: if (dvbdmxfeed->pid!=0xffff) {
1.8 mocm 704: if (dvbdmxfeed->pid<=DMX_MAX_PID)
1.1 mocm 705: dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0;
706: dvbdmxfeed->pid=0xffff;
707: }
708:
1.8 mocm 709: up(&dvbdmx->mutex);
1.1 mocm 710: return 0;
711: }
712:
713:
714: /******************************************************************************
715: * dmx_pes_feed API calls
716: ******************************************************************************/
717: /*
718: static int
719: dmx_pes_feed_set(struct dmx_pes_feed_s* feed,
1.8 mocm 720: u16 pid,
1.1 mocm 721: size_t circular_buffer_size,
722: int descramble,
723: struct timespec timeout)
724: {
725: return 0;
726: }
727:
728: static int
729: dmx_pes_feed_start_filtering(struct dmx_pes_feed_s* feed)
730: {
731: return 0;
732: }
733:
734: static int
735: dmx_pes_feed_stop_filtering(struct dmx_pes_feed_s* feed)
736: {
737: return 0;
738: }
739: */
740:
741: static int dvbdmx_allocate_pes_feed(dmx_demux_t *demux,
742: dmx_pes_feed_t **feed,
743: dmx_pes_cb callback)
744: {
745: return 0;
746: }
747:
748: static int dvbdmx_release_pes_feed(dmx_demux_t *demux,
749: dmx_pes_feed_t *feed)
750: {
751: return 0;
752: }
753:
754:
755: /******************************************************************************
756: * dmx_section_feed API calls
757: ******************************************************************************/
758:
759: static int
760: dmx_section_feed_allocate_filter(struct dmx_section_feed_s* feed,
761: dmx_section_filter_t** filter)
762: {
763: dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
764: dvb_demux_t *dvbdemux=dvbdmxfeed->demux;
765: dvb_demux_filter_t *dvbdmxfilter;
766:
1.10 ! mocm 767: down(&dvbdemux->mutex);
1.1 mocm 768: dvbdmxfilter=DvbDmxFilterAlloc(dvbdemux);
1.8 mocm 769: if (!dvbdmxfilter) {
770: up(&dvbdemux->mutex);
1.1 mocm 771: return -ENOSPC;
1.8 mocm 772: }
1.1 mocm 773: *filter=&dvbdmxfilter->filter;
774: (*filter)->parent=feed;
775: (*filter)->priv=0;
776: dvbdmxfilter->feed=dvbdmxfeed;
777: dvbdmxfilter->pid=dvbdmxfeed->pid;
778: dvbdmxfilter->type=DMX_TYPE_SEC;
779: dvbdmxfilter->state=DMX_STATE_READY;
780:
781: dvbdmxfilter->next=dvbdmxfeed->filter;
782: dvbdmxfeed->filter=dvbdmxfilter;
1.8 mocm 783: up(&dvbdemux->mutex);
1.1 mocm 784: return 0;
785: }
786:
787: static int
788: dmx_section_feed_set(struct dmx_section_feed_s* feed,
1.8 mocm 789: u16 pid, size_t circular_buffer_size,
1.1 mocm 790: int descramble, int check_crc)
791: {
792: dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
793: dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
794:
795: if (pid>0x1fff)
796: return -EINVAL;
1.10 ! mocm 797: down(&dvbdmx->mutex);
1.1 mocm 798: if (dvbdmxfeed->pid!=0xffff) {
799: dvbdmx->pid2feed[dvbdmxfeed->pid]=0;
800: dvbdmxfeed->pid=0xffff;
801: }
1.8 mocm 802: if (dvbdmx->pid2feed[pid]) {
803: up(&dvbdmx->mutex);
804: return -EBUSY;
805: }
1.1 mocm 806: dvbdmx->pid2feed[pid]=dvbdmxfeed;
1.6 mocm 807: dvbdmxfeed->pid=pid;
1.1 mocm 808:
809: dvbdmxfeed->buffer_size=circular_buffer_size;
810: dvbdmxfeed->descramble=descramble;
1.8 mocm 811: if (dvbdmxfeed->descramble) {
812: up(&dvbdmx->mutex);
1.1 mocm 813: return -ENOSYS;
1.8 mocm 814: }
1.1 mocm 815:
816: dvbdmxfeed->check_crc=check_crc;
1.7 mocm 817: #ifdef NOBUFS
818: dvbdmxfeed->buffer=0;
819: #else
1.1 mocm 820: dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size);
1.8 mocm 821: if (!dvbdmxfeed->buffer) {
822: up(&dvbdmx->mutex);
1.7 mocm 823: return -ENOMEM;
1.8 mocm 824: }
1.7 mocm 825: #endif
1.3 mocm 826: dvbdmxfeed->state=DMX_STATE_READY;
1.8 mocm 827: up(&dvbdmx->mutex);
1.1 mocm 828: return 0;
829: }
830:
831: static int
832: dmx_section_feed_start_filtering(dmx_section_feed_t *feed)
833: {
834: dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
835: dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
836: int ret;
837:
1.10 ! mocm 838: down(&dvbdmx->mutex);
1.8 mocm 839: if (feed->is_filtering) {
840: up(&dvbdmx->mutex);
841: return -EBUSY;
842: }
843: if (!dvbdmxfeed->filter) {
844: up(&dvbdmx->mutex);
1.1 mocm 845: return -EINVAL;
1.8 mocm 846: }
1.1 mocm 847: dvbdmxfeed->secbufp=0;
848: dvbdmxfeed->seclen=0;
849:
1.8 mocm 850: if (!dvbdmx->start_feed) {
851: up(&dvbdmx->mutex);
1.3 mocm 852: return -1;
1.8 mocm 853: }
1.1 mocm 854: ret=dvbdmx->start_feed(dvbdmxfeed);
1.8 mocm 855: if (ret<0) {
856: up(&dvbdmx->mutex);
857: return ret;
858: }
1.1 mocm 859: feed->is_filtering=1;
860: dvbdmxfeed->state=DMX_STATE_GO;
1.8 mocm 861: up(&dvbdmx->mutex);
1.1 mocm 862: return 0;
863: }
864:
865: static int
866: dmx_section_feed_stop_filtering(struct dmx_section_feed_s* feed)
867: {
868: dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
869: dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
1.3 mocm 870: int ret;
871:
1.10 ! mocm 872: down(&dvbdmx->mutex);
1.8 mocm 873: if (!dvbdmx->stop_feed) {
874: up(&dvbdmx->mutex);
1.3 mocm 875: return -1;
1.8 mocm 876: }
1.3 mocm 877: ret=dvbdmx->stop_feed(dvbdmxfeed);
1.1 mocm 878:
879: dvbdmxfeed->state=DMX_STATE_READY;
880: feed->is_filtering=0;
1.8 mocm 881: up(&dvbdmx->mutex);
1.1 mocm 882: return ret;
883: }
884:
885: static int
886: dmx_section_feed_release_filter(dmx_section_feed_t *feed,
887: dmx_section_filter_t* filter)
888: {
889: dvb_demux_filter_t *dvbdmxfilter=(dvb_demux_filter_t *) filter, *f;
890: dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
1.8 mocm 891: dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
1.1 mocm 892:
1.10 ! mocm 893: down(&dvbdmx->mutex);
1.8 mocm 894: if (dvbdmxfilter->feed!=dvbdmxfeed) {
895: up(&dvbdmx->mutex);
1.1 mocm 896: return -EINVAL;
1.8 mocm 897: }
1.1 mocm 898: if (feed->is_filtering)
1.2 mocm 899: feed->stop_filtering(feed);
1.8 mocm 900:
1.1 mocm 901: f=dvbdmxfeed->filter;
1.3 mocm 902: if (f==dvbdmxfilter)
1.1 mocm 903: dvbdmxfeed->filter=dvbdmxfilter->next;
904: else {
905: while(f->next!=dvbdmxfilter)
906: f=f->next;
907: f->next=f->next->next;
908: }
909: dvbdmxfilter->state=DMX_STATE_FREE;
1.8 mocm 910: up(&dvbdmx->mutex);
1.1 mocm 911: return 0;
912: }
913:
914: static int dvbdmx_allocate_section_feed(dmx_demux_t *demux,
915: dmx_section_feed_t **feed,
916: dmx_section_cb callback)
917: {
918: dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
919: dvb_demux_feed_t *dvbdmxfeed;
920:
1.10 ! mocm 921: down(&dvbdmx->mutex);
1.8 mocm 922: if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx))) {
923: up(&dvbdmx->mutex);
1.1 mocm 924: return -EBUSY;
1.8 mocm 925: }
1.1 mocm 926: dvbdmxfeed->type=DMX_TYPE_SEC;
927: dvbdmxfeed->cb.sec=callback;
928: dvbdmxfeed->demux=dvbdmx;
929: dvbdmxfeed->pid=0xffff;
930: dvbdmxfeed->secbufp=0;
931: dvbdmxfeed->filter=0;
1.8 mocm 932: dvbdmxfeed->buffer=0;
1.1 mocm 933:
934: (*feed)=&dvbdmxfeed->feed.sec;
935: (*feed)->is_filtering=0;
936: (*feed)->parent=demux;
937: (*feed)->priv=0;
938: (*feed)->set=dmx_section_feed_set;
939: (*feed)->allocate_filter=dmx_section_feed_allocate_filter;
940: (*feed)->release_filter=dmx_section_feed_release_filter;
941: (*feed)->start_filtering=dmx_section_feed_start_filtering;
942: (*feed)->stop_filtering=dmx_section_feed_stop_filtering;
1.8 mocm 943:
944: up(&dvbdmx->mutex);
1.1 mocm 945: return 0;
946: }
947:
948: static int dvbdmx_release_section_feed(dmx_demux_t *demux,
949: dmx_section_feed_t *feed)
950: {
951: dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
1.8 mocm 952: dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
1.1 mocm 953:
1.10 ! mocm 954: down(&dvbdmx->mutex);
1.8 mocm 955: if (dvbdmxfeed->state==DMX_STATE_FREE) {
956: up(&dvbdmx->mutex);
1.1 mocm 957: return -EINVAL;
1.8 mocm 958: }
959: #ifndef NOBUFS
1.3 mocm 960: if (dvbdmxfeed->buffer) {
1.1 mocm 961: vfree(dvbdmxfeed->buffer);
1.3 mocm 962: dvbdmxfeed->buffer=0;
963: }
1.8 mocm 964: #endif
1.1 mocm 965: dvbdmxfeed->state=DMX_STATE_FREE;
966: dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0;
967: if (dvbdmxfeed->pid!=0xffff)
968: dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0;
1.8 mocm 969: up(&dvbdmx->mutex);
1.1 mocm 970: return 0;
971: }
972:
973:
974: /******************************************************************************
975: * dvb_demux kernel data API calls
976: ******************************************************************************/
977:
1.3 mocm 978: static int dvbdmx_open(dmx_demux_t *demux)
1.1 mocm 979: {
980: dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
981:
982: if (dvbdemux->users>=MAX_DVB_DEMUX_USERS)
983: return -EUSERS;
984: dvbdemux->users++;
985: return 0;
986: }
987:
988: static int dvbdmx_close(struct dmx_demux_s *demux)
989: {
990: dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
991:
992: if (dvbdemux->users==0)
993: return -ENODEV;
994: dvbdemux->users--;
995: //FIXME: release any unneeded resources if users==0
996: return 0;
997: }
998:
999: static int dvbdmx_write(dmx_demux_t *demux, const char *buf, size_t count)
1000: {
1001: dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
1002:
1003: if ((!demux->frontend) ||
1004: (demux->frontend->source!=DMX_MEMORY_FE))
1005: return -EINVAL;
1006:
1.10 ! mocm 1007: down(&dvbdemux->mutex);
1.1 mocm 1008: DvbDmxSWFilter(dvbdemux, buf, count);
1.10 ! mocm 1009: up(&dvbdemux->mutex);
1.1 mocm 1010: return count;
1011: }
1012:
1013:
1014: static int dvbdmx_add_frontend(dmx_demux_t *demux,
1015: dmx_frontend_t *frontend)
1016: {
1017: dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
1018: struct list_head *pos, *head=&dvbdemux->frontend_list;
1019:
1020: //printk ("function : %s\n", __FUNCTION__);
1021:
1022: if (!(frontend->id && frontend->vendor && frontend->model))
1023: return -EINVAL;
1024: list_for_each(pos, head)
1025: {
1026: if (!strcmp(DMX_FE_ENTRY(pos)->id, frontend->id))
1027: return -EEXIST;
1028: }
1029:
1030: list_add(&(frontend->connectivity_list), head);
1031: return 0;
1032: }
1033:
1034: static int
1035: dvbdmx_remove_frontend(dmx_demux_t *demux,
1036: dmx_frontend_t *frontend)
1037: {
1038: dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
1039: struct list_head *pos, *head=&dvbdemux->frontend_list;
1040:
1041: list_for_each(pos, head)
1042: {
1043: if (DMX_FE_ENTRY(pos)==frontend)
1044: {
1045: list_del(pos);
1046: return 0;
1047: }
1048: }
1049: return -ENODEV;
1050: }
1051:
1052: static struct list_head *
1053: dvbdmx_get_frontends(dmx_demux_t *demux)
1054: {
1055: dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
1056:
1057: if (list_empty(&dvbdemux->frontend_list))
1058: return NULL;
1059: return &dvbdemux->frontend_list;
1060: }
1061:
1062: static int dvbdmx_connect_frontend(dmx_demux_t *demux,
1063: dmx_frontend_t *frontend)
1064: {
1.8 mocm 1065: dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
1066:
1.1 mocm 1067: if (demux->frontend)
1068: return -EINVAL;
1069:
1.10 ! mocm 1070: down(&dvbdemux->mutex);
1.1 mocm 1071: demux->frontend=frontend;
1.8 mocm 1072: up(&dvbdemux->mutex);
1.1 mocm 1073: return 0;
1074: }
1075:
1076: static int dvbdmx_disconnect_frontend(dmx_demux_t *demux)
1077: {
1.8 mocm 1078: dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
1079:
1.10 ! mocm 1080: down(&dvbdemux->mutex);
1.1 mocm 1081: demux->frontend=NULL;
1.8 mocm 1082: up(&dvbdemux->mutex);
1.1 mocm 1083: return 0;
1084: }
1085:
1.8 mocm 1086: static int dvbdmx_get_pes_pids(dmx_demux_t *demux, u16 *pids)
1.1 mocm 1087: {
1088: dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
1089:
1.8 mocm 1090: memcpy(pids, dvbdemux->pids, 5*sizeof(u16));
1.1 mocm 1091: return 0;
1092: }
1093:
1094: int
1.3 mocm 1095: DvbDmxInit(dvb_demux_t *dvbdemux)
1.1 mocm 1096: {
1.3 mocm 1097: int i;
1.1 mocm 1098: dmx_demux_t *dmx=&dvbdemux->dmx;
1099:
1.3 mocm 1100: dvbdemux->users=0;
1.1 mocm 1101: dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(dvb_demux_filter_t));
1102: if (!dvbdemux->filter)
1103: return -ENOMEM;
1.4 mocm 1104:
1105: dvbdemux->feed=vmalloc(dvbdemux->feednum*sizeof(dvb_demux_feed_t));
1106: if (!dvbdemux->feed) {
1107: vfree(dvbdemux->filter);
1108: return -ENOMEM;
1109: }
1110: for (i=0; i<dvbdemux->filternum; i++) {
1.1 mocm 1111: dvbdemux->filter[i].state=DMX_STATE_FREE;
1112: dvbdemux->filter[i].index=i;
1113: }
1.4 mocm 1114: for (i=0; i<dvbdemux->feednum; i++)
1.1 mocm 1115: dvbdemux->feed[i].state=DMX_STATE_FREE;
1.3 mocm 1116: dvbdemux->frontend_list.next=
1117: dvbdemux->frontend_list.prev=
1118: &dvbdemux->frontend_list;
1.1 mocm 1119: for (i=0; i<DMX_TS_PES_OTHER; i++) {
1120: dvbdemux->pesfilter[i]=NULL;
1121: dvbdemux->pids[i]=0xffff;
1122: }
1123: dvbdemux->playing=dvbdemux->recording=0;
1.8 mocm 1124: memset(dvbdemux->pid2feed, 0, (DMX_MAX_PID+1)*sizeof(dvb_demux_feed_t *));
1.1 mocm 1125: dvbdemux->tsbufp=0;
1126:
1127: dmx->frontend=0;
1128: dmx->reg_list.next=dmx->reg_list.prev=&dmx->reg_list;
1129: dmx->priv=(void *) dvbdemux;
1.3 mocm 1130: //dmx->users=0; // reset in dmx_register_demux()
1.1 mocm 1131: dmx->open=dvbdmx_open;
1132: dmx->close=dvbdmx_close;
1133: dmx->write=dvbdmx_write;
1134: dmx->allocate_ts_feed=dvbdmx_allocate_ts_feed;
1135: dmx->release_ts_feed=dvbdmx_release_ts_feed;
1136: dmx->allocate_pes_feed=dvbdmx_allocate_pes_feed;
1137: dmx->release_pes_feed=dvbdmx_release_pes_feed;
1138: dmx->allocate_section_feed=dvbdmx_allocate_section_feed;
1139: dmx->release_section_feed=dvbdmx_release_section_feed;
1140:
1141: dmx->descramble_mac_address=NULL;
1142: dmx->descramble_section_payload=NULL;
1143:
1144: dmx->add_frontend=dvbdmx_add_frontend;
1145: dmx->remove_frontend=dvbdmx_remove_frontend;
1146: dmx->get_frontends=dvbdmx_get_frontends;
1147: dmx->connect_frontend=dvbdmx_connect_frontend;
1148: dmx->disconnect_frontend=dvbdmx_disconnect_frontend;
1149: dmx->get_pes_pids=dvbdmx_get_pes_pids;
1.8 mocm 1150: sema_init(&dvbdemux->mutex, 1);
1.1 mocm 1151:
1152: if (dmx_register_demux(dmx)<0)
1153: return -1;
1.4 mocm 1154:
1.1 mocm 1155: return 0;
1156: }
1157:
1158: int
1159: DvbDmxRelease(dvb_demux_t *dvbdemux)
1160: {
1161: dmx_demux_t *dmx=&dvbdemux->dmx;
1162:
1163: dmx_unregister_demux(dmx);
1164: if (dvbdemux->filter)
1165: vfree(dvbdemux->filter);
1.4 mocm 1166: if (dvbdemux->feed)
1167: vfree(dvbdemux->feed);
1.1 mocm 1168: return 0;
1169: }
LinuxTV legacy CVS <linuxtv.org/cvs>