Annotation of margi2/dvb_demux.c, revision 1.2

1.1       mocm        1: /* 
                      2:  * dvb_demux.c - DVB kernel demux API
                      3:  *
                      4:  * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
                      5:  *                  & Marcus Metzler <marcus@convergence.de>
                      6:                       for convergence integrated media GmbH
                      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: 
                    474:         ret=dvbdmx->start_feed(dvbdmxfeed); 
                    475:         if (ret<0) 
                    476:               return ret;
                    477:         feed->is_filtering=1;
                    478:         dvbdmxfeed->state=DMX_STATE_GO;
                    479:        return 0;
                    480: }
                    481:  
                    482: static int 
                    483: dmx_ts_feed_stop_filtering(struct dmx_ts_feed_s* feed)
                    484: {
                    485:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    486:         dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
                    487:        int ret;
                    488: 
                    489:         //printk ("function : %s\n", __FUNCTION__);
                    490:         if (dvbdmxfeed->state<DMX_STATE_GO)
                    491:                 return -EINVAL;
                    492:         ret=dvbdmx->stop_feed(dvbdmxfeed); 
                    493:         feed->is_filtering=0;
                    494:         dvbdmxfeed->state=DMX_STATE_ALLOCATED;
                    495: 
                    496:         return ret;
                    497: }
                    498: 
                    499: static int dvbdmx_allocate_ts_feed(dmx_demux_t *demux,
                    500:                                    dmx_ts_feed_t **feed, 
                    501:                                    dmx_ts_cb callback)
                    502: {
                    503:         dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
                    504:         dvb_demux_feed_t *dvbdmxfeed;
                    505: 
                    506:         if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx)))
                    507:                 return -EBUSY;
                    508: 
                    509:         dvbdmxfeed->type=DMX_TYPE_TS;
                    510:         dvbdmxfeed->cb.ts=callback;
                    511:         dvbdmxfeed->demux=dvbdmx;
                    512:         dvbdmxfeed->pid=0xffff;
                    513:         dvbdmxfeed->peslen=0xfffa;
                    514: 
                    515:         (*feed)=&dvbdmxfeed->feed.ts;
                    516:         (*feed)->is_filtering=0;
                    517:         (*feed)->parent=demux;
                    518:         (*feed)->priv=0;
                    519:         (*feed)->set=dmx_ts_feed_set;
                    520:         (*feed)->set_type=dmx_ts_feed_set_type;
                    521:         (*feed)->start_filtering=dmx_ts_feed_start_filtering;
                    522:         (*feed)->stop_filtering=dmx_ts_feed_stop_filtering;
                    523: 
                    524: 
                    525:         if (!(dvbdmxfeed->filter=DvbDmxFilterAlloc(dvbdmx))) {
                    526:                 dvbdmxfeed->state=DMX_STATE_FREE;
                    527:                 return -EBUSY;
                    528:         }
                    529: 
                    530:         dvbdmxfeed->filter->type=DMX_TYPE_TS;
                    531:         dvbdmxfeed->filter->feed=dvbdmxfeed;
                    532:         dvbdmxfeed->filter->state=DMX_STATE_READY;
                    533:         
                    534:         return 0;
                    535: }
                    536: 
                    537: static int dvbdmx_release_ts_feed(dmx_demux_t *demux, dmx_ts_feed_t *feed)
                    538: {
                    539:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    540: 
                    541:         if (dvbdmxfeed->state==DMX_STATE_FREE)
                    542:                 return -EINVAL;
1.2     ! mocm      543:         if (dvbdmxfeed->buffer) 
1.1       mocm      544:                 vfree(dvbdmxfeed->buffer);
                    545:         dvbdmxfeed->buffer=0;
                    546:         dvbdmxfeed->state=DMX_STATE_FREE;
                    547:         dvbdmxfeed->filter->state=DMX_STATE_FREE;
                    548:         if (dvbdmxfeed->pid!=0xffff) {
                    549:                 if (dvbdmxfeed->pid<=0x1fff) 
                    550:                         dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0;
                    551:                 dvbdmxfeed->pid=0xffff;
                    552:         }
                    553: 
                    554:         return 0;
                    555: }
                    556: 
                    557: 
                    558: /******************************************************************************
                    559:  * dmx_pes_feed API calls
                    560:  ******************************************************************************/
                    561: /*
                    562: static int 
                    563: dmx_pes_feed_set(struct dmx_pes_feed_s* feed,
                    564:                  __u16 pid,
                    565:                  size_t circular_buffer_size, 
                    566:                  int descramble, 
                    567:                  struct timespec timeout)
                    568: {
                    569:         return 0;
                    570: }
                    571: 
                    572: static int 
                    573: dmx_pes_feed_start_filtering(struct dmx_pes_feed_s* feed)
                    574: {
                    575:         return 0;
                    576: }
                    577:  
                    578: static int 
                    579: dmx_pes_feed_stop_filtering(struct dmx_pes_feed_s* feed)
                    580: {
                    581:         return 0;
                    582: }
                    583: */
                    584: 
                    585: static int dvbdmx_allocate_pes_feed(dmx_demux_t *demux, 
                    586:                                     dmx_pes_feed_t **feed,
                    587:                                     dmx_pes_cb callback)
                    588: {
                    589:         return 0;
                    590: }
                    591: 
                    592: static int dvbdmx_release_pes_feed(dmx_demux_t *demux, 
                    593:                                    dmx_pes_feed_t *feed)
                    594: {
                    595:         return 0;
                    596: }
                    597: 
                    598: 
                    599: /******************************************************************************
                    600:  * dmx_section_feed API calls
                    601:  ******************************************************************************/
                    602: 
                    603: static int 
                    604: dmx_section_feed_allocate_filter(struct dmx_section_feed_s* feed, 
                    605:                                  dmx_section_filter_t** filter) 
                    606: {
                    607:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    608:         dvb_demux_t *dvbdemux=dvbdmxfeed->demux;
                    609:         dvb_demux_filter_t *dvbdmxfilter;
                    610: 
                    611:         dvbdmxfilter=DvbDmxFilterAlloc(dvbdemux);
                    612:         if (!dvbdmxfilter)
                    613:                 return -ENOSPC;
                    614: 
                    615:         *filter=&dvbdmxfilter->filter;
                    616:         (*filter)->parent=feed;
                    617:         (*filter)->priv=0;
                    618:         dvbdmxfilter->feed=dvbdmxfeed;
                    619:         dvbdmxfilter->pid=dvbdmxfeed->pid; 
                    620:         dvbdmxfilter->type=DMX_TYPE_SEC;
                    621:         dvbdmxfilter->state=DMX_STATE_READY;
                    622: 
                    623:         dvbdmxfilter->next=dvbdmxfeed->filter;
                    624:         dvbdmxfeed->filter=dvbdmxfilter;
                    625:         return 0;
                    626: }
                    627: 
                    628: static int 
                    629: dmx_section_feed_set(struct dmx_section_feed_s* feed, 
                    630:                      __u16 pid, size_t circular_buffer_size, 
                    631:                      int descramble, int check_crc) 
                    632: {
                    633:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    634:         dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
                    635: 
                    636:         //printk ("function : %s  PID %04x\n", __FUNCTION__, pid);
                    637: 
                    638:         if (pid>0x1fff)
                    639:                 return -EINVAL;
                    640:         if (dvbdmxfeed->pid!=0xffff) {
                    641:                 dvbdmx->pid2feed[dvbdmxfeed->pid]=0;
                    642:                 dvbdmxfeed->pid=0xffff;
                    643:         }
                    644:         if (dvbdmx->pid2feed[pid])
                    645:                 return -EBUSY;
                    646:         dvbdmx->pid2feed[pid]=dvbdmxfeed;
                    647: 
                    648:         dvbdmxfeed->pid=pid;
                    649:         dvbdmxfeed->buffer_size=circular_buffer_size;
                    650:         dvbdmxfeed->descramble=descramble;
                    651:         if (dvbdmxfeed->descramble)
                    652:                 return -ENOSYS;
                    653: 
                    654:         dvbdmxfeed->check_crc=check_crc;
                    655:         dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size);
                    656:         if (!dvbdmxfeed->buffer)
                    657:                 return -ENOMEM;
                    658:         return 0;
                    659: }
                    660: 
                    661: static int 
                    662: dmx_section_feed_start_filtering(dmx_section_feed_t *feed)
                    663: {
                    664:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    665:         dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
                    666:        int ret;
                    667: 
                    668:         if (feed->is_filtering)
                    669:                 return -EBUSY;
                    670:         if (!dvbdmxfeed->filter)
                    671:                 return -EINVAL;
                    672: 
                    673:         dvbdmxfeed->secbufp=0;
                    674:         dvbdmxfeed->seclen=0;
                    675:         
                    676:         ret=dvbdmx->start_feed(dvbdmxfeed); 
                    677:        if (ret<0) 
                    678:                return ret;
                    679:         feed->is_filtering=1;
                    680:         dvbdmxfeed->state=DMX_STATE_GO;
                    681:        return 0;
                    682: }
                    683: 
                    684: static int 
                    685: dmx_section_feed_stop_filtering(struct dmx_section_feed_s* feed)
                    686: {
                    687:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    688:         dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
                    689:        int ret=dvbdmx->stop_feed(dvbdmxfeed); 
                    690: 
                    691:         dvbdmxfeed->state=DMX_STATE_READY;
                    692:         feed->is_filtering=0;
                    693:        return ret;
                    694: }
                    695: 
                    696: static int 
                    697: dmx_section_feed_release_filter(dmx_section_feed_t *feed, 
                    698:                                 dmx_section_filter_t* filter)
                    699: {
                    700:         dvb_demux_filter_t *dvbdmxfilter=(dvb_demux_filter_t *) filter, *f;
                    701:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    702: 
                    703:         if (dvbdmxfilter->feed!=dvbdmxfeed)
                    704:                 return -EINVAL;
                    705:         if (feed->is_filtering) 
1.2     ! mocm      706:                 feed->stop_filtering(feed);
        !           707:                 //return -EBUSY;
1.1       mocm      708: 
                    709:         f=dvbdmxfeed->filter;
                    710:         if (f==dvbdmxfeed->filter)
                    711:                 dvbdmxfeed->filter=dvbdmxfilter->next;
                    712:         else {
                    713:                 while(f->next!=dvbdmxfilter)
                    714:                         f=f->next;
                    715:                 f->next=f->next->next;
                    716:         }
                    717: 
                    718:         dvbdmxfilter->state=DMX_STATE_FREE;
                    719:         return 0;
                    720: }
                    721: 
                    722: static int dvbdmx_allocate_section_feed(dmx_demux_t *demux, 
                    723:                                         dmx_section_feed_t **feed,
                    724:                                         dmx_section_cb callback)
                    725: {
                    726:         dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
                    727:         dvb_demux_feed_t *dvbdmxfeed;
                    728: 
                    729:         if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx)))
                    730:                 return -EBUSY;
                    731:         dvbdmxfeed->type=DMX_TYPE_SEC;
                    732:         dvbdmxfeed->cb.sec=callback;
                    733:         dvbdmxfeed->demux=dvbdmx;
                    734:         dvbdmxfeed->pid=0xffff;
                    735:         dvbdmxfeed->secbufp=0;
                    736:         dvbdmxfeed->filter=0;
                    737: 
                    738:         (*feed)=&dvbdmxfeed->feed.sec;
                    739:         (*feed)->is_filtering=0;
                    740:         (*feed)->parent=demux;
                    741:         (*feed)->priv=0;
                    742:         (*feed)->set=dmx_section_feed_set;
                    743:         (*feed)->allocate_filter=dmx_section_feed_allocate_filter;
                    744:         (*feed)->release_filter=dmx_section_feed_release_filter;
                    745:         (*feed)->start_filtering=dmx_section_feed_start_filtering;
                    746:         (*feed)->stop_filtering=dmx_section_feed_stop_filtering;
                    747:         return 0;
                    748: }
                    749: 
                    750: static int dvbdmx_release_section_feed(dmx_demux_t *demux, 
                    751:                                        dmx_section_feed_t *feed)
                    752: {
                    753:         dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
                    754: 
                    755:         if (dvbdmxfeed->state==DMX_STATE_FREE)
                    756:                 return -EINVAL;
                    757:         if (dvbdmxfeed->buffer)
                    758:                 vfree(dvbdmxfeed->buffer);
                    759:         dvbdmxfeed->buffer=0;
                    760:         dvbdmxfeed->state=DMX_STATE_FREE;
                    761:         dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0;
                    762:         if (dvbdmxfeed->pid!=0xffff)
                    763:                 dvbdmxfeed->demux->pid2feed[dvbdmxfeed->pid]=0;
                    764:         return 0;
                    765: }
                    766: 
                    767: 
                    768: /******************************************************************************
                    769:  * dvb_demux kernel data API calls
                    770:  ******************************************************************************/
                    771: 
                    772: static int dvbdmx_open(struct dmx_demux_s *demux)
                    773: {
                    774:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    775: 
                    776:         if (dvbdemux->users>=MAX_DVB_DEMUX_USERS)
                    777:                 return -EUSERS;
                    778:         dvbdemux->users++;
                    779:         return 0;
                    780: }
                    781: 
                    782: static int dvbdmx_close(struct dmx_demux_s *demux)
                    783: {
                    784:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    785: 
                    786:         if (dvbdemux->users==0)
                    787:                 return -ENODEV;
                    788:         dvbdemux->users--;
                    789:         //FIXME: release any unneeded resources if users==0
                    790:         return 0;
                    791: }
                    792: 
                    793: static int dvbdmx_write(dmx_demux_t *demux, const char *buf, size_t count)
                    794: {
                    795:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    796: 
                    797:         if ((!demux->frontend) ||
                    798:             (demux->frontend->source!=DMX_MEMORY_FE))
                    799:                 return -EINVAL;
                    800: 
                    801:         DvbDmxSWFilter(dvbdemux, buf, count);
                    802:         return count;
                    803: }
                    804: 
                    805: 
                    806: static int dvbdmx_add_frontend(dmx_demux_t *demux, 
                    807:                                dmx_frontend_t *frontend)
                    808: {
                    809:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    810:         struct list_head *pos, *head=&dvbdemux->frontend_list;
                    811:        
                    812:         //printk ("function : %s\n", __FUNCTION__);
                    813: 
                    814:        if (!(frontend->id && frontend->vendor && frontend->model)) 
                    815:                return -EINVAL;
                    816:        list_for_each(pos, head) 
                    817:        {
                    818:                if (!strcmp(DMX_FE_ENTRY(pos)->id, frontend->id))
                    819:                        return -EEXIST;
                    820:        }
                    821: 
                    822:        list_add(&(frontend->connectivity_list), head);
                    823:         return 0;
                    824: }
                    825: 
                    826: static int 
                    827: dvbdmx_remove_frontend(dmx_demux_t *demux, 
                    828:                        dmx_frontend_t *frontend)
                    829: {
                    830:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    831:         struct list_head *pos, *head=&dvbdemux->frontend_list;
                    832: 
                    833:        list_for_each(pos, head) 
                    834:        {
                    835:                if (DMX_FE_ENTRY(pos)==frontend) 
                    836:                 {
                    837:                        list_del(pos);
                    838:                        return 0;
                    839:                }
                    840:        }
                    841:        return -ENODEV;
                    842: }
                    843: 
                    844: static struct list_head *
                    845: dvbdmx_get_frontends(dmx_demux_t *demux)
                    846: {
                    847:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    848: 
                    849:         if (list_empty(&dvbdemux->frontend_list))
                    850:                return NULL;
                    851:         return &dvbdemux->frontend_list;
                    852: }
                    853: 
                    854: static int dvbdmx_connect_frontend(dmx_demux_t *demux, 
                    855:                                    dmx_frontend_t *frontend)
                    856: {
                    857:         if (demux->frontend)
                    858:                 return -EINVAL;
                    859:         
                    860:         demux->frontend=frontend;
                    861:         return 0;
                    862: }
                    863: 
                    864: static int dvbdmx_disconnect_frontend(dmx_demux_t *demux)
                    865: {
                    866:         demux->frontend=NULL;
                    867:         return 0;
                    868: }
                    869: 
                    870: static int dvbdmx_get_pes_pids(dmx_demux_t *demux, __u16 *pids)
                    871: {
                    872:         dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
                    873: 
                    874:         memcpy(pids, dvbdemux->pids, 5*sizeof(__u16));
                    875:         return 0;
                    876: }
                    877: 
                    878: int 
                    879: DvbDmxInit(dvb_demux_t *dvbdemux, char *id, char *vendor, char *model)
                    880: {
                    881:         dmx_demux_t *dmx=&dvbdemux->dmx;
                    882:         int i;
                    883: 
                    884:        dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(dvb_demux_filter_t));
                    885:        if (!dvbdemux->filter)
                    886:                 return -ENOMEM;
                    887:         
                    888:        dvbdemux->start_feed=0;
                    889:        dvbdemux->stop_feed=0;
                    890:        dvbdemux->write_to_decoder=0;
                    891:         dvbdemux->frontend_list.next=
                    892:           dvbdemux->frontend_list.prev=
                    893:             &dvbdemux->frontend_list;
                    894:         dvbdemux->users=0;
                    895: 
                    896:         for (i=0; i<DVB_DEMUX_FILTER_MAX; i++) {
                    897:                 dvbdemux->filter[i].state=DMX_STATE_FREE;
                    898:                 dvbdemux->filter[i].index=i;
                    899:         }
                    900:         for (i=0; i<DVB_DEMUX_FEED_MAX; i++)
                    901:                 dvbdemux->feed[i].state=DMX_STATE_FREE;
                    902:         for (i=0; i<DMX_TS_PES_OTHER; i++) {
                    903:                 dvbdemux->pesfilter[i]=NULL;
                    904:                 dvbdemux->pids[i]=0xffff;
                    905:        }
                    906:         dvbdemux->playing=dvbdemux->recording=0;
                    907:         memset(dvbdemux->pid2feed, 0, 0x2000*sizeof(dvb_demux_feed_t *));
                    908:         dvbdemux->tsbufp=0;
                    909: 
                    910:         dmx->id=id;
                    911:         dmx->vendor=vendor;
                    912:         dmx->model=model;
                    913:         dmx->frontend=0;
                    914:         dmx->reg_list.next=dmx->reg_list.prev=&dmx->reg_list;
                    915:         dmx->priv=(void *) dvbdemux;
                    916:         dmx->open=dvbdmx_open;
                    917:         dmx->close=dvbdmx_close;
                    918:         dmx->write=dvbdmx_write;
                    919:         dmx->allocate_ts_feed=dvbdmx_allocate_ts_feed;
                    920:         dmx->release_ts_feed=dvbdmx_release_ts_feed;
                    921:         dmx->allocate_pes_feed=dvbdmx_allocate_pes_feed;
                    922:         dmx->release_pes_feed=dvbdmx_release_pes_feed;
                    923:         dmx->allocate_section_feed=dvbdmx_allocate_section_feed;
                    924:         dmx->release_section_feed=dvbdmx_release_section_feed;
                    925: 
                    926:         dmx->descramble_mac_address=NULL;
                    927:         dmx->descramble_section_payload=NULL;
                    928:         
                    929:         dmx->add_frontend=dvbdmx_add_frontend;
                    930:         dmx->remove_frontend=dvbdmx_remove_frontend;
                    931:         dmx->get_frontends=dvbdmx_get_frontends;
                    932:         dmx->connect_frontend=dvbdmx_connect_frontend;
                    933:         dmx->disconnect_frontend=dvbdmx_disconnect_frontend;
                    934:         dmx->get_pes_pids=dvbdmx_get_pes_pids;
                    935: 
                    936:         if (dmx_register_demux(dmx)<0) 
                    937:                 return -1;
                    938:         if (dmx->open(dmx)<0)
                    939:                 return -1;
                    940:         return 0;
                    941: }
                    942: 
                    943: int 
                    944: DvbDmxRelease(dvb_demux_t *dvbdemux)
                    945: {
                    946:         dmx_demux_t *dmx=&dvbdemux->dmx;
                    947: 
                    948:         dmx_unregister_demux(dmx);
                    949:        if (dvbdemux->filter)
                    950:                 vfree(dvbdemux->filter);
                    951:         return 0;
                    952: }
                    953: 
                    954: /*
                    955:  * Local variables:
                    956:  * c-indent-level: 8
                    957:  * c-brace-imaginary-offset: 0
                    958:  * c-brace-offset: -8
                    959:  * c-argdecl-indent: 8
                    960:  * c-label-offset: -8
                    961:  * c-continued-statement-offset: 8
                    962:  * c-continued-brace-offset: 0
                    963:  * indent-tabs-mode: nil
                    964:  * tab-width: 8
                    965:  * End:
                    966:  */

LinuxTV legacy CVS <linuxtv.org/cvs>