Annotation of margi2/dvb_demux.c, revision 1.3

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: 
                     31: LIST_HEAD(dmx_muxs);
                     32: 
                     33: int dmx_register_demux(dmx_demux_t *demux) 
                     34: {
                     35:        struct list_head *pos, *head=&dmx_muxs;
                     36:        
                     37:        if (!(demux->id && demux->vendor && demux->model)) 
                     38:                return -EINVAL;
                     39:        list_for_each(pos, head) 
                     40:        {
                     41:                if (!strcmp(DMX_DIR_ENTRY(pos)->id, demux->id))
                     42:                        return -EEXIST;
                     43:        }
                     44:        
                     45:        demux->users=0;
                     46:        list_add(&(demux->reg_list), head);
                     47:        MOD_INC_USE_COUNT;
                     48:        return 0;
                     49: }
                     50: 
                     51: int dmx_unregister_demux(dmx_demux_t* demux)
                     52: {
                     53:        struct list_head *pos, *head=&dmx_muxs;
                     54: 
                     55:        list_for_each(pos, head) 
                     56:        {
                     57:                if (DMX_DIR_ENTRY(pos)==demux) 
                     58:                {
                     59:                        if (demux->users!=0)
                     60:                                return -EINVAL;
                     61:                        list_del(pos);
                     62:                        MOD_DEC_USE_COUNT;
                     63:                        return 0;
                     64:                }
                     65:        }
                     66:        return -ENODEV;
                     67: }
                     68: 
                     69: 
                     70: struct list_head *dmx_get_demuxes(void)
                     71: {
                     72:         if (list_empty(&dmx_muxs))
                     73:                return NULL;
                     74: 
                     75:        return &dmx_muxs;
                     76: }
                     77: 
                     78: /******************************************************************************
                     79:  * static inlined helper functions
                     80:  ******************************************************************************/
                     81: 
                     82: static inline u16 
                     83: section_length(const u8 *buf)
                     84: {
1.2       mocm       85:         return 3+((buf[1]&0x0f)<<8)+buf[2];
1.1       mocm       86: }
                     87: 
                     88: static inline u16 
                     89: ts_pid(const u8 *buf)
                     90: {
1.2       mocm       91:         return ((buf[1]&0x1f)<<8)+buf[2];
1.1       mocm       92: }
                     93: 
                     94: static inline int
1.2       mocm       95: payload(const u8 *tsp)
1.1       mocm       96: {
                     97:         if (!(tsp[3]&0x10)) // no payload?
                     98:                 return 0;
1.2       mocm       99:         if (tsp[3]&0x20)   // adaptation field?
                    100:                 return 184-1-tsp[4];
                    101:         return 184;
1.1       mocm      102: }
                    103: 
                    104: /******************************************************************************
                    105:  * Software filter functions
                    106:  ******************************************************************************/
                    107: 
                    108: static inline int
                    109: DvbDmxSWFilterPayload(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) 
                    110: {
1.2       mocm      111:         int p, count, ccok;
1.1       mocm      112: 
1.2       mocm      113:         if (!(count=payload(buf)))
1.1       mocm      114:                 return -1;
1.2       mocm      115:         p=188-count;
1.1       mocm      116:         ccok=((dvbdmxfeed->cc+1)&0x0f)==(buf[3]&0x0f) ? 1 : 0;
                    117:         dvbdmxfeed->cc=buf[3]&0x0f;
1.2       mocm      118:         /*
1.1       mocm      119:         if (!ccok)
                    120:           printk("missed packet!\n");
                    121:         */
1.2       mocm      122:         if (buf[1]&0x40)  // PUSI ?
1.1       mocm      123:                 dvbdmxfeed->peslen=0xfffa;
                    124:         dvbdmxfeed->peslen+=count;
                    125: 
                    126:         return dvbdmxfeed->cb.ts((u8 *)&buf[p], count, 0, 0, 
                    127:                                  &dvbdmxfeed->feed.ts, DMX_OK); 
                    128: }
                    129: 
                    130: 
                    131: static int
                    132: DvbDmxSWFilterSectionFilter(dvb_demux_feed_t *dvbdmxfeed, 
                    133:                             dvb_demux_filter_t *dvbdmxfilter)
                    134: {
                    135:         dmx_section_filter_t *filter=&dvbdmxfilter->filter;
                    136: #if 0
                    137:         int i;
                    138: 
                    139:         for (i=0; i<DVB_DEMUX_MASK_MAX; i++)
                    140:                 if (filter->filter_mask[i]&
                    141:                     (filter->filter_value[i]^dvbdmxfeed->secbuf[i]))
                    142:                         return 0;
                    143: #else
                    144:         u32 res;
                    145:         u32 *val=(u32 *)(filter->filter_value);
                    146:         u32 *mask=(u32 *)(filter->filter_mask);
                    147:         u32 *data=(u32 *)(dvbdmxfeed->secbuf);
                    148: 
                    149:         res=mask[0]&(val[0]^data[0]);
                    150:         if (res) return 0;
                    151: 
                    152:         res=mask[1]&(val[1]^data[1]);
                    153:         if (res) return 0;
                    154: 
                    155:         res=mask[2]&(val[2]^data[2]);
                    156:         if (res) return 0;
                    157: 
                    158:         res=mask[3]&(val[3]^data[3]);
                    159:         if (res) return 0;
                    160: 
                    161:         res=*(u16 *)(4+mask) & (*(u16 *)(4+val) ^ *(u16 *)(4+data));
                    162:         if (res) return 0;
                    163: #endif
                    164: 
                    165:         return dvbdmxfeed->cb.sec(dvbdmxfeed->secbuf, dvbdmxfeed->seclen, 
                    166:                                   0, 0, filter, DMX_OK); 
                    167: }
                    168: 
                    169: static inline int
                    170: DvbDmxSWFilterSectionFeed(dvb_demux_feed_t *dvbdmxfeed)
                    171: {
                    172:         u8 *buf=dvbdmxfeed->secbuf;
                    173:         dvb_demux_filter_t *f;
                    174: 
                    175:         if (dvbdmxfeed->secbufp!=dvbdmxfeed->seclen)
                    176:                 return -1;
                    177:         if (!dvbdmxfeed->feed.sec.is_filtering)
                    178:                 return 0;
                    179:         if (!(f=dvbdmxfeed->filter))
                    180:                 return 0;
                    181:         do 
                    182:                 if (DvbDmxSWFilterSectionFilter(dvbdmxfeed, f)<0)
                    183:                         return -1;
                    184:         while ((f=f->next) && dvbdmxfeed->feed.sec.is_filtering);
                    185: 
                    186:         dvbdmxfeed->secbufp=dvbdmxfeed->seclen=0;
                    187:         memset(buf, 0, DVB_DEMUX_MASK_MAX);
                    188:         return 0;
                    189: }
                    190: 
                    191: static inline int
                    192: DvbDmxSWFilterSectionPacket(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) 
                    193: {
1.2       mocm      194:         int p, count;
                    195:         int ccok, rest;
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;
1.1       mocm      200: 
1.2       mocm      201:         ccok=((dvbdmxfeed->cc+1)&0x0f)==(buf[3]&0x0f) ? 1 : 0;
                    202:         dvbdmxfeed->cc=buf[3]&0x0f;
1.1       mocm      203: 
1.2       mocm      204:         if (buf[1]&0x40) { // PUSI set -- a section begins in this packet
                    205:                 // offset to start of first section is in buf[p] 
1.1       mocm      206: 
1.2       mocm      207:                 if (buf[p] && ccok) { // rest of previous section?
1.1       mocm      208: 
1.2       mocm      209:                         // did we have enough data in last packet to calc length?
                    210:                         if (dvbdmxfeed->secbufp && dvbdmxfeed->secbufp<3) {
                    211:                                 memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp,
                    212:                                        buf+p+1, 
                    213:                                        3-dvbdmxfeed->secbufp);
                    214:                                 dvbdmxfeed->seclen=section_length(dvbdmxfeed->secbuf);
                    215:                         }
1.1       mocm      216:                         rest=dvbdmxfeed->seclen-dvbdmxfeed->secbufp;
                    217:                         if (rest==buf[p] && dvbdmxfeed->seclen) {
                    218:                                 memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp,
                    219:                                        buf+p+1, buf[p]);
                    220:                                 dvbdmxfeed->secbufp+=buf[p];
                    221:                                 DvbDmxSWFilterSectionFeed(dvbdmxfeed);
                    222:                         }
                    223:                 }
1.2       mocm      224:                 p+=buf[p]+1;           // skip rest of last section
                    225:                 count=188-p;
1.1       mocm      226:                 while (count>0) {
1.2       mocm      227:                         if ((count>2) &&  // enough data to determine sec length?
1.1       mocm      228:                             ((dvbdmxfeed->seclen=section_length(buf+p))<=count)) {
                    229:                                 memcpy(dvbdmxfeed->secbuf, buf+p, 
                    230:                                        dvbdmxfeed->seclen);
                    231:                                 dvbdmxfeed->secbufp=dvbdmxfeed->seclen;
                    232:                                 p+=dvbdmxfeed->seclen;
1.2       mocm      233:                                 count=188-p;
1.1       mocm      234:                                 DvbDmxSWFilterSectionFeed(dvbdmxfeed);
1.2       mocm      235: 
                    236:                                 // filling bytes until packet end?
                    237:                                 if (buf[p]==0xff) 
                    238:                                         count=0;
                    239:                         } else { // section continues to following ts block
1.1       mocm      240:                                 memcpy(dvbdmxfeed->secbuf, buf+p, count);
1.2       mocm      241:                                 dvbdmxfeed->secbufp+=count;
1.1       mocm      242:                                 count=0;
                    243:                         }
                    244:                 }
1.2       mocm      245:         } else {               // section continued below
1.1       mocm      246:                 if (!ccok)
                    247:                         return -1;
1.2       mocm      248:                 if (!dvbdmxfeed->secbufp) // any data in last ts packet?
                    249:                         return -1;
                    250:                 // did we have enough data in last packet to calc section length?
1.1       mocm      251:                 if (dvbdmxfeed->secbufp<3) {
1.2       mocm      252:                         memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, 
                    253:                                3-dvbdmxfeed->secbufp);
1.1       mocm      254:                         dvbdmxfeed->seclen=section_length(dvbdmxfeed->secbuf);
                    255:                 }
                    256:                 rest=dvbdmxfeed->seclen-dvbdmxfeed->secbufp;
1.2       mocm      257:                 if (rest<0)
1.1       mocm      258:                         return -1;
1.2       mocm      259:                if (rest<=count) {      // section completed in this ts block
                    260:                        memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, rest);
                    261:                        dvbdmxfeed->secbufp+=rest;
                    262:                        DvbDmxSWFilterSectionFeed(dvbdmxfeed);
                    263:                } else  {       // section continues in following ts block
                    264:                         memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, count);
                    265:                         dvbdmxfeed->secbufp+=count;
                    266:                }
                    267: 
1.1       mocm      268:         }
                    269:         return 0;
                    270: }
                    271: 
                    272: static void 
                    273: DvbDmxSWFilterPacketType(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf)
                    274: {
                    275:         switch(dvbdmxfeed->type) {
                    276:         case DMX_TYPE_TS:
                    277:                 if (!dvbdmxfeed->feed.ts.is_filtering)
                    278:                         break;
                    279:                 if (dvbdmxfeed->ts_type & TS_PACKET) {
                    280:                         if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
                    281:                                 DvbDmxSWFilterPayload(dvbdmxfeed, buf);
                    282:                         else
                    283:                                 dvbdmxfeed->cb.ts((u8 *)buf, 188, 0, 0, 
                    284:                                                   &dvbdmxfeed->feed.ts, DMX_OK); 
                    285:                 }
                    286:                 if (dvbdmxfeed->ts_type & TS_DECODER) 
                    287:                         if (dvbdmxfeed->demux->write_to_decoder)
                    288:                                 dvbdmxfeed->demux->
                    289:                                   write_to_decoder(dvbdmxfeed, (u8 *)buf, 188);
                    290:                 break;
                    291: 
                    292:         case DMX_TYPE_SEC:
                    293:                 if (!dvbdmxfeed->feed.sec.is_filtering)
                    294:                         break;
                    295:                 if (DvbDmxSWFilterSectionPacket(dvbdmxfeed, buf)<0)
                    296:                         dvbdmxfeed->seclen=dvbdmxfeed->secbufp=0;
                    297:                 break;
                    298: 
                    299:         default:
                    300:                 break;
                    301:         }
                    302: }
                    303: 
                    304: void inline
                    305: DvbDmxSWFilterPacket(dvb_demux_t *dvbdmx, const u8 *buf)
                    306: {
                    307:         dvb_demux_feed_t *dvbdmxfeed;
                    308: 
                    309:         if (!(dvbdmxfeed=dvbdmx->pid2feed[ts_pid(buf)]))
                    310:                 return;
                    311:         DvbDmxSWFilterPacketType(dvbdmxfeed, buf);
                    312: }
                    313: 
                    314: void
                    315: DvbDmxSWFilterPackets(dvb_demux_t *dvbdmx, const u8 *buf, int count)
                    316: {
                    317:         dvb_demux_feed_t *dvbdmxfeed;
                    318: 
                    319:         for (; count>0; count--, buf+=188)
                    320:                 if ((dvbdmxfeed=dvbdmx->pid2feed[ts_pid(buf)]))
                    321:                         DvbDmxSWFilterPacketType(dvbdmxfeed, buf);
                    322: }
                    323: 
                    324: static inline void
                    325: DvbDmxSWFilter(dvb_demux_t *dvbdmx, const u8 *buf, size_t count)
                    326: {
                    327:         int p=0,i, j;
                    328:         
                    329:         if ((i=dvbdmx->tsbufp)) {
                    330:                 if (count<(j=188-i)) {
                    331:                         memcpy(&dvbdmx->tsbuf[i], buf, count);
                    332:                         dvbdmx->tsbufp+=count;
                    333:                         return;
                    334:                 }
                    335:                 memcpy(&dvbdmx->tsbuf[i], buf, j);
                    336:                 DvbDmxSWFilterPacket(dvbdmx, dvbdmx->tsbuf);
                    337:                 dvbdmx->tsbufp=0;
                    338:                 p+=j;
                    339:         }
                    340:         
                    341:         while (p<count) {
                    342:                 if (buf[p]==0x47) {
                    343:                         if (count-p>=188) {
                    344:                                 DvbDmxSWFilterPacket(dvbdmx, buf+p);
                    345:                                 p+=188;
                    346:                         } else {
                    347:                                 i=count-p;
                    348:                                 memcpy(dvbdmx->tsbuf, buf+p, i);
                    349:                                 dvbdmx->tsbufp=i;
                    350:                                 return;
                    351:                         }
                    352:                 } else 
                    353:                         p++;
                    354:         }          
                    355: }
                    356: 
                    357: 
                    358: /******************************************************************************
                    359:  ******************************************************************************
                    360:  * DVB DEMUX API LEVEL FUNCTIONS
                    361:  ******************************************************************************
                    362:  ******************************************************************************/
                    363: 
                    364: static dvb_demux_filter_t *
                    365: DvbDmxFilterAlloc(dvb_demux_t *dvbdmx)
                    366: {
                    367:         int i;
                    368: 
                    369:         for (i=0; i<DVB_DEMUX_FILTER_MAX; i++)
                    370:                 if (dvbdmx->filter[i].state==DMX_STATE_FREE)
                    371:                         break;
                    372:         if (i==DVB_DEMUX_FILTER_MAX)  
                    373:                 return 0;
                    374:         dvbdmx->filter[i].state=DMX_STATE_ALLOCATED;
                    375:         return &dvbdmx->filter[i];
                    376: }
                    377: 
                    378: static dvb_demux_feed_t *
                    379: DvbDmxFeedAlloc(dvb_demux_t *dvbdmx)
                    380: {
                    381:         int i;
                    382: 
                    383:         for (i=0; i<DVB_DEMUX_FEED_MAX; i++)
                    384:                 if (dvbdmx->feed[i].state==DMX_STATE_FREE)
                    385:                         break;
                    386:         if (i==DVB_DEMUX_FEED_MAX)
                    387:                 return 0;
                    388:         dvbdmx->feed[i].state=DMX_STATE_ALLOCATED;
                    389:         return &dvbdmx->feed[i];
                    390: }
                    391: 
                    392: 
                    393: /******************************************************************************
                    394:  * dmx_ts_feed API calls
                    395:  ******************************************************************************/
                    396: 
                    397: static int 
                    398: dmx_ts_feed_set_type(dmx_ts_feed_t *feed, int type, dmx_ts_pes_t pes_type)
                    399: {
                    400:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    401:         dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
                    402:   
                    403:         dvbdmxfeed->ts_type=type;
                    404:         dvbdmxfeed->pes_type=pes_type;
                    405: 
                    406:         if (dvbdmxfeed->ts_type & TS_DECODER) {
                    407:                 if (pes_type >= DMX_TS_PES_OTHER)
                    408:                         return -EINVAL;
                    409:                 if (dvbdmx->pesfilter[pes_type] && 
                    410:                     (dvbdmx->pesfilter[pes_type]!=dvbdmxfeed))
                    411:                         return -EINVAL;
                    412:                 dvbdmx->pesfilter[pes_type]=dvbdmxfeed;
                    413:                 //printk("pids[%d]=%04x\n", pes_type, dvbdmxfeed->pid);
                    414:                dvbdmx->pids[pes_type]=dvbdmxfeed->pid;
                    415:         }
                    416:         return 0;
                    417: }
                    418: 
                    419: static int 
                    420: dmx_ts_feed_set(struct dmx_ts_feed_s* feed,
                    421:                 __u16 pid,
                    422:                 size_t callback_length, 
                    423:                 size_t circular_buffer_size, 
                    424:                 int descramble, 
                    425:                 struct timespec timeout
                    426:                 )
                    427: {
                    428:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    429:         dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
                    430: 
                    431:         if (pid>0x1fff)
                    432:                 return -EINVAL;
                    433:         if (dvbdmxfeed->pid!=0xffff) {
                    434:                 if (dvbdmxfeed->pid<=0x1fff)
                    435:                         dvbdmx->pid2feed[dvbdmxfeed->pid]=0;
                    436:                 dvbdmxfeed->pid=0xffff;
                    437:         }
                    438:         if (dvbdmx->pid2feed[pid])
                    439:                 return -EBUSY;
                    440: 
                    441:         dvbdmx->pid2feed[pid]=dvbdmxfeed;
                    442:         dvbdmxfeed->pid=pid;
                    443: 
                    444:         dvbdmxfeed->buffer_size=circular_buffer_size;
                    445:         dvbdmxfeed->descramble=descramble;
                    446:         dvbdmxfeed->timeout=timeout;
                    447:         dvbdmxfeed->cb_length=callback_length;
                    448:         dvbdmxfeed->ts_type=TS_PACKET;
                    449: 
                    450:         if (dvbdmxfeed->descramble)
                    451:                 return -ENOSYS;
                    452: 
                    453:         if (dvbdmxfeed->buffer_size) {
                    454:                 dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size);
                    455:                 if (!dvbdmxfeed->buffer)
                    456:                         return -ENOMEM;
                    457:         }
                    458:         dvbdmxfeed->state=DMX_STATE_READY;
                    459:         return 0;
                    460: }
                    461: 
                    462: static int 
                    463: dmx_ts_feed_start_filtering(struct dmx_ts_feed_s* feed)
                    464: {
                    465:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    466:         dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
                    467:        int ret;
                    468: 
                    469:         if (dvbdmxfeed->state!=DMX_STATE_READY)
                    470:                 return -EINVAL;
                    471:         if (dvbdmxfeed->type!=DMX_TYPE_TS)
                    472:                 return -EINVAL;
                    473: 
1.3     ! mocm      474:         if (!dvbdmx->start_feed)
        !           475:                 return -1;
1.1       mocm      476:         ret=dvbdmx->start_feed(dvbdmxfeed); 
                    477:         if (ret<0) 
                    478:               return ret;
                    479:         feed->is_filtering=1;
                    480:         dvbdmxfeed->state=DMX_STATE_GO;
                    481:        return 0;
                    482: }
                    483:  
                    484: static int 
                    485: dmx_ts_feed_stop_filtering(struct dmx_ts_feed_s* feed)
                    486: {
                    487:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    488:         dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
                    489:        int ret;
                    490: 
                    491:         //printk ("function : %s\n", __FUNCTION__);
                    492:         if (dvbdmxfeed->state<DMX_STATE_GO)
                    493:                 return -EINVAL;
1.3     ! mocm      494:         if (!dvbdmx->stop_feed)
        !           495:                 return -1;
1.1       mocm      496:         ret=dvbdmx->stop_feed(dvbdmxfeed); 
                    497:         feed->is_filtering=0;
                    498:         dvbdmxfeed->state=DMX_STATE_ALLOCATED;
                    499: 
                    500:         return ret;
                    501: }
                    502: 
                    503: static int dvbdmx_allocate_ts_feed(dmx_demux_t *demux,
                    504:                                    dmx_ts_feed_t **feed, 
                    505:                                    dmx_ts_cb callback)
                    506: {
                    507:         dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
                    508:         dvb_demux_feed_t *dvbdmxfeed;
                    509: 
                    510:         if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx)))
                    511:                 return -EBUSY;
                    512: 
                    513:         dvbdmxfeed->type=DMX_TYPE_TS;
                    514:         dvbdmxfeed->cb.ts=callback;
                    515:         dvbdmxfeed->demux=dvbdmx;
                    516:         dvbdmxfeed->pid=0xffff;
                    517:         dvbdmxfeed->peslen=0xfffa;
                    518: 
                    519:         (*feed)=&dvbdmxfeed->feed.ts;
                    520:         (*feed)->is_filtering=0;
                    521:         (*feed)->parent=demux;
                    522:         (*feed)->priv=0;
                    523:         (*feed)->set=dmx_ts_feed_set;
                    524:         (*feed)->set_type=dmx_ts_feed_set_type;
                    525:         (*feed)->start_filtering=dmx_ts_feed_start_filtering;
                    526:         (*feed)->stop_filtering=dmx_ts_feed_stop_filtering;
                    527: 
                    528: 
                    529:         if (!(dvbdmxfeed->filter=DvbDmxFilterAlloc(dvbdmx))) {
                    530:                 dvbdmxfeed->state=DMX_STATE_FREE;
                    531:                 return -EBUSY;
                    532:         }
                    533: 
                    534:         dvbdmxfeed->filter->type=DMX_TYPE_TS;
                    535:         dvbdmxfeed->filter->feed=dvbdmxfeed;
                    536:         dvbdmxfeed->filter->state=DMX_STATE_READY;
                    537:         
                    538:         return 0;
                    539: }
                    540: 
                    541: static int dvbdmx_release_ts_feed(dmx_demux_t *demux, dmx_ts_feed_t *feed)
                    542: {
                    543:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    544: 
                    545:         if (dvbdmxfeed->state==DMX_STATE_FREE)
                    546:                 return -EINVAL;
1.3     ! mocm      547:         if (dvbdmxfeed->buffer) { 
1.1       mocm      548:                 vfree(dvbdmxfeed->buffer);
1.3     ! mocm      549:                 dvbdmxfeed->buffer=0;
        !           550:         }
1.1       mocm      551:         dvbdmxfeed->state=DMX_STATE_FREE;
                    552:         dvbdmxfeed->filter->state=DMX_STATE_FREE;
                    553:         if (dvbdmxfeed->pid!=0xffff) {
                    554:                 if (dvbdmxfeed->pid<=0x1fff) 
                    555:                         dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0;
                    556:                 dvbdmxfeed->pid=0xffff;
                    557:         }
                    558: 
                    559:         return 0;
                    560: }
                    561: 
                    562: 
                    563: /******************************************************************************
                    564:  * dmx_pes_feed API calls
                    565:  ******************************************************************************/
                    566: /*
                    567: static int 
                    568: dmx_pes_feed_set(struct dmx_pes_feed_s* feed,
                    569:                  __u16 pid,
                    570:                  size_t circular_buffer_size, 
                    571:                  int descramble, 
                    572:                  struct timespec timeout)
                    573: {
                    574:         return 0;
                    575: }
                    576: 
                    577: static int 
                    578: dmx_pes_feed_start_filtering(struct dmx_pes_feed_s* feed)
                    579: {
                    580:         return 0;
                    581: }
                    582:  
                    583: static int 
                    584: dmx_pes_feed_stop_filtering(struct dmx_pes_feed_s* feed)
                    585: {
                    586:         return 0;
                    587: }
                    588: */
                    589: 
                    590: static int dvbdmx_allocate_pes_feed(dmx_demux_t *demux, 
                    591:                                     dmx_pes_feed_t **feed,
                    592:                                     dmx_pes_cb callback)
                    593: {
                    594:         return 0;
                    595: }
                    596: 
                    597: static int dvbdmx_release_pes_feed(dmx_demux_t *demux, 
                    598:                                    dmx_pes_feed_t *feed)
                    599: {
                    600:         return 0;
                    601: }
                    602: 
                    603: 
                    604: /******************************************************************************
                    605:  * dmx_section_feed API calls
                    606:  ******************************************************************************/
                    607: 
                    608: static int 
                    609: dmx_section_feed_allocate_filter(struct dmx_section_feed_s* feed, 
                    610:                                  dmx_section_filter_t** filter) 
                    611: {
                    612:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    613:         dvb_demux_t *dvbdemux=dvbdmxfeed->demux;
                    614:         dvb_demux_filter_t *dvbdmxfilter;
                    615: 
                    616:         dvbdmxfilter=DvbDmxFilterAlloc(dvbdemux);
                    617:         if (!dvbdmxfilter)
                    618:                 return -ENOSPC;
                    619: 
                    620:         *filter=&dvbdmxfilter->filter;
                    621:         (*filter)->parent=feed;
                    622:         (*filter)->priv=0;
                    623:         dvbdmxfilter->feed=dvbdmxfeed;
                    624:         dvbdmxfilter->pid=dvbdmxfeed->pid; 
                    625:         dvbdmxfilter->type=DMX_TYPE_SEC;
                    626:         dvbdmxfilter->state=DMX_STATE_READY;
                    627: 
                    628:         dvbdmxfilter->next=dvbdmxfeed->filter;
                    629:         dvbdmxfeed->filter=dvbdmxfilter;
                    630:         return 0;
                    631: }
                    632: 
                    633: static int 
                    634: dmx_section_feed_set(struct dmx_section_feed_s* feed, 
                    635:                      __u16 pid, size_t circular_buffer_size, 
                    636:                      int descramble, int check_crc) 
                    637: {
                    638:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    639:         dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
                    640: 
                    641:         //printk ("function : %s  PID %04x\n", __FUNCTION__, pid);
                    642: 
                    643:         if (pid>0x1fff)
                    644:                 return -EINVAL;
                    645:         if (dvbdmxfeed->pid!=0xffff) {
                    646:                 dvbdmx->pid2feed[dvbdmxfeed->pid]=0;
                    647:                 dvbdmxfeed->pid=0xffff;
                    648:         }
                    649:         if (dvbdmx->pid2feed[pid])
                    650:                 return -EBUSY;
                    651:         dvbdmx->pid2feed[pid]=dvbdmxfeed;
                    652: 
                    653:         dvbdmxfeed->pid=pid;
                    654:         dvbdmxfeed->buffer_size=circular_buffer_size;
                    655:         dvbdmxfeed->descramble=descramble;
                    656:         if (dvbdmxfeed->descramble)
                    657:                 return -ENOSYS;
                    658: 
                    659:         dvbdmxfeed->check_crc=check_crc;
                    660:         dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size);
                    661:         if (!dvbdmxfeed->buffer)
                    662:                 return -ENOMEM;
1.3     ! mocm      663:         dvbdmxfeed->state=DMX_STATE_READY;
1.1       mocm      664:         return 0;
                    665: }
                    666: 
                    667: static int 
                    668: dmx_section_feed_start_filtering(dmx_section_feed_t *feed)
                    669: {
                    670:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    671:         dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
                    672:        int ret;
                    673: 
                    674:         if (feed->is_filtering)
                    675:                 return -EBUSY;
                    676:         if (!dvbdmxfeed->filter)
                    677:                 return -EINVAL;
                    678: 
                    679:         dvbdmxfeed->secbufp=0;
                    680:         dvbdmxfeed->seclen=0;
                    681:         
1.3     ! mocm      682:         if (!dvbdmx->start_feed)
        !           683:                 return -1;
1.1       mocm      684:         ret=dvbdmx->start_feed(dvbdmxfeed); 
                    685:        if (ret<0) 
                    686:                return ret;
                    687:         feed->is_filtering=1;
                    688:         dvbdmxfeed->state=DMX_STATE_GO;
                    689:        return 0;
                    690: }
                    691: 
                    692: static int 
                    693: dmx_section_feed_stop_filtering(struct dmx_section_feed_s* feed)
                    694: {
                    695:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    696:         dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
1.3     ! mocm      697:         int ret;
        !           698: 
        !           699:         if (!dvbdmx->stop_feed)
        !           700:                 return -1;
        !           701:        ret=dvbdmx->stop_feed(dvbdmxfeed); 
1.1       mocm      702: 
                    703:         dvbdmxfeed->state=DMX_STATE_READY;
                    704:         feed->is_filtering=0;
                    705:        return ret;
                    706: }
                    707: 
                    708: static int 
                    709: dmx_section_feed_release_filter(dmx_section_feed_t *feed, 
                    710:                                 dmx_section_filter_t* filter)
                    711: {
                    712:         dvb_demux_filter_t *dvbdmxfilter=(dvb_demux_filter_t *) filter, *f;
                    713:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    714: 
                    715:         if (dvbdmxfilter->feed!=dvbdmxfeed)
                    716:                 return -EINVAL;
                    717:         if (feed->is_filtering) 
1.2       mocm      718:                 feed->stop_filtering(feed);
                    719:                 //return -EBUSY;
1.1       mocm      720: 
                    721:         f=dvbdmxfeed->filter;
1.3     ! mocm      722:         if (f==dvbdmxfilter)
1.1       mocm      723:                 dvbdmxfeed->filter=dvbdmxfilter->next;
                    724:         else {
                    725:                 while(f->next!=dvbdmxfilter)
                    726:                         f=f->next;
                    727:                 f->next=f->next->next;
                    728:         }
                    729: 
                    730:         dvbdmxfilter->state=DMX_STATE_FREE;
                    731:         return 0;
                    732: }
                    733: 
                    734: static int dvbdmx_allocate_section_feed(dmx_demux_t *demux, 
                    735:                                         dmx_section_feed_t **feed,
                    736:                                         dmx_section_cb callback)
                    737: {
                    738:         dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
                    739:         dvb_demux_feed_t *dvbdmxfeed;
                    740: 
                    741:         if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx)))
                    742:                 return -EBUSY;
                    743:         dvbdmxfeed->type=DMX_TYPE_SEC;
                    744:         dvbdmxfeed->cb.sec=callback;
                    745:         dvbdmxfeed->demux=dvbdmx;
                    746:         dvbdmxfeed->pid=0xffff;
                    747:         dvbdmxfeed->secbufp=0;
                    748:         dvbdmxfeed->filter=0;
                    749: 
                    750:         (*feed)=&dvbdmxfeed->feed.sec;
                    751:         (*feed)->is_filtering=0;
                    752:         (*feed)->parent=demux;
                    753:         (*feed)->priv=0;
                    754:         (*feed)->set=dmx_section_feed_set;
                    755:         (*feed)->allocate_filter=dmx_section_feed_allocate_filter;
                    756:         (*feed)->release_filter=dmx_section_feed_release_filter;
                    757:         (*feed)->start_filtering=dmx_section_feed_start_filtering;
                    758:         (*feed)->stop_filtering=dmx_section_feed_stop_filtering;
                    759:         return 0;
                    760: }
                    761: 
                    762: static int dvbdmx_release_section_feed(dmx_demux_t *demux, 
                    763:                                        dmx_section_feed_t *feed)
                    764: {
                    765:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    766: 
                    767:         if (dvbdmxfeed->state==DMX_STATE_FREE)
                    768:                 return -EINVAL;
1.3     ! mocm      769:         if (dvbdmxfeed->buffer) {
1.1       mocm      770:                 vfree(dvbdmxfeed->buffer);
1.3     ! mocm      771:                 dvbdmxfeed->buffer=0;
        !           772:         }
1.1       mocm      773:         dvbdmxfeed->state=DMX_STATE_FREE;
                    774:         dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0;
                    775:         if (dvbdmxfeed->pid!=0xffff)
                    776:                 dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0;
                    777:         return 0;
                    778: }
                    779: 
                    780: 
                    781: /******************************************************************************
                    782:  * dvb_demux kernel data API calls
                    783:  ******************************************************************************/
                    784: 
1.3     ! mocm      785: static int dvbdmx_open(dmx_demux_t *demux)
1.1       mocm      786: {
                    787:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    788: 
                    789:         if (dvbdemux->users>=MAX_DVB_DEMUX_USERS)
                    790:                 return -EUSERS;
                    791:         dvbdemux->users++;
                    792:         return 0;
                    793: }
                    794: 
                    795: static int dvbdmx_close(struct dmx_demux_s *demux)
                    796: {
                    797:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    798: 
                    799:         if (dvbdemux->users==0)
                    800:                 return -ENODEV;
                    801:         dvbdemux->users--;
                    802:         //FIXME: release any unneeded resources if users==0
                    803:         return 0;
                    804: }
                    805: 
                    806: static int dvbdmx_write(dmx_demux_t *demux, const char *buf, size_t count)
                    807: {
                    808:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    809: 
                    810:         if ((!demux->frontend) ||
                    811:             (demux->frontend->source!=DMX_MEMORY_FE))
                    812:                 return -EINVAL;
                    813: 
                    814:         DvbDmxSWFilter(dvbdemux, buf, count);
                    815:         return count;
                    816: }
                    817: 
                    818: 
                    819: static int dvbdmx_add_frontend(dmx_demux_t *demux, 
                    820:                                dmx_frontend_t *frontend)
                    821: {
                    822:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    823:         struct list_head *pos, *head=&dvbdemux->frontend_list;
                    824:        
                    825:         //printk ("function : %s\n", __FUNCTION__);
                    826: 
                    827:        if (!(frontend->id && frontend->vendor && frontend->model)) 
                    828:                return -EINVAL;
                    829:        list_for_each(pos, head) 
                    830:        {
                    831:                if (!strcmp(DMX_FE_ENTRY(pos)->id, frontend->id))
                    832:                        return -EEXIST;
                    833:        }
                    834: 
                    835:        list_add(&(frontend->connectivity_list), head);
                    836:         return 0;
                    837: }
                    838: 
                    839: static int 
                    840: dvbdmx_remove_frontend(dmx_demux_t *demux, 
                    841:                        dmx_frontend_t *frontend)
                    842: {
                    843:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    844:         struct list_head *pos, *head=&dvbdemux->frontend_list;
                    845: 
                    846:        list_for_each(pos, head) 
                    847:        {
                    848:                if (DMX_FE_ENTRY(pos)==frontend) 
                    849:                 {
                    850:                        list_del(pos);
                    851:                        return 0;
                    852:                }
                    853:        }
                    854:        return -ENODEV;
                    855: }
                    856: 
                    857: static struct list_head *
                    858: dvbdmx_get_frontends(dmx_demux_t *demux)
                    859: {
                    860:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    861: 
                    862:         if (list_empty(&dvbdemux->frontend_list))
                    863:                return NULL;
                    864:         return &dvbdemux->frontend_list;
                    865: }
                    866: 
                    867: static int dvbdmx_connect_frontend(dmx_demux_t *demux, 
                    868:                                    dmx_frontend_t *frontend)
                    869: {
                    870:         if (demux->frontend)
                    871:                 return -EINVAL;
                    872:         
                    873:         demux->frontend=frontend;
                    874:         return 0;
                    875: }
                    876: 
                    877: static int dvbdmx_disconnect_frontend(dmx_demux_t *demux)
                    878: {
                    879:         demux->frontend=NULL;
                    880:         return 0;
                    881: }
                    882: 
                    883: static int dvbdmx_get_pes_pids(dmx_demux_t *demux, __u16 *pids)
                    884: {
                    885:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    886: 
                    887:         memcpy(pids, dvbdemux->pids, 5*sizeof(__u16));
                    888:         return 0;
                    889: }
                    890: 
                    891: int 
1.3     ! mocm      892: DvbDmxInit(dvb_demux_t *dvbdemux)
1.1       mocm      893: {
1.3     ! mocm      894:         int i;
1.1       mocm      895:         dmx_demux_t *dmx=&dvbdemux->dmx;
                    896: 
1.3     ! mocm      897:         dvbdemux->users=0;
1.1       mocm      898:        dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(dvb_demux_filter_t));
                    899:        if (!dvbdemux->filter)
                    900:                 return -ENOMEM;
                    901:         for (i=0; i<DVB_DEMUX_FILTER_MAX; i++) {
                    902:                 dvbdemux->filter[i].state=DMX_STATE_FREE;
                    903:                 dvbdemux->filter[i].index=i;
                    904:         }
                    905:         for (i=0; i<DVB_DEMUX_FEED_MAX; i++)
                    906:                 dvbdemux->feed[i].state=DMX_STATE_FREE;
1.3     ! mocm      907:         dvbdemux->frontend_list.next=
        !           908:           dvbdemux->frontend_list.prev=
        !           909:             &dvbdemux->frontend_list;
1.1       mocm      910:         for (i=0; i<DMX_TS_PES_OTHER; i++) {
                    911:                 dvbdemux->pesfilter[i]=NULL;
                    912:                 dvbdemux->pids[i]=0xffff;
                    913:        }
                    914:         dvbdemux->playing=dvbdemux->recording=0;
                    915:         memset(dvbdemux->pid2feed, 0, 0x2000*sizeof(dvb_demux_feed_t *));
                    916:         dvbdemux->tsbufp=0;
                    917: 
                    918:         dmx->frontend=0;
                    919:         dmx->reg_list.next=dmx->reg_list.prev=&dmx->reg_list;
                    920:         dmx->priv=(void *) dvbdemux;
1.3     ! mocm      921:         //dmx->users=0;                  // reset in dmx_register_demux() 
1.1       mocm      922:         dmx->open=dvbdmx_open;
                    923:         dmx->close=dvbdmx_close;
                    924:         dmx->write=dvbdmx_write;
                    925:         dmx->allocate_ts_feed=dvbdmx_allocate_ts_feed;
                    926:         dmx->release_ts_feed=dvbdmx_release_ts_feed;
                    927:         dmx->allocate_pes_feed=dvbdmx_allocate_pes_feed;
                    928:         dmx->release_pes_feed=dvbdmx_release_pes_feed;
                    929:         dmx->allocate_section_feed=dvbdmx_allocate_section_feed;
                    930:         dmx->release_section_feed=dvbdmx_release_section_feed;
                    931: 
                    932:         dmx->descramble_mac_address=NULL;
                    933:         dmx->descramble_section_payload=NULL;
                    934:         
                    935:         dmx->add_frontend=dvbdmx_add_frontend;
                    936:         dmx->remove_frontend=dvbdmx_remove_frontend;
                    937:         dmx->get_frontends=dvbdmx_get_frontends;
                    938:         dmx->connect_frontend=dvbdmx_connect_frontend;
                    939:         dmx->disconnect_frontend=dvbdmx_disconnect_frontend;
                    940:         dmx->get_pes_pids=dvbdmx_get_pes_pids;
                    941: 
                    942:         if (dmx_register_demux(dmx)<0) 
                    943:                 return -1;
1.3     ! mocm      944:         //if (dmx->open(dmx)<0)
        !           945:         //        return -1;
1.1       mocm      946:         return 0;
                    947: }
                    948: 
                    949: int 
                    950: DvbDmxRelease(dvb_demux_t *dvbdemux)
                    951: {
                    952:         dmx_demux_t *dmx=&dvbdemux->dmx;
                    953: 
                    954:         dmx_unregister_demux(dmx);
                    955:        if (dvbdemux->filter)
                    956:                 vfree(dvbdemux->filter);
                    957:         return 0;
                    958: }
                    959: 
                    960: /*
                    961:  * Local variables:
                    962:  * c-indent-level: 8
                    963:  * c-brace-imaginary-offset: 0
                    964:  * c-brace-offset: -8
                    965:  * c-argdecl-indent: 8
                    966:  * c-label-offset: -8
                    967:  * c-continued-statement-offset: 8
                    968:  * c-continued-brace-offset: 0
                    969:  * indent-tabs-mode: nil
                    970:  * tab-width: 8
                    971:  * End:
                    972:  */

LinuxTV legacy CVS <linuxtv.org/cvs>