X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmedia%2Fdvb%2Fdvb-core%2Fdvb_demux.c;h=ac9889d222882bc6629d5a2c90b7405496d8f740;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=657d5579b16b6e9c4679c90a11cdfcf88ad426c8;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index 657d5579b..ac9889d22 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -1,4 +1,4 @@ -/* +/* * dvb_demux.c - DVB kernel demux API * * Copyright (C) 2000-2001 Ralph Metzler @@ -27,30 +27,29 @@ #include #include #include - #include +#include #include #include "dvb_demux.h" -#include "dvb_functions.h" -#define NOBUFS -/* +#define NOBUFS +/* ** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog */ // #define DVB_DEMUX_SECTION_LOSS_LOG -LIST_HEAD(dmx_muxs); +static LIST_HEAD(dmx_muxs); -int dmx_register_demux(struct dmx_demux *demux) +static int dmx_register_demux(struct dmx_demux *demux) { demux->users = 0; list_add(&demux->reg_list, &dmx_muxs); return 0; } -int dmx_unregister_demux(struct dmx_demux* demux) +static int dmx_unregister_demux(struct dmx_demux* demux) { struct list_head *pos, *n, *head=&dmx_muxs; @@ -67,14 +66,6 @@ int dmx_unregister_demux(struct dmx_demux* demux) } -struct list_head *dmx_get_demuxes(void) -{ - if (list_empty(&dmx_muxs)) - return NULL; - - return &dmx_muxs; -} - /****************************************************************************** * static inlined helper functions ******************************************************************************/ @@ -94,10 +85,10 @@ static inline u16 ts_pid(const u8 *buf) static inline u8 payload(const u8 *tsp) { - if (!(tsp[3]&0x10)) // no payload? + if (!(tsp[3] & 0x10)) // no payload? return 0; - if (tsp[3]&0x20) { // adaptation field? - if (tsp[4]>183) // corrupted data? + if (tsp[3] & 0x20) { // adaptation field? + if (tsp[4] > 183) // corrupted data? return 0; else return 184-1-tsp[4]; @@ -106,19 +97,6 @@ static inline u8 payload(const u8 *tsp) } -void dvb_set_crc32(u8 *data, int length) -{ - u32 crc; - - crc = crc32_be(~0, data, length); - - data[length] = (crc >> 24) & 0xff; - data[length+1] = (crc >> 16) & 0xff; - data[length+2] = (crc >> 8) & 0xff; - data[length+3] = (crc) & 0xff; -} - - static u32 dvb_dmx_crc32 (struct dvb_demux_feed *f, const u8 *src, size_t len) { return (f->feed.sec.crc_val = crc32_be (f->feed.sec.crc_val, src, len)); @@ -135,7 +113,7 @@ static void dvb_dmx_memcopy (struct dvb_demux_feed *f, u8 *d, const u8 *s, size_ * Software filter functions ******************************************************************************/ -static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u8 *buf) +static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u8 *buf) { int count = payload(buf); int p; @@ -160,11 +138,11 @@ static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u feed->peslen += count; - return feed->cb.ts (&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK); + return feed->cb.ts (&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK); } -static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed, +static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed, struct dvb_demux_filter *f) { u8 neq = 0; @@ -182,8 +160,8 @@ static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed, if (f->doneq && !neq) return 0; - return feed->cb.sec (feed->feed.sec.secbuf, feed->feed.sec.seclen, - NULL, 0, &f->filter, DMX_OK); + return feed->cb.sec (feed->feed.sec.secbuf, feed->feed.sec.seclen, + NULL, 0, &f->filter, DMX_OK); } @@ -204,7 +182,7 @@ static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed) section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0); if (section_syntax_indicator && demux->check_crc32(feed, sec->secbuf, sec->seclen)) - return -1; + return -1; } do { @@ -233,22 +211,37 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) */ if(sec->secbuf[0] != 0xff || sec->secbuf[n-1] != 0xff) { - printk("dvb_demux.c section ts padding loss: %d/%d\n", + printk("dvb_demux.c section ts padding loss: %d/%d\n", n, sec->tsfeedp); printk("dvb_demux.c pad data:"); for(i = 0; i < n; i++) printk(" %02x", sec->secbuf[i]); printk("\n"); - } - } + } + } #endif sec->tsfeedp = sec->secbufp = sec->seclen = 0; sec->secbuf = sec->secbuf_base; - } +} -/* -** Losless Section Demux 1.4 by Emard +/* +** Losless Section Demux 1.4.1 by Emard +** Valsecchi Patrick: +** - middle of section A (no PUSI) +** - end of section A and start of section B +** (with PUSI pointing to the start of the second section) +** +** In this case, without feed->pusi_seen you'll receive a garbage section +** consisting of the end of section A. Basically because tsfeedp +** is incemented and the use=0 condition is not raised +** when the second packet arrives. +** +** Fix: +** when demux is started, let feed->pusi_seen = 0 to +** prevent initial feeding of garbage from the end of +** previous section. When you for the first time see PUSI=1 +** then set feed->pusi_seen = 1 */ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const u8 *buf, u8 len) { @@ -262,7 +255,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const if(sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) { #ifdef DVB_DEMUX_SECTION_LOSS_LOG - printk("dvb_demux.c section buffer full loss: %d/%d\n", + printk("dvb_demux.c section buffer full loss: %d/%d\n", sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, DMX_MAX_SECFEED_SIZE); #endif len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp; @@ -288,71 +281,84 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const for(n = 0; sec->secbufp + 2 < limit; n++) { seclen = section_length(sec->secbuf); - if(seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE + if(seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE || seclen + sec->secbufp > limit) return 0; sec->seclen = seclen; sec->crc_val = ~0; /* dump [secbuf .. secbuf+seclen) */ - dvb_dmx_swfilter_section_feed(feed); + if(feed->pusi_seen) + dvb_dmx_swfilter_section_feed(feed); +#ifdef DVB_DEMUX_SECTION_LOSS_LOG + else + printk("dvb_demux.c pusi not seen, discarding section data\n"); +#endif sec->secbufp += seclen; /* secbufp and secbuf moving together is */ sec->secbuf += seclen; /* redundand but saves pointer arithmetic */ - } - - return 0; } + return 0; +} + -static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf) +static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf) { u8 p, count; - int ccok; + int ccok, dc_i = 0; u8 cc; count = payload(buf); - + if (count == 0) /* count == 0 if no payload or out of range */ - return -1; + return -1; - p = 188-count; /* payload start */ + p = 188 - count; /* payload start */ cc = buf[3] & 0x0f; - ccok = ((feed->cc+1) & 0x0f) == cc ? 1 : 0; + ccok = ((feed->cc + 1) & 0x0f) == cc; feed->cc = cc; - if(ccok == 0) - { + + if (buf[3] & 0x20) { + /* adaption field present, check for discontinuity_indicator */ + if ((buf[4] > 0) && (buf[5] & 0x80)) + dc_i = 1; + } + + if (!ccok || dc_i) { #ifdef DVB_DEMUX_SECTION_LOSS_LOG printk("dvb_demux.c discontinuity detected %d bytes lost\n", count); /* those bytes under sume circumstances will again be reported ** in the following dvb_dmx_swfilter_section_new */ #endif + /* Discontinuity detected. Reset pusi_seen = 0 to + ** stop feeding of suspicious data until next PUSI=1 arrives + */ + feed->pusi_seen = 0; dvb_dmx_swfilter_section_new(feed); return 0; } - if(buf[1] & 0x40) - { + if (buf[1] & 0x40) { // PUSI=1 (is set), section boundary is here - if(count > 1 && buf[p] < count) - { + if (count > 1 && buf[p] < count) { const u8 *before = buf+p+1; u8 before_len = buf[p]; const u8 *after = before+before_len; u8 after_len = count-1-before_len; dvb_dmx_swfilter_section_copy_dump(feed, before, before_len); + /* before start of new section, set pusi_seen = 1 */ + feed->pusi_seen = 1; dvb_dmx_swfilter_section_new(feed); dvb_dmx_swfilter_section_copy_dump(feed, after, after_len); } #ifdef DVB_DEMUX_SECTION_LOSS_LOG else - if(count > 0) + if (count > 0) printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count); #endif - } - else - { + } else { // PUSI=0 (is not set), no section boundary const u8 *entire = buf+p; u8 entire_len = count; @@ -373,9 +379,9 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con if (feed->ts_type & TS_PAYLOAD_ONLY) dvb_dmx_swfilter_payload(feed, buf); else - feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK); + feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK); } - if (feed->ts_type & TS_DECODER) + if (feed->ts_type & TS_DECODER) if (feed->demux->write_to_decoder) feed->demux->write_to_decoder(feed, buf, 188); break; @@ -397,7 +403,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con ((f)->feed.ts.is_filtering) && \ (((f)->ts_type & (TS_PACKET|TS_PAYLOAD_ONLY)) == TS_PACKET)) -void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) +static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) { struct dvb_demux_feed *feed; struct list_head *pos, *head=&demux->feed_list; @@ -416,7 +422,7 @@ void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) continue; if (feed->pid == pid) { - dvb_dmx_swfilter_packet_type (feed, buf); + dvb_dmx_swfilter_packet_type(feed, buf); if (DVR_FEED(feed)) continue; } @@ -426,26 +432,26 @@ void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) } } - void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count) { spin_lock(&demux->lock); while (count--) { - if(buf[0] == 0x47) { - dvb_dmx_swfilter_packet(demux, buf); + if(buf[0] == 0x47) { + dvb_dmx_swfilter_packet(demux, buf); } buf += 188; } spin_unlock(&demux->lock); } +EXPORT_SYMBOL(dvb_dmx_swfilter_packets); void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) { - int p = 0,i, j; - + int p = 0, i, j; + spin_lock(&demux->lock); if ((i = demux->tsbufp)) { @@ -456,7 +462,7 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) } memcpy(&demux->tsbuf[i], buf, j); if (demux->tsbuf[0] == 0x47) - dvb_dmx_swfilter_packet(demux, demux->tsbuf); + dvb_dmx_swfilter_packet(demux, demux->tsbuf); demux->tsbufp = 0; p += j; } @@ -472,13 +478,14 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) demux->tsbufp=i; goto bailout; } - } else + } else p++; } bailout: spin_unlock(&demux->lock); } +EXPORT_SYMBOL(dvb_dmx_swfilter); void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) { @@ -515,7 +522,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) demux->tsbufp=i; goto bailout; } - } else { + } else { p++; } } @@ -523,6 +530,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) bailout: spin_unlock(&demux->lock); } +EXPORT_SYMBOL(dvb_dmx_swfilter_204); static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux) @@ -565,34 +573,40 @@ static int dvb_demux_feed_find(struct dvb_demux_feed *feed) if (entry == feed) return 1; - return 0; - } + return 0; +} static void dvb_demux_feed_add(struct dvb_demux_feed *feed) { + spin_lock_irq(&feed->demux->lock); if (dvb_demux_feed_find(feed)) { printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n", __FUNCTION__, feed->type, feed->state, feed->pid); - return; + goto out; } list_add(&feed->list_head, &feed->demux->feed_list); +out: + spin_unlock_irq(&feed->demux->lock); } static void dvb_demux_feed_del(struct dvb_demux_feed *feed) { + spin_lock_irq(&feed->demux->lock); if (!(dvb_demux_feed_find(feed))) { printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n", __FUNCTION__, feed->type, feed->state, feed->pid); - return; -} + goto out; + } list_del(&feed->list_head); +out: + spin_unlock_irq(&feed->demux->lock); } -static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type, - enum dmx_ts_pes pes_type, size_t callback_length, - size_t circular_buffer_size, int descramble, +static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type, + enum dmx_ts_pes pes_type, size_t callback_length, + size_t circular_buffer_size, int descramble, struct timespec timeout) { struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed; @@ -600,7 +614,7 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type, if (pid > DMX_MAX_PID) return -EINVAL; - + if (down_interruptible (&demux->mutex)) return -ERESTARTSYS; @@ -610,7 +624,7 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type, return -EINVAL; } - if (demux->pesfilter[pes_type] && + if (demux->pesfilter[pes_type] && demux->pesfilter[pes_type] != feed) { up(&demux->mutex); return -EINVAL; @@ -646,7 +660,7 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type, } #endif } - + feed->state = DMX_STATE_READY; up(&demux->mutex); @@ -686,7 +700,7 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed* ts_feed) return 0; } - + static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed) { struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed; @@ -696,7 +710,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed) if (down_interruptible (&demux->mutex)) return -ERESTARTSYS; - if (feed->statestate < DMX_STATE_GO) { up(&demux->mutex); return -EINVAL; } @@ -706,7 +720,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed) return -ENODEV; } - ret = demux->stop_feed(feed); + ret = demux->stop_feed(feed); spin_lock_irq(&demux->lock); ts_feed->is_filtering = 0; @@ -717,7 +731,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed) return ret; } -static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **ts_feed, +static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **ts_feed, dmx_ts_cb callback) { struct dvb_demux *demux = (struct dvb_demux *) dmx; @@ -756,7 +770,7 @@ static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed ** feed->filter->type = DMX_TYPE_TS; feed->filter->feed = feed; feed->filter->state = DMX_STATE_READY; - + up(&demux->mutex); return 0; @@ -776,10 +790,8 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_ } #ifndef NOBUFS - if (feed->buffer) { - vfree(feed->buffer); - feed->buffer=0; - } + vfree(feed->buffer); + feed->buffer=0; #endif feed->state = DMX_STATE_FREE; @@ -787,9 +799,9 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_ dvb_demux_feed_del(feed); - feed->pid = 0xffff; - - if (feed->ts_type & TS_DECODER) + feed->pid = 0xffff; + + if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER) demux->pesfilter[feed->pes_type] = NULL; up(&demux->mutex); @@ -801,64 +813,65 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_ * dmx_section_feed API calls ******************************************************************************/ -static int dmx_section_feed_allocate_filter(struct dmx_section_feed* feed, - struct dmx_section_filter** filter) +static int dmx_section_feed_allocate_filter(struct dmx_section_feed* feed, + struct dmx_section_filter** filter) { - struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; - struct dvb_demux *dvbdemux=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdemux = dvbdmxfeed->demux; struct dvb_demux_filter *dvbdmxfilter; if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; - dvbdmxfilter=dvb_dmx_filter_alloc(dvbdemux); + dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux); if (!dvbdmxfilter) { up(&dvbdemux->mutex); return -EBUSY; } spin_lock_irq(&dvbdemux->lock); - *filter=&dvbdmxfilter->filter; - (*filter)->parent=feed; - (*filter)->priv=NULL; - dvbdmxfilter->feed=dvbdmxfeed; - dvbdmxfilter->type=DMX_TYPE_SEC; - dvbdmxfilter->state=DMX_STATE_READY; - - dvbdmxfilter->next=dvbdmxfeed->filter; - dvbdmxfeed->filter=dvbdmxfilter; + *filter = &dvbdmxfilter->filter; + (*filter)->parent = feed; + (*filter)->priv = NULL; + dvbdmxfilter->feed = dvbdmxfeed; + dvbdmxfilter->type = DMX_TYPE_SEC; + dvbdmxfilter->state = DMX_STATE_READY; + dvbdmxfilter->next = dvbdmxfeed->filter; + dvbdmxfeed->filter = dvbdmxfilter; spin_unlock_irq(&dvbdemux->lock); + up(&dvbdemux->mutex); return 0; } -static int dmx_section_feed_set(struct dmx_section_feed* feed, - u16 pid, size_t circular_buffer_size, - int descramble, int check_crc) +static int dmx_section_feed_set(struct dmx_section_feed* feed, + u16 pid, size_t circular_buffer_size, + int descramble, int check_crc) { - struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; - struct dvb_demux *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - if (pid>0x1fff) + if (pid > 0x1fff) return -EINVAL; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; - + dvb_demux_feed_add(dvbdmxfeed); dvbdmxfeed->pid = pid; - dvbdmxfeed->buffer_size=circular_buffer_size; - dvbdmxfeed->descramble=descramble; + dvbdmxfeed->buffer_size = circular_buffer_size; + dvbdmxfeed->descramble = descramble; if (dvbdmxfeed->descramble) { up(&dvbdmx->mutex); return -ENOSYS; } - dvbdmxfeed->feed.sec.check_crc=check_crc; + dvbdmxfeed->feed.sec.check_crc = check_crc; + #ifdef NOBUFS - dvbdmxfeed->buffer=NULL; + dvbdmxfeed->buffer = NULL; #else dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size); if (!dvbdmxfeed->buffer) { @@ -866,47 +879,50 @@ static int dmx_section_feed_set(struct dmx_section_feed* feed, return -ENOMEM; } #endif - dvbdmxfeed->state=DMX_STATE_READY; + + dvbdmxfeed->state = DMX_STATE_READY; up(&dvbdmx->mutex); return 0; } + static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed) { int i; struct dvb_demux_filter *f; struct dmx_section_filter *sf; u8 mask, mode, doneq; - + if (!(f=dvbdmxfeed->filter)) return; do { - sf=&f->filter; - doneq=0; + sf = &f->filter; + doneq = 0; for (i=0; ifilter_mode[i]; - mask=sf->filter_mask[i]; - f->maskandmode[i]=mask&mode; - doneq|=f->maskandnotmode[i]=mask&~mode; + mode = sf->filter_mode[i]; + mask = sf->filter_mask[i]; + f->maskandmode[i] = mask & mode; + doneq |= f->maskandnotmode[i] = mask & ~mode; } - f->doneq=doneq ? 1 : 0; - } while ((f=f->next)); + f->doneq = doneq ? 1 : 0; + } while ((f = f->next)); } static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) { - struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; - struct dvb_demux *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; - + if (feed->is_filtering) { up(&dvbdmx->mutex); return -EBUSY; } + if (!dvbdmxfeed->filter) { up(&dvbdmx->mutex); return -EINVAL; @@ -914,9 +930,9 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) dvbdmxfeed->feed.sec.tsfeedp = 0; dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; - dvbdmxfeed->feed.sec.secbufp=0; - dvbdmxfeed->feed.sec.seclen=0; - + dvbdmxfeed->feed.sec.secbufp = 0; + dvbdmxfeed->feed.sec.seclen = 0; + if (!dvbdmx->start_feed) { up(&dvbdmx->mutex); return -ENODEV; @@ -930,9 +946,10 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) } spin_lock_irq(&dvbdmx->lock); - feed->is_filtering=1; - dvbdmxfeed->state=DMX_STATE_GO; + feed->is_filtering = 1; + dvbdmxfeed->state = DMX_STATE_GO; spin_unlock_irq(&dvbdmx->lock); + up(&dvbdmx->mutex); return 0; } @@ -940,8 +957,8 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) static int dmx_section_feed_stop_filtering(struct dmx_section_feed* feed) { - struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; - struct dvb_demux *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) @@ -951,93 +968,99 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed* feed) up(&dvbdmx->mutex); return -ENODEV; } - ret=dvbdmx->stop_feed(dvbdmxfeed); + + ret = dvbdmx->stop_feed(dvbdmxfeed); + spin_lock_irq(&dvbdmx->lock); - dvbdmxfeed->state=DMX_STATE_READY; - feed->is_filtering=0; + dvbdmxfeed->state = DMX_STATE_READY; + feed->is_filtering = 0; spin_unlock_irq(&dvbdmx->lock); + up(&dvbdmx->mutex); return ret; } -static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, +static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, struct dmx_section_filter* filter) { - struct dvb_demux_filter *dvbdmxfilter=(struct dvb_demux_filter *) filter, *f; - struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; - struct dvb_demux *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *) filter, *f; + struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; - if (dvbdmxfilter->feed!=dvbdmxfeed) { + if (dvbdmxfilter->feed != dvbdmxfeed) { up(&dvbdmx->mutex); return -EINVAL; } - if (feed->is_filtering) + + if (feed->is_filtering) feed->stop_filtering(feed); - + spin_lock_irq(&dvbdmx->lock); - f=dvbdmxfeed->filter; + f = dvbdmxfeed->filter; if (f == dvbdmxfilter) { - dvbdmxfeed->filter=dvbdmxfilter->next; + dvbdmxfeed->filter = dvbdmxfilter->next; } else { - while(f->next!=dvbdmxfilter) - f=f->next; - f->next=f->next->next; + while(f->next != dvbdmxfilter) + f = f->next; + f->next = f->next->next; } - dvbdmxfilter->state=DMX_STATE_FREE; + + dvbdmxfilter->state = DMX_STATE_FREE; spin_unlock_irq(&dvbdmx->lock); up(&dvbdmx->mutex); return 0; } -static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, +static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, struct dmx_section_feed **feed, dmx_section_cb callback) { - struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; + struct dvb_demux *dvbdmx = (struct dvb_demux *) demux; struct dvb_demux_feed *dvbdmxfeed; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; - if (!(dvbdmxfeed=dvb_dmx_feed_alloc(dvbdmx))) { + if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) { up(&dvbdmx->mutex); return -EBUSY; } - dvbdmxfeed->type=DMX_TYPE_SEC; - dvbdmxfeed->cb.sec=callback; - dvbdmxfeed->demux=dvbdmx; - dvbdmxfeed->pid=0xffff; + + dvbdmxfeed->type = DMX_TYPE_SEC; + dvbdmxfeed->cb.sec = callback; + dvbdmxfeed->demux = dvbdmx; + dvbdmxfeed->pid = 0xffff; dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; dvbdmxfeed->feed.sec.tsfeedp = 0; - dvbdmxfeed->filter=NULL; - dvbdmxfeed->buffer=NULL; + dvbdmxfeed->filter = NULL; + dvbdmxfeed->buffer = NULL; (*feed)=&dvbdmxfeed->feed.sec; - (*feed)->is_filtering=0; - (*feed)->parent=demux; - (*feed)->priv=NULL; - - (*feed)->set=dmx_section_feed_set; - (*feed)->allocate_filter=dmx_section_feed_allocate_filter; - (*feed)->start_filtering=dmx_section_feed_start_filtering; - (*feed)->stop_filtering=dmx_section_feed_stop_filtering; + (*feed)->is_filtering = 0; + (*feed)->parent = demux; + (*feed)->priv = NULL; + + (*feed)->set = dmx_section_feed_set; + (*feed)->allocate_filter = dmx_section_feed_allocate_filter; + (*feed)->start_filtering = dmx_section_feed_start_filtering; + (*feed)->stop_filtering = dmx_section_feed_stop_filtering; (*feed)->release_filter = dmx_section_feed_release_filter; up(&dvbdmx->mutex); return 0; } -static int dvbdmx_release_section_feed(struct dmx_demux *demux, +static int dvbdmx_release_section_feed(struct dmx_demux *demux, struct dmx_section_feed *feed) { - struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; - struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; + struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx = (struct dvb_demux *) demux; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; @@ -1047,16 +1070,14 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux, return -EINVAL; } #ifndef NOBUFS - if (dvbdmxfeed->buffer) { - vfree(dvbdmxfeed->buffer); - dvbdmxfeed->buffer=0; - } + vfree(dvbdmxfeed->buffer); + dvbdmxfeed->buffer=0; #endif dvbdmxfeed->state=DMX_STATE_FREE; dvb_demux_feed_del(dvbdmxfeed); - dvbdmxfeed->pid = 0xffff; + dvbdmxfeed->pid = 0xffff; up(&dvbdmx->mutex); return 0; @@ -1069,10 +1090,11 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux, static int dvbdmx_open(struct dmx_demux *demux) { - struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; + struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; - if (dvbdemux->users>=MAX_DVB_DEMUX_USERS) + if (dvbdemux->users >= MAX_DVB_DEMUX_USERS) return -EUSERS; + dvbdemux->users++; return 0; } @@ -1080,10 +1102,11 @@ static int dvbdmx_open(struct dmx_demux *demux) static int dvbdmx_close(struct dmx_demux *demux) { - struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; + struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; - if (dvbdemux->users==0) + if (dvbdemux->users == 0) return -ENODEV; + dvbdemux->users--; //FIXME: release any unneeded resources if users==0 return 0; @@ -1110,7 +1133,7 @@ static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count) static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend) { - struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; + struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; struct list_head *head = &dvbdemux->frontend_list; list_add(&(frontend->connectivity_list), head); @@ -1121,8 +1144,8 @@ static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *fro static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend) { - struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; - struct list_head *pos, *n, *head=&dvbdemux->frontend_list; + struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; + struct list_head *pos, *n, *head = &dvbdemux->frontend_list; list_for_each_safe (pos, n, head) { if (DMX_FE_ENTRY(pos) == frontend) { @@ -1130,13 +1153,14 @@ static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend * return 0; } } + return -ENODEV; } static struct list_head * dvbdmx_get_frontends(struct dmx_demux *demux) { - struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; + struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; if (list_empty(&dvbdemux->frontend_list)) return NULL; @@ -1144,30 +1168,30 @@ static struct list_head * dvbdmx_get_frontends(struct dmx_demux *demux) } -int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend) +static int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend) { - struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; + struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; if (demux->frontend) return -EINVAL; - + if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; - demux->frontend=frontend; + demux->frontend = frontend; up(&dvbdemux->mutex); return 0; } -int dvbdmx_disconnect_frontend(struct dmx_demux *demux) +static int dvbdmx_disconnect_frontend(struct dmx_demux *demux) { - struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; + struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; - demux->frontend=NULL; + demux->frontend = NULL; up(&dvbdemux->mutex); return 0; } @@ -1175,7 +1199,7 @@ int dvbdmx_disconnect_frontend(struct dmx_demux *demux) static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids) { - struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; + struct dvb_demux *dvbdemux = (struct dvb_demux *) demux; memcpy(pids, dvbdemux->pids, 5*sizeof(u16)); return 0; @@ -1187,35 +1211,38 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) int i, err; struct dmx_demux *dmx = &dvbdemux->dmx; - dvbdemux->users=0; - dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter)); + dvbdemux->users = 0; + dvbdemux->filter = vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter)); + if (!dvbdemux->filter) return -ENOMEM; - dvbdemux->feed=vmalloc(dvbdemux->feednum*sizeof(struct dvb_demux_feed)); + dvbdemux->feed = vmalloc(dvbdemux->feednum*sizeof(struct dvb_demux_feed)); if (!dvbdemux->feed) { vfree(dvbdemux->filter); return -ENOMEM; } for (i=0; ifilternum; i++) { - dvbdemux->filter[i].state=DMX_STATE_FREE; - dvbdemux->filter[i].index=i; + dvbdemux->filter[i].state = DMX_STATE_FREE; + dvbdemux->filter[i].index = i; + } + for (i=0; ifeednum; i++) { + dvbdemux->feed[i].state = DMX_STATE_FREE; + dvbdemux->feed[i].index = i; } - for (i=0; ifeednum; i++) - dvbdemux->feed[i].state=DMX_STATE_FREE; dvbdemux->frontend_list.next= dvbdemux->frontend_list.prev= &dvbdemux->frontend_list; for (i=0; ipesfilter[i]=NULL; - dvbdemux->pids[i]=0xffff; + dvbdemux->pesfilter[i] = NULL; + dvbdemux->pids[i] = 0xffff; } INIT_LIST_HEAD(&dvbdemux->feed_list); dvbdemux->playing = 0; dvbdemux->recording = 0; - dvbdemux->tsbufp=0; + dvbdemux->tsbufp = 0; if (!dvbdemux->check_crc32) dvbdemux->check_crc32 = dvb_dmx_crc32; @@ -1223,34 +1250,36 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) if (!dvbdemux->memcopy) dvbdemux->memcopy = dvb_dmx_memcopy; - dmx->frontend=NULL; + dmx->frontend = NULL; dmx->reg_list.prev = dmx->reg_list.next = &dmx->reg_list; - dmx->priv=(void *) dvbdemux; - dmx->open=dvbdmx_open; - dmx->close=dvbdmx_close; - dmx->write=dvbdmx_write; - dmx->allocate_ts_feed=dvbdmx_allocate_ts_feed; - dmx->release_ts_feed=dvbdmx_release_ts_feed; - dmx->allocate_section_feed=dvbdmx_allocate_section_feed; - dmx->release_section_feed=dvbdmx_release_section_feed; - - dmx->descramble_mac_address=NULL; - dmx->descramble_section_payload=NULL; - - dmx->add_frontend=dvbdmx_add_frontend; - dmx->remove_frontend=dvbdmx_remove_frontend; - dmx->get_frontends=dvbdmx_get_frontends; - dmx->connect_frontend=dvbdmx_connect_frontend; - dmx->disconnect_frontend=dvbdmx_disconnect_frontend; - dmx->get_pes_pids=dvbdmx_get_pes_pids; + dmx->priv = (void *) dvbdemux; + dmx->open = dvbdmx_open; + dmx->close = dvbdmx_close; + dmx->write = dvbdmx_write; + dmx->allocate_ts_feed = dvbdmx_allocate_ts_feed; + dmx->release_ts_feed = dvbdmx_release_ts_feed; + dmx->allocate_section_feed = dvbdmx_allocate_section_feed; + dmx->release_section_feed = dvbdmx_release_section_feed; + + dmx->descramble_mac_address = NULL; + dmx->descramble_section_payload = NULL; + + dmx->add_frontend = dvbdmx_add_frontend; + dmx->remove_frontend = dvbdmx_remove_frontend; + dmx->get_frontends = dvbdmx_get_frontends; + dmx->connect_frontend = dvbdmx_connect_frontend; + dmx->disconnect_frontend = dvbdmx_disconnect_frontend; + dmx->get_pes_pids = dvbdmx_get_pes_pids; + sema_init(&dvbdemux->mutex, 1); spin_lock_init(&dvbdemux->lock); - if ((err = dmx_register_demux(dmx)) < 0) + if ((err = dmx_register_demux(dmx)) < 0) return err; return 0; } +EXPORT_SYMBOL(dvb_dmx_init); int dvb_dmx_release(struct dvb_demux *dvbdemux) @@ -1258,9 +1287,8 @@ int dvb_dmx_release(struct dvb_demux *dvbdemux) struct dmx_demux *dmx = &dvbdemux->dmx; dmx_unregister_demux(dmx); - if (dvbdemux->filter) - vfree(dvbdemux->filter); - if (dvbdemux->feed) - vfree(dvbdemux->feed); + vfree(dvbdemux->filter); + vfree(dvbdemux->feed); return 0; } +EXPORT_SYMBOL(dvb_dmx_release);