Annotation of margi2/dvb_demux.c, revision 1.9

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;
                    221: #if 0
                    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
                    249: 
                    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;
                    448:                                 return;
                    449:                         }
                    450:                 } else 
                    451:                         p++;
                    452:         }          
                    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.8       mocm      501:         down_interruptible(&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.8       mocm      557:         down_interruptible(&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.8       mocm      597:         down_interruptible(&dvbdmx->mutex);
                    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.8       mocm      625:         down_interruptible(&dvbdmx->mutex);
                    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.8       mocm      649:         down_interruptible(&dvbdmx->mutex);
                    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.8       mocm      690:         down_interruptible(&dvbdmx->mutex);
                    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.8       mocm      767:        down_interruptible(&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.8       mocm      797:         down_interruptible(&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.8       mocm      838:         down_interruptible(&dvbdmx->mutex);
                    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.8       mocm      872:         down_interruptible(&dvbdmx->mutex);
                    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.8       mocm      893:         down_interruptible(&dvbdmx->mutex);
                    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: 
                    910:         dvbdmxfilter->state=DMX_STATE_FREE;
1.8       mocm      911:         up(&dvbdmx->mutex);
1.1       mocm      912:         return 0;
                    913: }
                    914: 
                    915: static int dvbdmx_allocate_section_feed(dmx_demux_t *demux, 
                    916:                                         dmx_section_feed_t **feed,
                    917:                                         dmx_section_cb callback)
                    918: {
                    919:         dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
                    920:         dvb_demux_feed_t *dvbdmxfeed;
                    921: 
1.8       mocm      922:         down_interruptible(&dvbdmx->mutex);
                    923:         if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx))) {
                    924:                up(&dvbdmx->mutex);
1.1       mocm      925:                 return -EBUSY;
1.8       mocm      926:        }
1.1       mocm      927:         dvbdmxfeed->type=DMX_TYPE_SEC;
                    928:         dvbdmxfeed->cb.sec=callback;
                    929:         dvbdmxfeed->demux=dvbdmx;
                    930:         dvbdmxfeed->pid=0xffff;
                    931:         dvbdmxfeed->secbufp=0;
                    932:         dvbdmxfeed->filter=0;
1.8       mocm      933:         dvbdmxfeed->buffer=0;
1.1       mocm      934: 
                    935:         (*feed)=&dvbdmxfeed->feed.sec;
                    936:         (*feed)->is_filtering=0;
                    937:         (*feed)->parent=demux;
                    938:         (*feed)->priv=0;
                    939:         (*feed)->set=dmx_section_feed_set;
                    940:         (*feed)->allocate_filter=dmx_section_feed_allocate_filter;
                    941:         (*feed)->release_filter=dmx_section_feed_release_filter;
                    942:         (*feed)->start_filtering=dmx_section_feed_start_filtering;
                    943:         (*feed)->stop_filtering=dmx_section_feed_stop_filtering;
1.8       mocm      944: 
                    945:         up(&dvbdmx->mutex);
1.1       mocm      946:         return 0;
                    947: }
                    948: 
                    949: static int dvbdmx_release_section_feed(dmx_demux_t *demux, 
                    950:                                        dmx_section_feed_t *feed)
                    951: {
                    952:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
1.8       mocm      953:         dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
1.1       mocm      954: 
1.8       mocm      955:         down_interruptible(&dvbdmx->mutex);
                    956:         if (dvbdmxfeed->state==DMX_STATE_FREE) {
                    957:                up(&dvbdmx->mutex);
1.1       mocm      958:                 return -EINVAL;
1.8       mocm      959:        }
                    960: #ifndef NOBUFS
1.3       mocm      961:         if (dvbdmxfeed->buffer) {
1.1       mocm      962:                 vfree(dvbdmxfeed->buffer);
1.3       mocm      963:                 dvbdmxfeed->buffer=0;
                    964:         }
1.8       mocm      965: #endif
1.1       mocm      966:         dvbdmxfeed->state=DMX_STATE_FREE;
                    967:         dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0;
                    968:         if (dvbdmxfeed->pid!=0xffff)
                    969:                 dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0;
1.8       mocm      970:         up(&dvbdmx->mutex);
1.1       mocm      971:         return 0;
                    972: }
                    973: 
                    974: 
                    975: /******************************************************************************
                    976:  * dvb_demux kernel data API calls
                    977:  ******************************************************************************/
                    978: 
1.3       mocm      979: static int dvbdmx_open(dmx_demux_t *demux)
1.1       mocm      980: {
                    981:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    982: 
                    983:         if (dvbdemux->users>=MAX_DVB_DEMUX_USERS)
                    984:                 return -EUSERS;
                    985:         dvbdemux->users++;
                    986:         return 0;
                    987: }
                    988: 
                    989: static int dvbdmx_close(struct dmx_demux_s *demux)
                    990: {
                    991:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    992: 
                    993:         if (dvbdemux->users==0)
                    994:                 return -ENODEV;
                    995:         dvbdemux->users--;
                    996:         //FIXME: release any unneeded resources if users==0
                    997:         return 0;
                    998: }
                    999: 
                   1000: static int dvbdmx_write(dmx_demux_t *demux, const char *buf, size_t count)
                   1001: {
                   1002:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                   1003: 
                   1004:         if ((!demux->frontend) ||
                   1005:             (demux->frontend->source!=DMX_MEMORY_FE))
                   1006:                 return -EINVAL;
                   1007: 
                   1008:         DvbDmxSWFilter(dvbdemux, buf, count);
                   1009:         return count;
                   1010: }
                   1011: 
                   1012: 
                   1013: static int dvbdmx_add_frontend(dmx_demux_t *demux, 
                   1014:                                dmx_frontend_t *frontend)
                   1015: {
                   1016:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                   1017:         struct list_head *pos, *head=&dvbdemux->frontend_list;
                   1018:        
                   1019:         //printk ("function : %s\n", __FUNCTION__);
                   1020: 
                   1021:        if (!(frontend->id && frontend->vendor && frontend->model)) 
                   1022:                return -EINVAL;
                   1023:        list_for_each(pos, head) 
                   1024:        {
                   1025:                if (!strcmp(DMX_FE_ENTRY(pos)->id, frontend->id))
                   1026:                        return -EEXIST;
                   1027:        }
                   1028: 
                   1029:        list_add(&(frontend->connectivity_list), head);
                   1030:         return 0;
                   1031: }
                   1032: 
                   1033: static int 
                   1034: dvbdmx_remove_frontend(dmx_demux_t *demux, 
                   1035:                        dmx_frontend_t *frontend)
                   1036: {
                   1037:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                   1038:         struct list_head *pos, *head=&dvbdemux->frontend_list;
                   1039: 
                   1040:        list_for_each(pos, head) 
                   1041:        {
                   1042:                if (DMX_FE_ENTRY(pos)==frontend) 
                   1043:                 {
                   1044:                        list_del(pos);
                   1045:                        return 0;
                   1046:                }
                   1047:        }
                   1048:        return -ENODEV;
                   1049: }
                   1050: 
                   1051: static struct list_head *
                   1052: dvbdmx_get_frontends(dmx_demux_t *demux)
                   1053: {
                   1054:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                   1055: 
                   1056:         if (list_empty(&dvbdemux->frontend_list))
                   1057:                return NULL;
                   1058:         return &dvbdemux->frontend_list;
                   1059: }
                   1060: 
                   1061: static int dvbdmx_connect_frontend(dmx_demux_t *demux, 
                   1062:                                    dmx_frontend_t *frontend)
                   1063: {
1.8       mocm     1064:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                   1065: 
1.1       mocm     1066:         if (demux->frontend)
                   1067:                 return -EINVAL;
                   1068:         
1.8       mocm     1069:         down_interruptible(&dvbdemux->mutex);
1.1       mocm     1070:         demux->frontend=frontend;
1.8       mocm     1071:         up(&dvbdemux->mutex);
1.1       mocm     1072:         return 0;
                   1073: }
                   1074: 
                   1075: static int dvbdmx_disconnect_frontend(dmx_demux_t *demux)
                   1076: {
1.8       mocm     1077:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                   1078: 
                   1079:         down_interruptible(&dvbdemux->mutex);
1.1       mocm     1080:         demux->frontend=NULL;
1.8       mocm     1081:         up(&dvbdemux->mutex);
1.1       mocm     1082:         return 0;
                   1083: }
                   1084: 
1.8       mocm     1085: static int dvbdmx_get_pes_pids(dmx_demux_t *demux, u16 *pids)
1.1       mocm     1086: {
                   1087:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                   1088: 
1.8       mocm     1089:         memcpy(pids, dvbdemux->pids, 5*sizeof(u16));
1.1       mocm     1090:         return 0;
                   1091: }
                   1092: 
                   1093: int 
1.3       mocm     1094: DvbDmxInit(dvb_demux_t *dvbdemux)
1.1       mocm     1095: {
1.3       mocm     1096:         int i;
1.1       mocm     1097:         dmx_demux_t *dmx=&dvbdemux->dmx;
                   1098: 
1.3       mocm     1099:         dvbdemux->users=0;
1.1       mocm     1100:        dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(dvb_demux_filter_t));
                   1101:        if (!dvbdemux->filter)
                   1102:                 return -ENOMEM;
1.4       mocm     1103: 
                   1104:        dvbdemux->feed=vmalloc(dvbdemux->feednum*sizeof(dvb_demux_feed_t));
                   1105:        if (!dvbdemux->feed) {
                   1106:                vfree(dvbdemux->filter);
                   1107:                 return -ENOMEM;
                   1108:        }
                   1109:         for (i=0; i<dvbdemux->filternum; i++) {
1.1       mocm     1110:                 dvbdemux->filter[i].state=DMX_STATE_FREE;
                   1111:                 dvbdemux->filter[i].index=i;
                   1112:         }
1.4       mocm     1113:         for (i=0; i<dvbdemux->feednum; i++)
1.1       mocm     1114:                 dvbdemux->feed[i].state=DMX_STATE_FREE;
1.3       mocm     1115:         dvbdemux->frontend_list.next=
                   1116:           dvbdemux->frontend_list.prev=
                   1117:             &dvbdemux->frontend_list;
1.1       mocm     1118:         for (i=0; i<DMX_TS_PES_OTHER; i++) {
                   1119:                 dvbdemux->pesfilter[i]=NULL;
                   1120:                 dvbdemux->pids[i]=0xffff;
                   1121:        }
                   1122:         dvbdemux->playing=dvbdemux->recording=0;
1.8       mocm     1123:         memset(dvbdemux->pid2feed, 0, (DMX_MAX_PID+1)*sizeof(dvb_demux_feed_t *));
1.1       mocm     1124:         dvbdemux->tsbufp=0;
                   1125: 
                   1126:         dmx->frontend=0;
                   1127:         dmx->reg_list.next=dmx->reg_list.prev=&dmx->reg_list;
                   1128:         dmx->priv=(void *) dvbdemux;
1.3       mocm     1129:         //dmx->users=0;                  // reset in dmx_register_demux() 
1.1       mocm     1130:         dmx->open=dvbdmx_open;
                   1131:         dmx->close=dvbdmx_close;
                   1132:         dmx->write=dvbdmx_write;
                   1133:         dmx->allocate_ts_feed=dvbdmx_allocate_ts_feed;
                   1134:         dmx->release_ts_feed=dvbdmx_release_ts_feed;
                   1135:         dmx->allocate_pes_feed=dvbdmx_allocate_pes_feed;
                   1136:         dmx->release_pes_feed=dvbdmx_release_pes_feed;
                   1137:         dmx->allocate_section_feed=dvbdmx_allocate_section_feed;
                   1138:         dmx->release_section_feed=dvbdmx_release_section_feed;
                   1139: 
                   1140:         dmx->descramble_mac_address=NULL;
                   1141:         dmx->descramble_section_payload=NULL;
                   1142:         
                   1143:         dmx->add_frontend=dvbdmx_add_frontend;
                   1144:         dmx->remove_frontend=dvbdmx_remove_frontend;
                   1145:         dmx->get_frontends=dvbdmx_get_frontends;
                   1146:         dmx->connect_frontend=dvbdmx_connect_frontend;
                   1147:         dmx->disconnect_frontend=dvbdmx_disconnect_frontend;
                   1148:         dmx->get_pes_pids=dvbdmx_get_pes_pids;
1.8       mocm     1149:         sema_init(&dvbdemux->mutex, 1);
1.1       mocm     1150: 
                   1151:         if (dmx_register_demux(dmx)<0) 
                   1152:                 return -1;
1.4       mocm     1153: 
1.1       mocm     1154:         return 0;
                   1155: }
                   1156: 
                   1157: int 
                   1158: DvbDmxRelease(dvb_demux_t *dvbdemux)
                   1159: {
                   1160:         dmx_demux_t *dmx=&dvbdemux->dmx;
                   1161: 
                   1162:         dmx_unregister_demux(dmx);
                   1163:        if (dvbdemux->filter)
                   1164:                 vfree(dvbdemux->filter);
1.4       mocm     1165:        if (dvbdemux->feed)
                   1166:                 vfree(dvbdemux->feed);
1.1       mocm     1167:         return 0;
                   1168: }

LinuxTV legacy CVS <linuxtv.org/cvs>