Commit 28003225 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] update the dvb core

parent c8639e86
......@@ -3,6 +3,6 @@
#
dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o
dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o dvb_ringbuffer.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o
obj-$(CONFIG_DVB_CORE) += crc32.o
......@@ -144,6 +144,14 @@ struct dmx_section_feed_s {
int is_filtering; /* Set to non-zero when filtering in progress */
struct dmx_demux_s* parent; /* Back-pointer */
void* priv; /* Pointer to private data of the API client */
int check_crc;
u32 crc_val;
u8 secbuf[4096];
int secbufp;
int seclen;
int (*set) (struct dmx_section_feed_s* feed,
__u16 pid,
size_t circular_buffer_size,
......@@ -162,16 +170,16 @@ typedef struct dmx_section_feed_s dmx_section_feed_t;
/* Callback functions */
/*--------------------------------------------------------------------------*/
typedef int (*dmx_ts_cb) ( __u8 * buffer1,
typedef int (*dmx_ts_cb) ( const u8 * buffer1,
size_t buffer1_length,
__u8 * buffer2,
const u8 * buffer2,
size_t buffer2_length,
dmx_ts_feed_t* source,
dmx_success_t success);
typedef int (*dmx_section_cb) ( __u8 * buffer1,
typedef int (*dmx_section_cb) ( const u8 * buffer1,
size_t buffer1_len,
__u8 * buffer2,
const u8 * buffer2,
size_t buffer2_len,
dmx_section_filter_t * source,
dmx_success_t success);
......@@ -278,6 +286,9 @@ struct dmx_demux_s {
int (*disconnect_frontend) (struct dmx_demux_s* demux);
int (*get_pes_pids) (struct dmx_demux_s* demux, __u16 *pids);
int (*get_stc) (struct dmx_demux_s* demux, unsigned int num,
uint64_t *stc, unsigned int *base);
};
typedef struct dmx_demux_s dmx_demux_t;
......
This diff is collapsed.
......@@ -85,6 +85,8 @@ typedef struct dmxdev_filter_s {
struct dmxdev_s *dev;
dmxdev_buffer_t buffer;
struct semaphore mutex;
// only for sections
struct timer_list timer;
int todo;
......
This diff is collapsed.
......@@ -25,6 +25,9 @@
#ifndef _DVB_DEMUX_H_
#define _DVB_DEMUX_H_
#include <asm/semaphore.h>
#include <linux/timer.h>
#include "demux.h"
#define DMX_TYPE_TS 0
......@@ -59,6 +62,8 @@ struct dvb_demux_filter {
};
#define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head)
struct dvb_demux_feed {
union {
dmx_ts_feed_t ts;
......@@ -71,13 +76,13 @@ struct dvb_demux_feed {
} cb;
struct dvb_demux *demux;
void *priv;
int type;
int state;
u16 pid;
u8 *buffer;
int buffer_size;
int descramble;
int check_crc;
struct timespec timeout;
struct dvb_demux_filter *filter;
......@@ -86,12 +91,11 @@ struct dvb_demux_feed {
int ts_type;
dmx_ts_pes_t pes_type;
u8 secbuf[4096];
int secbufp;
int seclen;
int cc;
u16 peslen;
struct list_head list_head;
};
struct dvb_demux {
......@@ -99,10 +103,14 @@ struct dvb_demux {
void *priv;
int filternum;
int feednum;
int (*start_feed)(struct dvb_demux_feed *);
int (*stop_feed)(struct dvb_demux_feed *);
int (*write_to_decoder)(struct dvb_demux_feed *, u8 *, size_t);
int (*start_feed) (struct dvb_demux_feed *feed);
int (*stop_feed) (struct dvb_demux_feed *feed);
int (*write_to_decoder) (struct dvb_demux_feed *feed,
const u8 *buf, size_t len);
u32 (*check_crc32) (struct dvb_demux_feed *feed,
const u8 *buf, size_t len);
void (*memcopy) (struct dvb_demux_feed *feed, u8 *dst,
const u8 *src, size_t len);
int users;
#define MAX_DVB_DEMUX_USERS 10
......@@ -117,7 +125,7 @@ struct dvb_demux {
int recording;
#define DMX_MAX_PID 0x2000
struct dvb_demux_feed *pid2feed[DMX_MAX_PID+1];
struct list_head feed_list;
u8 tsbuf[188];
int tsbufp;
......@@ -129,6 +137,7 @@ struct dvb_demux {
int dvb_dmx_init(struct dvb_demux *dvbdemux);
int dvb_dmx_release(struct dvb_demux *dvbdemux);
void dvb_dmx_swfilter_packet(struct dvb_demux *dvbdmx, const u8 *buf);
void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, int count);
void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, size_t count);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
#endif /* _DVB_DEMUX_H_ */
#include <linux/module.h>
#include <linux/videodev.h>
#include "dvb_filter.h"
unsigned int bitrates[3][16] =
......@@ -346,8 +345,8 @@ int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
}
#endif
static
int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
int dvb_filter_get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
{
uint8_t *headr;
int found = 0;
......@@ -605,397 +604,3 @@ int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len)
return p2ts->cb(p2ts->priv, buf);
}
void dvb_filter_ipack_reset(ipack *p)
{
p->found = 0;
p->cid = 0;
p->plength = 0;
p->flag1 = 0;
p->flag2 = 0;
p->hlength = 0;
p->mpeg = 0;
p->check = 0;
p->which = 0;
p->done = 0;
p->count = 0;
}
void dvb_filter_ipack_init(ipack *p, int size,
void (*func)(u8 *buf, int size, void *priv))
{
if ( !(p->buf = vmalloc(size*sizeof(u8))) ){
printk ("Couldn't allocate memory for ipack\n");
}
p->size = size;
p->func = func;
p->repack_subids = 0;
dvb_filter_ipack_reset(p);
}
void dvb_filter_ipack_free(ipack * p)
{
if (p->buf) vfree(p->buf);
}
static
void send_ipack(ipack *p)
{
int off;
AudioInfo ai;
int ac3_off = 0;
int streamid=0;
int nframes= 0;
int f=0;
switch ( p->mpeg ){
case 2:
if (p->count < 10) return;
p->buf[3] = p->cid;
p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8);
p->buf[5] = (u8)((p->count-6) & 0x00FF);
if (p->repack_subids && p->cid == PRIVATE_STREAM1){
off = 9+p->buf[8];
streamid = p->buf[off];
if ((streamid & 0xF8) == 0x80){
ai.off = 0;
ac3_off = ((p->buf[off+2] << 8)|
p->buf[off+3]);
if (ac3_off < p->count)
f=get_ac3info(p->buf+off+3+ac3_off,
p->count-ac3_off, &ai,0);
if ( !f ){
nframes = (p->count-off-3-ac3_off)/
ai.framesize + 1;
p->buf[off+2] = (ac3_off >> 8)& 0xFF;
p->buf[off+3] = (ac3_off)& 0xFF;
p->buf[off+1] = nframes;
ac3_off += nframes * ai.framesize -
p->count;
}
}
}
p->func(p->buf, p->count, p->data);
p->buf[6] = 0x80;
p->buf[7] = 0x00;
p->buf[8] = 0x00;
p->count = 9;
if (p->repack_subids && p->cid == PRIVATE_STREAM1
&& (streamid & 0xF8)==0x80 ){
p->count += 4;
p->buf[9] = streamid;
p->buf[10] = (ac3_off >> 8)& 0xFF;
p->buf[11] = (ac3_off)& 0xFF;
p->buf[12] = 0;
}
break;
case 1:
if (p->count < 8) return;
p->buf[3] = p->cid;
p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8);
p->buf[5] = (u8)((p->count-6) & 0x00FF);
p->func(p->buf, p->count, p->data);
p->buf[6] = 0x0F;
p->count = 7;
break;
}
}
void dvb_filter_ipack_flush(ipack *p)
{
if (p->plength != MMAX_PLENGTH-6 || p->found<=6)
return;
p->plength = p->found-6;
p->found = 0;
send_ipack(p);
dvb_filter_ipack_reset(p);
}
static
void write_ipack(ipack *p, u8 *data, int count)
{
u8 headr[3] = { 0x00, 0x00, 0x01} ;
if (p->count < 6){
memcpy(p->buf, headr, 3);
p->count = 6;
}
if (p->count + count < p->size){
memcpy(p->buf+p->count, data, count);
p->count += count;
} else {
int rest = p->size - p->count;
memcpy(p->buf+p->count, data, rest);
p->count += rest;
send_ipack(p);
if (count - rest > 0)
write_ipack(p, data+rest, count-rest);
}
}
int dvb_filter_instant_repack(u8 *buf, int count, ipack *p)
{
int l;
int c=0;
while (c < count && (p->mpeg == 0 ||
(p->mpeg == 1 && p->found < 7) ||
(p->mpeg == 2 && p->found < 9))
&& (p->found < 5 || !p->done)){
switch ( p->found ){
case 0:
case 1:
if (buf[c] == 0x00) p->found++;
else p->found = 0;
c++;
break;
case 2:
if (buf[c] == 0x01) p->found++;
else if (buf[c] == 0) {
p->found = 2;
} else p->found = 0;
c++;
break;
case 3:
p->cid = 0;
switch (buf[c]){
case PROG_STREAM_MAP:
case PRIVATE_STREAM2:
case PROG_STREAM_DIR:
case ECM_STREAM :
case EMM_STREAM :
case PADDING_STREAM :
case DSM_CC_STREAM :
case ISO13522_STREAM:
p->done = 1;
case PRIVATE_STREAM1:
case VIDEO_STREAM_S ... VIDEO_STREAM_E:
case AUDIO_STREAM_S ... AUDIO_STREAM_E:
p->found++;
p->cid = buf[c];
c++;
break;
default:
p->found = 0;
break;
}
break;
case 4:
if (count-c > 1){
p->plen[0] = buf[c];
c++;
p->plen[1] = buf[c];
c++;
p->found+=2;
p->plength=(p->plen[0]<<8)|p->plen[1];
} else {
p->plen[0] = buf[c];
p->found++;
return count;
}
break;
case 5:
p->plen[1] = buf[c];
c++;
p->found++;
p->plength=(p->plen[0]<<8)|p->plen[1];
break;
case 6:
if (!p->done){
p->flag1 = buf[c];
c++;
p->found++;
if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2;
else {
p->hlength = 0;
p->which = 0;
p->mpeg = 1;
p->flag2 = 0;
}
}
break;
case 7:
if ( !p->done && p->mpeg == 2) {
p->flag2 = buf[c];
c++;
p->found++;
}
break;
case 8:
if ( !p->done && p->mpeg == 2) {
p->hlength = buf[c];
c++;
p->found++;
}
break;
default:
break;
}
}
if (c == count) return count;
if (!p->plength) p->plength = MMAX_PLENGTH-6;
if ( p->done || ((p->mpeg == 2 && p->found >= 9) ||
(p->mpeg == 1 && p->found >= 7)) ){
switch (p->cid){
case AUDIO_STREAM_S ... AUDIO_STREAM_E:
case VIDEO_STREAM_S ... VIDEO_STREAM_E:
case PRIVATE_STREAM1:
if (p->mpeg == 2 && p->found == 9) {
write_ipack(p, &p->flag1, 1);
write_ipack(p, &p->flag2, 1);
write_ipack(p, &p->hlength, 1);
}
if (p->mpeg == 1 && p->found == 7)
write_ipack(p, &p->flag1, 1);
if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&
p->found < 14) {
while (c < count && p->found < 14) {
p->pts[p->found-9] = buf[c];
write_ipack(p, buf+c, 1);
c++;
p->found++;
}
if (c == count) return count;
}
if (p->mpeg == 1 && p->which < 2000) {
if (p->found == 7) {
p->check = p->flag1;
p->hlength = 1;
}
while (!p->which && c < count &&
p->check == 0xFF){
p->check = buf[c];
write_ipack(p, buf+c, 1);
c++;
p->found++;
p->hlength++;
}
if ( c == count) return count;
if ( (p->check & 0xC0) == 0x40 && !p->which){
p->check = buf[c];
write_ipack(p, buf+c, 1);
c++;
p->found++;
p->hlength++;
p->which = 1;
if ( c == count) return count;
p->check = buf[c];
write_ipack(p, buf+c, 1);
c++;
p->found++;
p->hlength++;
p->which = 2;
if ( c == count) return count;
}
if (p->which == 1){
p->check = buf[c];
write_ipack(p, buf+c, 1);
c++;
p->found++;
p->hlength++;
p->which = 2;
if ( c == count) return count;
}
if ( (p->check & 0x30) && p->check != 0xFF){
p->flag2 = (p->check & 0xF0) << 2;
p->pts[0] = p->check;
p->which = 3;
}
if ( c == count) return count;
if (p->which > 2){
if ((p->flag2 & PTS_DTS_FLAGS)
== PTS_ONLY){
while (c < count &&
p->which < 7){
p->pts[p->which-2] =
buf[c];
write_ipack(p,buf+c,1);
c++;
p->found++;
p->which++;
p->hlength++;
}
if ( c == count) return count;
} else if ((p->flag2 & PTS_DTS_FLAGS)
== PTS_DTS){
while (c < count &&
p->which< 12){
if (p->which< 7)
p->pts[p->which
-2] =
buf[c];
write_ipack(p,buf+c,1);
c++;
p->found++;
p->which++;
p->hlength++;
}
if ( c == count) return count;
}
p->which = 2000;
}
}
while (c < count && p->found < p->plength+6){
l = count -c;
if (l+p->found > p->plength+6)
l = p->plength+6-p->found;
write_ipack(p, buf+c, l);
p->found += l;
c += l;
}
break;
}
if ( p->done ){
if( p->found + count - c < p->plength+6){
p->found += count-c;
c = count;
} else {
c += p->plength+6 - p->found;
p->found = p->plength+6;
}
}
if (p->plength && p->found == p->plength+6) {
send_ipack(p);
dvb_filter_ipack_reset(p);
if (c < count)
dvb_filter_instant_repack(buf+c, count-c, p);
}
}
return count;
}
......@@ -17,6 +17,7 @@ typedef struct dvb_filter_pes2ts_s {
void dvb_filter_pes2ts_init(dvb_filter_pes2ts_t *p2ts, unsigned short pid,
dvb_filter_pes2ts_cb_t *cb, void *priv);
int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len);
......@@ -223,12 +224,7 @@ typedef struct audio_i{
uint32_t off;
} AudioInfo;
int dvb_filter_get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr);
void dvb_filter_ipack_reset(ipack *p);
int dvb_filter_instant_repack(u8 *buf, int count, ipack *p);
void dvb_filter_ipack_init(ipack *p, int size,
void (*func)(u8 *buf, int size, void *priv));
void dvb_filter_ipack_free(ipack * p);
void dvb_filter_ipack_flush(ipack *p);
#endif
This diff is collapsed.
......@@ -52,8 +52,10 @@ struct dvb_frontend {
int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg);
int (*ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg);
int (*after_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg);
void (*notifier_callback) (fe_status_t s, void *data);
struct dvb_i2c_bus *i2c;
void *before_after_data; /* can be used by hardware module... */
void *notifier_data; /* can be used by hardware module... */
void *data; /* can be used by hardware module... */
};
......
......@@ -22,10 +22,13 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/version.h>
#include "compat.h"
#include "dvb_i2c.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#include "compat.h"
#endif
#include "dvb_i2c.h"
struct dvb_i2c_device {
struct list_head list_head;
......@@ -34,13 +37,11 @@ struct dvb_i2c_device {
void (*detach) (struct dvb_i2c_bus *i2c);
};
LIST_HEAD(dvb_i2c_buslist);
LIST_HEAD(dvb_i2c_devicelist);
DECLARE_MUTEX(dvb_i2c_mutex);
static
int register_i2c_client (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
{
......@@ -63,11 +64,16 @@ int register_i2c_client (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
static
void try_attach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
{
if (try_module_get(dev->owner)) {
if (dev->attach(i2c) == 0)
register_i2c_client(i2c, dev);
else
module_put(dev->owner);
if (dev->owner) {
if (!try_module_get(dev->owner))
return;
}
if (dev->attach (i2c) == 0) {
register_i2c_client (i2c, dev);
} else {
if (dev->owner)
module_put (dev->owner);
}
}
......@@ -75,8 +81,10 @@ void try_attach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
static
void detach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
{
dev->detach(i2c);
module_put(dev->owner);
dev->detach (i2c);
if (dev->owner)
module_put (dev->owner);
}
......@@ -84,25 +92,27 @@ static
void unregister_i2c_client_from_bus (struct dvb_i2c_device *dev,
struct dvb_i2c_bus *i2c)
{
struct list_head *entry;
struct list_head *entry, *n;
list_for_each (entry, &i2c->client_list) {
list_for_each_safe (entry, n, &i2c->client_list) {
struct dvb_i2c_device *client;
client = list_entry (entry, struct dvb_i2c_device, list_head);
if (client->detach == dev->detach)
if (client->detach == dev->detach) {
list_del (entry);
detach_device (i2c, dev);
}
}
}
static
void unregister_i2c_client_from_all_busses (struct dvb_i2c_device *dev)
{
struct list_head *entry;
struct list_head *entry, *n;
list_for_each (entry, &dvb_i2c_buslist) {
list_for_each_safe (entry, n, &dvb_i2c_buslist) {
struct dvb_i2c_bus *i2c;
i2c = list_entry (entry, struct dvb_i2c_bus, list_head);
......@@ -118,18 +128,15 @@ void unregister_all_clients_from_bus (struct dvb_i2c_bus *i2c)
struct list_head *entry, *n;
list_for_each_safe (entry, n, &(i2c->client_list)) {
struct dvb_i2c_device *client;
client = list_entry (entry, struct dvb_i2c_device, list_head);
struct dvb_i2c_device *dev;
detach_device (i2c, client);
dev = list_entry (entry, struct dvb_i2c_device, list_head);
list_del (entry);
unregister_i2c_client_from_bus (dev, i2c);
}
}
static
void probe_device_on_all_busses (struct dvb_i2c_device *dev)
{
......@@ -160,15 +167,38 @@ void probe_devices_on_bus (struct dvb_i2c_bus *i2c)
}
struct dvb_i2c_bus*
dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
struct i2c_msg msgs[], int num),
void *data,
static
struct dvb_i2c_bus* dvb_find_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
const struct i2c_msg msgs[],
int num),
struct dvb_adapter *adapter,
int id)
{
struct list_head *entry;
list_for_each (entry, &dvb_i2c_buslist) {
struct dvb_i2c_bus *i2c;
i2c = list_entry (entry, struct dvb_i2c_bus, list_head);
if (i2c->xfer == xfer && i2c->adapter == adapter && i2c->id == id)
return i2c;
}
return NULL;
}
struct dvb_i2c_bus*
dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
const struct i2c_msg *msgs, int num),
void *data, struct dvb_adapter *adapter, int id)
{
struct dvb_i2c_bus *i2c;
if (down_interruptible (&dvb_i2c_mutex))
return NULL;
if (!(i2c = kmalloc (sizeof (struct dvb_i2c_bus), GFP_KERNEL)))
return NULL;
......@@ -184,54 +214,27 @@ dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
list_add_tail (&i2c->list_head, &dvb_i2c_buslist);
return i2c;
}
struct dvb_i2c_bus*
dvb_find_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
struct i2c_msg msgs[], int num),
struct dvb_adapter *adapter,
int id)
{
struct list_head *entry;
if (down_interruptible (&dvb_i2c_mutex))
return NULL;
list_for_each (entry, &dvb_i2c_buslist) {
struct dvb_i2c_bus *i2c;
i2c = list_entry (entry, struct dvb_i2c_bus, list_head);
if (i2c->xfer == xfer &&
i2c->adapter == adapter &&
i2c->id == id)
{
up (&dvb_i2c_mutex);
return i2c;
}
}
up (&dvb_i2c_mutex);
return NULL;
return i2c;
}
void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
struct i2c_msg msgs[], int num),
struct dvb_adapter *adapter,
int id)
const struct i2c_msg msgs[], int num),
struct dvb_adapter *adapter, int id)
{
struct dvb_i2c_bus *i2c = dvb_find_i2c_bus (xfer, adapter, id);
struct dvb_i2c_bus *i2c;
down (&dvb_i2c_mutex);
if (i2c) {
if ((i2c = dvb_find_i2c_bus (xfer, adapter, id))) {
unregister_all_clients_from_bus (i2c);
list_del (&i2c->list_head);
kfree (i2c);
}
up (&dvb_i2c_mutex);
}
......@@ -267,8 +270,7 @@ int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c))
{
struct list_head *entry, *n;
if (down_interruptible (&dvb_i2c_mutex))
return -ERESTARTSYS;
down (&dvb_i2c_mutex);
list_for_each_safe (entry, n, &dvb_i2c_devicelist) {
struct dvb_i2c_device *dev;
......
......@@ -30,7 +30,9 @@
struct dvb_i2c_bus {
struct list_head list_head;
int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num);
int (*xfer) (struct dvb_i2c_bus *i2c,
const struct i2c_msg msgs[],
int num);
void *data;
struct dvb_adapter *adapter;
int id;
......@@ -38,17 +40,16 @@ struct dvb_i2c_bus {
};
extern
struct dvb_i2c_bus* dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
struct i2c_msg msgs[],
int num),
extern struct dvb_i2c_bus*
dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
const struct i2c_msg *msgs, int num),
void *data,
struct dvb_adapter *adapter,
int id);
extern
void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
struct i2c_msg msgs[], int num),
const struct i2c_msg msgs[], int num),
struct dvb_adapter *adapter,
int id);
......
......@@ -8,6 +8,69 @@
#include "dvb_demux.h"
#include "dvb_net.h"
/* if the miracle happens and "generic_usercopy()" is included into
the kernel, then this can vanish. please don't make the mistake and
define this as video_usercopy(). this will introduce a dependecy
to the v4l "videodev.o" module, which is unnecessary for some
cards (ie. the budget dvb-cards don't need the v4l module...) */
int dvb_usercopy(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg,
int (*func)(struct inode *inode, struct file *file,
unsigned int cmd, void *arg))
{
char sbuf[128];
void *mbuf = NULL;
void *parg = NULL;
int err = -EINVAL;
/* Copy arguments into temp kernel buffer */
switch (_IOC_DIR(cmd)) {
case _IOC_NONE:
parg = (void *)arg;
break;
case _IOC_READ: /* some v4l ioctls are marked wrong ... */
case _IOC_WRITE:
case (_IOC_WRITE | _IOC_READ):
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
parg = sbuf;
} else {
/* too big to allocate from stack */
mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
if (NULL == mbuf)
return -ENOMEM;
parg = mbuf;
}
err = -EFAULT;
if (copy_from_user(parg, (void *)arg, _IOC_SIZE(cmd)))
goto out;
break;
}
/* call driver */
if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD)
err = -EINVAL;
if (err < 0)
goto out;
/* Copy results into user buffer */
switch (_IOC_DIR(cmd))
{
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void *)arg, parg, _IOC_SIZE(cmd)))
err = -EFAULT;
break;
}
out:
if (mbuf)
kfree(mbuf);
return err;
}
EXPORT_SYMBOL(dvb_usercopy);
EXPORT_SYMBOL(dvb_dmxdev_init);
EXPORT_SYMBOL(dvb_dmxdev_release);
......@@ -15,6 +78,7 @@ EXPORT_SYMBOL(dvb_dmx_init);
EXPORT_SYMBOL(dvb_dmx_release);
EXPORT_SYMBOL(dvb_dmx_swfilter_packet);
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
EXPORT_SYMBOL(dvb_dmx_swfilter);
EXPORT_SYMBOL(dvb_register_frontend);
EXPORT_SYMBOL(dvb_unregister_frontend);
......@@ -39,11 +103,7 @@ EXPORT_SYMBOL(dvb_generic_ioctl);
EXPORT_SYMBOL(dvb_generic_open);
EXPORT_SYMBOL(dvb_generic_release);
EXPORT_SYMBOL(dvb_filter_ipack_init);
EXPORT_SYMBOL(dvb_filter_ipack_reset);
EXPORT_SYMBOL(dvb_filter_ipack_free);
EXPORT_SYMBOL(dvb_filter_ipack_flush);
EXPORT_SYMBOL(dvb_filter_instant_repack);
EXPORT_SYMBOL(dvb_filter_pes2ts_init);
EXPORT_SYMBOL(dvb_filter_pes2ts);
EXPORT_SYMBOL(dvb_filter_get_ac3info);
This diff is collapsed.
......@@ -32,23 +32,9 @@
#include "dvbdev.h"
#define DVB_NET_DEVICES_MAX 10
#define DVB_NET_MULTICAST_MAX 10
typedef struct dvb_net_priv_s {
struct net_device_stats stats;
char name[6];
u16 pid;
dmx_demux_t *demux;
dmx_section_feed_t *secfeed;
dmx_section_filter_t *secfilter;
int multi_num;
dmx_section_filter_t *multi_secfilter[DVB_NET_MULTICAST_MAX];
unsigned char multi_macs[DVB_NET_MULTICAST_MAX][6];
} dvb_net_priv_t;
typedef struct dvb_net_s {
typedef struct dvb_net {
struct dvb_device *dvbdev;
int card_num;
int dev_num;
struct net_device device[DVB_NET_DEVICES_MAX];
......@@ -57,7 +43,8 @@ typedef struct dvb_net_s {
} dvb_net_t;
void dvb_net_release(dvb_net_t *);
int dvb_net_init(struct dvb_adapter *, dvb_net_t *, dmx_demux_t *);
void dvb_net_release(struct dvb_net *);
int dvb_net_init(struct dvb_adapter *, struct dvb_net *, dmx_demux_t *);
#endif
/*
*
* dvb_ringbuffer.c: ring buffer implementation for the dvb driver
*
* Copyright (C) 2003 Oliver Endriss
*
* based on code originally found in av7110.c:
* Copyright (C) 1999-2002 Ralph Metzler
* & Marcus Metzler for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*
* the project's page is at http://www.linuxtv.org/dvb/
*/
#define __KERNEL_SYSCALLS__
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#include "dvb_ringbuffer.h"
void dvb_ringbuffer_init(dvb_ringbuffer_t *rbuf, void *data, size_t len)
{
rbuf->pread=rbuf->pwrite=0;
rbuf->data=data;
rbuf->size=len;
init_waitqueue_head(&rbuf->queue);
spin_lock_init(&(rbuf->lock));
rbuf->lock=SPIN_LOCK_UNLOCKED;
}
int dvb_ringbuffer_empty(dvb_ringbuffer_t *rbuf)
{
return (rbuf->pread==rbuf->pwrite);
}
ssize_t dvb_ringbuffer_free(dvb_ringbuffer_t *rbuf)
{
ssize_t free;
free = rbuf->pread - rbuf->pwrite;
if (free <= 0)
free += rbuf->size;
return free-1;
}
ssize_t dvb_ringbuffer_avail(dvb_ringbuffer_t *rbuf)
{
ssize_t avail;
avail = rbuf->pwrite - rbuf->pread;
if (avail < 0)
avail += rbuf->size;
return avail;
}
void dvb_ringbuffer_flush(dvb_ringbuffer_t *rbuf)
{
rbuf->pread = rbuf->pwrite;
}
void dvb_ringbuffer_flush_spinlock_wakeup(dvb_ringbuffer_t *rbuf)
{
unsigned long flags;
spin_lock_irqsave(&rbuf->lock, flags);
dvb_ringbuffer_flush(rbuf);
spin_unlock_irqrestore(&rbuf->lock, flags);
wake_up(&rbuf->queue);
}
ssize_t dvb_ringbuffer_read(dvb_ringbuffer_t *rbuf, u8 *buf, size_t len, int usermem)
{
size_t todo = len;
size_t split;
split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
if (split > 0) {
if (!usermem)
memcpy(buf, rbuf->data+rbuf->pread, split);
else
if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
return -EFAULT;
buf += split;
todo -= split;
rbuf->pread = 0;
}
if (!usermem)
memcpy(buf, rbuf->data+rbuf->pread, todo);
else
if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
return -EFAULT;
rbuf->pread = (rbuf->pread + len) % rbuf->size;
return len;
}
ssize_t dvb_ringbuffer_write(dvb_ringbuffer_t *rbuf, const u8 *buf,
size_t len, int usermem)
{
size_t todo = len;
size_t split;
split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0;
if (split > 0) {
if (!usermem)
memcpy(rbuf->data+rbuf->pwrite, buf, split);
else
if (copy_from_user(rbuf->data+rbuf->pwrite,
buf, split))
return -EFAULT;
buf += split;
todo -= split;
rbuf->pwrite = 0;
}
if (!usermem)
memcpy(rbuf->data+rbuf->pwrite, buf, todo);
else
if (copy_from_user(rbuf->data+rbuf->pwrite, buf, todo))
return -EFAULT;
rbuf->pwrite = (rbuf->pwrite + len) % rbuf->size;
return len;
}
EXPORT_SYMBOL_GPL(dvb_ringbuffer_init);
EXPORT_SYMBOL_GPL(dvb_ringbuffer_empty);
EXPORT_SYMBOL_GPL(dvb_ringbuffer_free);
EXPORT_SYMBOL_GPL(dvb_ringbuffer_avail);
EXPORT_SYMBOL_GPL(dvb_ringbuffer_flush);
EXPORT_SYMBOL_GPL(dvb_ringbuffer_flush_spinlock_wakeup);
EXPORT_SYMBOL_GPL(dvb_ringbuffer_read);
EXPORT_SYMBOL_GPL(dvb_ringbuffer_write);
/*
*
* dvb_ringbuffer.h: ring buffer implementation for the dvb driver
*
* Copyright (C) 2003 Oliver Endriss
*
* based on code originally found in av7110.c:
* Copyright (C) 1999-2002 Ralph Metzler
* & Marcus Metzler for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*
* the project's page is at http://www.linuxtv.org/dvb/
*/
#ifndef _DVB_RINGBUFFER_H_
#define _DVB_RINGBUFFER_H_
typedef struct dvb_ringbuffer {
u8 *data;
ssize_t size;
ssize_t pread;
ssize_t pwrite;
wait_queue_head_t queue;
spinlock_t lock;
} dvb_ringbuffer_t;
/*
** Notes:
** ------
** (1) For performance reasons read and write routines don't check buffer sizes
** and/or number of bytes free/available. This has to be done before these
** routines are called. For example:
**
** *** write <buflen> bytes ***
** free = dvb_ringbuffer_free(rbuf);
** if (free >= buflen)
** count = dvb_ringbuffer_write(rbuf, buffer, buflen, 0);
** else
** ...
**
** *** read min. 1000, max. <bufsize> bytes ***
** avail = dvb_ringbuffer_avail(rbuf);
** if (avail >= 1000)
** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize), 0);
** else
** ...
**
** (2) If there is exactly one reader and one writer, there is no need
** to lock read or write operations.
** Two or more readers must be locked against each other.
** Flushing the buffer counts as a read operation.
** Two or more writers must be locked against each other.
*/
/* initialize ring buffer, lock and queue */
extern void dvb_ringbuffer_init(dvb_ringbuffer_t *rbuf, void *data, size_t len);
/* test whether buffer is empty */
extern int dvb_ringbuffer_empty(dvb_ringbuffer_t *rbuf);
/* return the number of free bytes in the buffer */
extern ssize_t dvb_ringbuffer_free(dvb_ringbuffer_t *rbuf);
/* return the number of bytes waiting in the buffer */
extern ssize_t dvb_ringbuffer_avail(dvb_ringbuffer_t *rbuf);
/* read routines & macros */
/* ---------------------- */
/* flush buffer */
extern void dvb_ringbuffer_flush(dvb_ringbuffer_t *rbuf);
/* flush buffer protected by spinlock and wake-up waiting task(s) */
extern void dvb_ringbuffer_flush_spinlock_wakeup(dvb_ringbuffer_t *rbuf);
/* peek at byte <offs> in the buffer */
#define DVB_RINGBUFFER_PEEK(rbuf,offs) \
(rbuf)->data[((rbuf)->pread+(offs))%(rbuf)->size]
/* advance read ptr by <num> bytes */
#define DVB_RINGBUFFER_SKIP(rbuf,num) \
(rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size
/*
** read <len> bytes from ring buffer into <buf>
** <usermem> specifies whether <buf> resides in user space
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_read(dvb_ringbuffer_t *rbuf, u8 *buf,
size_t len, int usermem);
/* write routines & macros */
/* ----------------------- */
/* write single byte to ring buffer */
#define DVB_RINGBUFFER_WRITE_BYTE(rbuf,byte) \
{ (rbuf)->data[(rbuf)->pwrite]=(byte); \
(rbuf)->pwrite=((rbuf)->pwrite+1)%(rbuf)->size; }
/*
** write <len> bytes to ring buffer
** <usermem> specifies whether <buf> resides in user space
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_write(dvb_ringbuffer_t *rbuf, const u8 *buf,
size_t len, int usermem);
#endif /* _DVB_RINGBUFFER_H_ */
......@@ -35,11 +35,13 @@
#include <asm/system.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/videodev.h>
#include "compat.h"
#include "dvbdev.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#include "compat.h"
#endif
static int dvbdev_debug = 0;
#define dprintk if (dvbdev_debug) printk
......@@ -57,7 +59,6 @@ static char *dnames[] = {
#define DVB_MAX_IDS 4
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
static
struct dvb_device* dvbdev_find_device (int minor)
{
......@@ -160,7 +161,7 @@ int dvb_generic_ioctl(struct inode *inode, struct file *file,
if (!dvbdev->kernel_ioctl)
return -EINVAL;
return video_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl);
return dvb_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl);
}
......@@ -267,7 +268,7 @@ int dvbdev_get_free_adapter_num (void)
}
int dvb_register_adapter(struct dvb_adapter **padap, char *name)
int dvb_register_adapter(struct dvb_adapter **padap, const char *name)
{
struct dvb_adapter *adap;
int num;
......@@ -288,12 +289,14 @@ int dvb_register_adapter(struct dvb_adapter **padap, char *name)
memset (adap, 0, sizeof(struct dvb_adapter));
INIT_LIST_HEAD (&adap->device_list);
MOD_INC_USE_COUNT;
/* fixme: is this correct? */
try_module_get(THIS_MODULE);
printk ("DVB: registering new adapter (%s).\n", name);
adap->devfs_handle = devfs_mk_dir("dvb/adapter%d", num);
adap->num = num;
adap->name = name;
list_add_tail (&adap->list_head, &dvb_adapter_list);
......@@ -311,7 +314,8 @@ int dvb_unregister_adapter(struct dvb_adapter *adap)
list_del (&adap->list_head);
up (&dvbdev_register_lock);
kfree (adap);
MOD_DEC_USE_COUNT;
/* fixme: is this correct? */
module_put(THIS_MODULE);
return 0;
}
......
......@@ -48,6 +48,7 @@ struct dvb_adapter {
devfs_handle_t devfs_handle;
struct list_head list_head;
struct list_head device_list;
const char *name;
};
......@@ -70,7 +71,7 @@ struct dvb_device {
};
extern int dvb_register_adapter (struct dvb_adapter **padap, char *name);
extern int dvb_register_adapter (struct dvb_adapter **padap, const char *name);
extern int dvb_unregister_adapter (struct dvb_adapter *adap);
extern int dvb_register_device (struct dvb_adapter *adap,
......@@ -85,6 +86,9 @@ extern int dvb_generic_open (struct inode *inode, struct file *file);
extern int dvb_generic_release (struct inode *inode, struct file *file);
extern int dvb_generic_ioctl (struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
int dvb_usercopy(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg,
int (*func)(struct inode *inode, struct file *file,
unsigned int cmd, void *arg));
#endif /* #ifndef _DVBDEV_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment