Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
28003225
Commit
28003225
authored
Apr 07, 2003
by
Alan Cox
Committed by
Linus Torvalds
Apr 07, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] update the dvb core
parent
c8639e86
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
2145 additions
and
1945 deletions
+2145
-1945
drivers/media/dvb/dvb-core/Makefile
drivers/media/dvb/dvb-core/Makefile
+1
-1
drivers/media/dvb/dvb-core/Makefile.lib
drivers/media/dvb/dvb-core/Makefile.lib
+1
-0
drivers/media/dvb/dvb-core/demux.h
drivers/media/dvb/dvb-core/demux.h
+15
-4
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/dvb-core/dmxdev.c
+442
-385
drivers/media/dvb/dvb-core/dmxdev.h
drivers/media/dvb/dvb-core/dmxdev.h
+2
-0
drivers/media/dvb/dvb-core/dvb_demux.c
drivers/media/dvb/dvb-core/dvb_demux.c
+781
-723
drivers/media/dvb/dvb-core/dvb_demux.h
drivers/media/dvb/dvb-core/dvb_demux.h
+19
-10
drivers/media/dvb/dvb-core/dvb_filter.c
drivers/media/dvb/dvb-core/dvb_filter.c
+63
-458
drivers/media/dvb/dvb-core/dvb_filter.h
drivers/media/dvb/dvb-core/dvb_filter.h
+2
-6
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_frontend.c
+154
-139
drivers/media/dvb/dvb-core/dvb_frontend.h
drivers/media/dvb/dvb-core/dvb_frontend.h
+2
-0
drivers/media/dvb/dvb-core/dvb_i2c.c
drivers/media/dvb/dvb-core/dvb_i2c.c
+66
-64
drivers/media/dvb/dvb-core/dvb_i2c.h
drivers/media/dvb/dvb-core/dvb_i2c.h
+10
-9
drivers/media/dvb/dvb-core/dvb_ksyms.c
drivers/media/dvb/dvb-core/dvb_ksyms.c
+65
-5
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-core/dvb_net.c
+195
-112
drivers/media/dvb/dvb-core/dvb_net.h
drivers/media/dvb/dvb-core/dvb_net.h
+5
-18
drivers/media/dvb/dvb-core/dvb_ringbuffer.c
drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+176
-0
drivers/media/dvb/dvb-core/dvb_ringbuffer.h
drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+127
-0
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/dvb/dvb-core/dvbdev.c
+11
-7
drivers/media/dvb/dvb-core/dvbdev.h
drivers/media/dvb/dvb-core/dvbdev.h
+8
-4
No files found.
drivers/media/dvb/dvb-core/Makefile
View file @
28003225
...
...
@@ -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
drivers/media/dvb/dvb-core/Makefile.lib
0 → 100644
View file @
28003225
obj-$(CONFIG_DVB_CORE)
+=
crc32.o
drivers/media/dvb/dvb-core/demux.h
View file @
28003225
...
...
@@ -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
;
...
...
drivers/media/dvb/dvb-core/dmxdev.c
View file @
28003225
...
...
@@ -2,8 +2,8 @@
* dmxdev.c - DVB demultiplexer device
*
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
*
& Marcus Metzler <marcus@convergence.de>
for convergence integrated media GmbH
*
& Marcus Metzler <marcus@convergence.de>
for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
...
...
@@ -24,11 +24,13 @@
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/videodev.h>
#include <asm/uaccess.h>
#include "dmxdev.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#include "compat.h"
#endif
//MODULE_DESCRIPTION("");
//MODULE_AUTHOR("Ralph Metzler, Marcus Metzler");
...
...
@@ -43,133 +45,133 @@ static int debug = 0;
inline
dmxdev_filter_t
*
dvb_dmxdev_file_to_filter
(
struct
file
*
file
)
{
return
(
dmxdev_filter_t
*
)
file
->
private_data
;
return
(
dmxdev_filter_t
*
)
file
->
private_data
;
}
inline
dmxdev_dvr_t
*
dvb_dmxdev_file_to_dvr
(
dmxdev_t
*
dmxdev
,
struct
file
*
file
)
{
return
(
dmxdev_dvr_t
*
)
file
->
private_data
;
return
(
dmxdev_dvr_t
*
)
file
->
private_data
;
}
static
inline
void
dvb_dmxdev_buffer_init
(
dmxdev_buffer_t
*
buffer
)
{
buffer
->
data
=
0
;
buffer
->
size
=
8192
;
buffer
->
pread
=
0
;
buffer
->
pwrite
=
0
;
buffer
->
error
=
0
;
init_waitqueue_head
(
&
buffer
->
queue
);
buffer
->
data
=
0
;
buffer
->
size
=
8192
;
buffer
->
pread
=
0
;
buffer
->
pwrite
=
0
;
buffer
->
error
=
0
;
init_waitqueue_head
(
&
buffer
->
queue
);
}
static
inline
int
dvb_dmxdev_buffer_write
(
dmxdev_buffer_t
*
buf
,
uint8_t
*
src
,
int
len
)
static
inline
int
dvb_dmxdev_buffer_write
(
dmxdev_buffer_t
*
buf
,
const
u8
*
src
,
int
len
)
{
int
split
;
int
free
;
int
todo
;
int
split
;
int
free
;
int
todo
;
if
(
!
len
)
return
0
;
return
0
;
if
(
!
buf
->
data
)
return
0
;
return
0
;
free
=
buf
->
pread
-
buf
->
pwrite
;
split
=
0
;
if
(
free
<=
0
)
{
free
+=
buf
->
size
;
split
=
buf
->
size
-
buf
->
pwrite
;
}
if
(
len
>=
free
)
{
free
=
buf
->
pread
-
buf
->
pwrite
;
split
=
0
;
if
(
free
<=
0
)
{
free
+=
buf
->
size
;
split
=
buf
->
size
-
buf
->
pwrite
;
}
if
(
len
>=
free
)
{
dprintk
(
"dmxdev: buffer overflow
\n
"
);
return
-
1
;
return
-
1
;
}
if
(
split
>=
len
)
split
=
0
;
todo
=
len
;
if
(
split
)
{
memcpy
(
buf
->
data
+
buf
->
pwrite
,
src
,
split
);
todo
-=
split
;
buf
->
pwrite
=
0
;
}
memcpy
(
buf
->
data
+
buf
->
pwrite
,
src
+
split
,
todo
);
buf
->
pwrite
=
(
buf
->
pwrite
+
todo
)
%
buf
->
size
;
return
len
;
if
(
split
>=
len
)
split
=
0
;
todo
=
len
;
if
(
split
)
{
memcpy
(
buf
->
data
+
buf
->
pwrite
,
src
,
split
);
todo
-=
split
;
buf
->
pwrite
=
0
;
}
memcpy
(
buf
->
data
+
buf
->
pwrite
,
src
+
split
,
todo
);
buf
->
pwrite
=
(
buf
->
pwrite
+
todo
)
%
buf
->
size
;
return
len
;
}
static
ssize_t
dvb_dmxdev_buffer_read
(
dmxdev_buffer_t
*
src
,
int
non_blocking
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
unsigned
long
todo
=
count
;
int
split
,
avail
,
error
;
unsigned
long
todo
=
count
;
int
split
,
avail
,
error
;
if
(
!
src
->
data
)
return
0
;
return
0
;
if
((
error
=
src
->
error
))
{
src
->
pwrite
=
src
->
pread
;
src
->
error
=
0
;
src
->
error
=
0
;
return
error
;
}
if
(
non_blocking
&&
(
src
->
pwrite
==
src
->
pread
))
return
-
EWOULDBLOCK
;
return
-
EWOULDBLOCK
;
while
(
todo
>
0
)
{
if
(
non_blocking
&&
(
src
->
pwrite
==
src
->
pread
))
return
(
count
-
todo
)
?
(
count
-
todo
)
:
-
EWOULDBLOCK
;
while
(
todo
>
0
)
{
if
(
non_blocking
&&
(
src
->
pwrite
==
src
->
pread
))
return
(
count
-
todo
)
?
(
count
-
todo
)
:
-
EWOULDBLOCK
;
if
(
wait_event_interruptible
(
src
->
queue
,
if
(
wait_event_interruptible
(
src
->
queue
,
(
src
->
pread
!=
src
->
pwrite
)
||
(
src
->
error
))
<
0
)
return
count
-
todo
;
return
count
-
todo
;
if
((
error
=
src
->
error
))
{
src
->
pwrite
=
src
->
pread
;
src
->
error
=
0
;
src
->
error
=
0
;
return
error
;
}
split
=
src
->
size
;
avail
=
src
->
pwrite
-
src
->
pread
;
if
(
avail
<
0
)
{
avail
+=
src
->
size
;
split
=
src
->
size
-
src
->
pread
;
}
if
(
avail
>
todo
)
avail
=
todo
;
if
(
split
<
avail
)
{
if
(
copy_to_user
(
buf
,
src
->
data
+
src
->
pread
,
split
))
return
-
EFAULT
;
buf
+=
split
;
src
->
pread
=
0
;
todo
-=
split
;
avail
-=
split
;
}
if
(
avail
)
{
if
(
copy_to_user
(
buf
,
src
->
data
+
src
->
pread
,
avail
))
return
-
EFAULT
;
src
->
pread
=
(
src
->
pread
+
avail
)
%
src
->
size
;
todo
-=
avail
;
buf
+=
avail
;
}
}
return
count
;
split
=
src
->
size
;
avail
=
src
->
pwrite
-
src
->
pread
;
if
(
avail
<
0
)
{
avail
+=
src
->
size
;
split
=
src
->
size
-
src
->
pread
;
}
if
(
avail
>
todo
)
avail
=
todo
;
if
(
split
<
avail
)
{
if
(
copy_to_user
(
buf
,
src
->
data
+
src
->
pread
,
split
))
return
-
EFAULT
;
buf
+=
split
;
src
->
pread
=
0
;
todo
-=
split
;
avail
-=
split
;
}
if
(
avail
)
{
if
(
copy_to_user
(
buf
,
src
->
data
+
src
->
pread
,
avail
))
return
-
EFAULT
;
src
->
pread
=
(
src
->
pread
+
avail
)
%
src
->
size
;
todo
-=
avail
;
buf
+=
avail
;
}
}
return
count
;
}
static
dmx_frontend_t
*
get_fe
(
dmx_demux_t
*
demux
,
int
type
)
{
struct
list_head
*
head
,
*
pos
;
struct
list_head
*
head
,
*
pos
;
head
=
demux
->
get_frontends
(
demux
);
head
=
demux
->
get_frontends
(
demux
);
if
(
!
head
)
return
0
;
return
0
;
list_for_each
(
pos
,
head
)
if
(
DMX_FE_ENTRY
(
pos
)
->
source
==
type
)
return
DMX_FE_ENTRY
(
pos
);
if
(
DMX_FE_ENTRY
(
pos
)
->
source
==
type
)
return
DMX_FE_ENTRY
(
pos
);
return
0
;
}
...
...
@@ -177,8 +179,8 @@ get_fe(dmx_demux_t *demux, int type)
static
inline
void
dvb_dmxdev_dvr_state_set
(
dmxdev_dvr_t
*
dmxdevdvr
,
int
state
)
{
spin_lock_irq
(
&
dmxdevdvr
->
dev
->
lock
);
dmxdevdvr
->
state
=
state
;
spin_lock_irq
(
&
dmxdevdvr
->
dev
->
lock
);
dmxdevdvr
->
state
=
state
;
spin_unlock_irq
(
&
dmxdevdvr
->
dev
->
lock
);
}
...
...
@@ -186,17 +188,17 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
{
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
dmx_frontend_t
*
front
;
dmx_frontend_t
*
front
;
dprintk
(
"function : %s
\n
"
,
__FUNCTION__
);
dprintk
(
"function : %s
\n
"
,
__FUNCTION__
);
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDWR
)
{
if
(
!
(
dmxdev
->
capabilities
&
DMXDEV_CAP_DUPLEX
))
{
if
(
!
(
dmxdev
->
capabilities
&
DMXDEV_CAP_DUPLEX
))
{
up
(
&
dmxdev
->
mutex
);
return
-
EOPNOTSUPP
;
return
-
EOPNOTSUPP
;
}
}
...
...
@@ -206,12 +208,12 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
dmxdev
->
dvr_buffer
.
data
=
vmalloc
(
DVR_BUFFER_SIZE
);
if
(
!
dmxdev
->
dvr_buffer
.
data
)
{
up
(
&
dmxdev
->
mutex
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_WRONLY
)
{
dmxdev
->
dvr_orig_fe
=
dmxdev
->
demux
->
frontend
;
dmxdev
->
dvr_orig_fe
=
dmxdev
->
demux
->
frontend
;
if
(
!
dmxdev
->
demux
->
write
)
{
up
(
&
dmxdev
->
mutex
);
...
...
@@ -222,13 +224,13 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
if
(
!
front
)
{
up
(
&
dmxdev
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
dmxdev
->
demux
->
disconnect_frontend
(
dmxdev
->
demux
);
dmxdev
->
demux
->
connect_frontend
(
dmxdev
->
demux
,
front
);
}
up
(
&
dmxdev
->
mutex
);
return
0
;
up
(
&
dmxdev
->
mutex
);
return
0
;
}
static
int
dvb_dvr_release
(
struct
inode
*
inode
,
struct
file
*
file
)
...
...
@@ -236,25 +238,25 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_WRONLY
)
{
dmxdev
->
demux
->
disconnect_frontend
(
dmxdev
->
demux
);
dmxdev
->
demux
->
disconnect_frontend
(
dmxdev
->
demux
);
dmxdev
->
demux
->
connect_frontend
(
dmxdev
->
demux
,
dmxdev
->
dvr_orig_fe
);
}
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDONLY
)
{
if
(
dmxdev
->
dvr_buffer
.
data
)
{
void
*
mem
=
dmxdev
->
dvr_buffer
.
data
;
void
*
mem
=
dmxdev
->
dvr_buffer
.
data
;
mb
();
spin_lock_irq
(
&
dmxdev
->
lock
);
dmxdev
->
dvr_buffer
.
data
=
0
;
spin_unlock_irq
(
&
dmxdev
->
lock
);
vfree
(
mem
);
vfree
(
mem
);
}
}
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
0
;
}
...
...
@@ -265,14 +267,14 @@ dvb_dvr_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
int
ret
;
if
(
!
dmxdev
->
demux
->
write
)
return
-
EOPNOTSUPP
;
if
(
!
dmxdev
->
demux
->
write
)
return
-
EOPNOTSUPP
;
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_WRONLY
)
return
-
EINVAL
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
EINVAL
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
ret
=
dmxdev
->
demux
->
write
(
dmxdev
->
demux
,
buf
,
count
);
up
(
&
dmxdev
->
mutex
);
ret
=
dmxdev
->
demux
->
write
(
dmxdev
->
demux
,
buf
,
count
);
up
(
&
dmxdev
->
mutex
);
return
ret
;
}
...
...
@@ -283,19 +285,19 @@ dvb_dvr_read(struct file *file, char *buf, size_t count, loff_t *ppos)
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
int
ret
;
//down(&dmxdev->mutex);
ret
=
dvb_dmxdev_buffer_read
(
&
dmxdev
->
dvr_buffer
,
//down(&dmxdev->mutex);
ret
=
dvb_dmxdev_buffer_read
(
&
dmxdev
->
dvr_buffer
,
file
->
f_flags
&
O_NONBLOCK
,
buf
,
count
,
ppos
);
//up(&dmxdev->mutex);
//up(&dmxdev->mutex);
return
ret
;
}
static
inline
void
dvb_dmxdev_filter_state_set
(
dmxdev_filter_t
*
dmxdevfilter
,
int
state
)
{
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
dmxdevfilter
->
state
=
state
;
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
dmxdevfilter
->
state
=
state
;
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
}
...
...
@@ -306,25 +308,25 @@ dvb_dmxdev_set_buffer_size(dmxdev_filter_t *dmxdevfilter, unsigned long size)
void
*
mem
;
if
(
buf
->
size
==
size
)
return
0
;
if
(
dmxdevfilter
->
state
>=
DMXDEV_STATE_GO
)
return
-
EBUSY
;
return
0
;
if
(
dmxdevfilter
->
state
>=
DMXDEV_STATE_GO
)
return
-
EBUSY
;
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
mem
=
buf
->
data
;
buf
->
data
=
0
;
buf
->
size
=
size
;
buf
->
pwrite
=
buf
->
pread
=
0
;
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
if
(
mem
)
if
(
mem
)
vfree
(
mem
);
if
(
buf
->
size
)
{
mem
=
vmalloc
(
dmxdevfilter
->
buffer
.
size
);
if
(
buf
->
size
)
{
mem
=
vmalloc
(
dmxdevfilter
->
buffer
.
size
);
if
(
!
mem
)
return
-
ENOMEM
;
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
buf
->
data
=
mem
;
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
return
-
ENOMEM
;
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
buf
->
data
=
mem
;
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
}
return
0
;
}
...
...
@@ -332,23 +334,23 @@ dvb_dmxdev_set_buffer_size(dmxdev_filter_t *dmxdevfilter, unsigned long size)
static
void
dvb_dmxdev_filter_timeout
(
unsigned
long
data
)
{
dmxdev_filter_t
*
dmxdevfilter
=
(
dmxdev_filter_t
*
)
data
;
dmxdev_filter_t
*
dmxdevfilter
=
(
dmxdev_filter_t
*
)
data
;
dmxdevfilter
->
buffer
.
error
=-
ETIMEDOUT
;
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
dmxdevfilter
->
state
=
DMXDEV_STATE_TIMEDOUT
;
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
}
static
void
dvb_dmxdev_filter_timer
(
dmxdev_filter_t
*
dmxdevfilter
)
{
struct
dmx_sct_filter_params
*
para
=&
dmxdevfilter
->
params
.
sec
;
struct
dmx_sct_filter_params
*
para
=&
dmxdevfilter
->
params
.
sec
;
del_timer
(
&
dmxdevfilter
->
timer
);
if
(
para
->
timeout
)
{
dmxdevfilter
->
timer
.
function
=
dvb_dmxdev_filter_timeout
;
dmxdevfilter
->
timer
.
function
=
dvb_dmxdev_filter_timeout
;
dmxdevfilter
->
timer
.
data
=
(
unsigned
long
)
dmxdevfilter
;
dmxdevfilter
->
timer
.
expires
=
jiffies
+
1
+
(
HZ
/
2
+
HZ
*
para
->
timeout
)
/
1000
;
add_timer
(
&
dmxdevfilter
->
timer
);
...
...
@@ -356,53 +358,51 @@ dvb_dmxdev_filter_timer(dmxdev_filter_t *dmxdevfilter)
}
static
int
dvb_dmxdev_section_callback
(
u8
*
buffer1
,
size_t
buffer1_len
,
u8
*
buffer2
,
size_t
buffer2_len
,
dmx_section_filter_t
*
filter
,
dmx_success_t
success
)
dvb_dmxdev_section_callback
(
const
u8
*
buffer1
,
size_t
buffer1_len
,
const
u8
*
buffer2
,
size_t
buffer2_len
,
dmx_section_filter_t
*
filter
,
dmx_success_t
success
)
{
dmxdev_filter_t
*
dmxdevfilter
=
(
dmxdev_filter_t
*
)
filter
->
priv
;
int
ret
;
dmxdev_filter_t
*
dmxdevfilter
=
(
dmxdev_filter_t
*
)
filter
->
priv
;
int
ret
;
if
(
dmxdevfilter
->
buffer
.
error
)
{
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
return
0
;
return
0
;
}
spin_lock
(
&
dmxdevfilter
->
dev
->
lock
);
if
(
dmxdevfilter
->
state
!=
DMXDEV_STATE_GO
)
{
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
return
0
;
return
0
;
}
del_timer
(
&
dmxdevfilter
->
timer
);
dprintk
(
"dmxdev: section callback %02x %02x %02x %02x %02x %02x
\n
"
,
buffer1
[
0
],
buffer1
[
1
],
buffer1
[
2
],
buffer1
[
3
],
buffer1
[
4
],
buffer1
[
5
]);
ret
=
dvb_dmxdev_buffer_write
(
&
dmxdevfilter
->
buffer
,
buffer1
,
buffer1_len
);
if
(
ret
==
buffer1_len
)
{
ret
=
dvb_dmxdev_buffer_write
(
&
dmxdevfilter
->
buffer
,
buffer2
,
buffer2_len
);
ret
=
dvb_dmxdev_buffer_write
(
&
dmxdevfilter
->
buffer
,
buffer1
,
buffer1_len
);
if
(
ret
==
buffer1_len
)
{
ret
=
dvb_dmxdev_buffer_write
(
&
dmxdevfilter
->
buffer
,
buffer2
,
buffer2_len
);
}
if
(
ret
<
0
)
{
dmxdevfilter
->
buffer
.
pwrite
=
dmxdevfilter
->
buffer
.
pread
;
dmxdevfilter
->
buffer
.
error
=-
EOVERFLOW
;
if
(
ret
<
0
)
{
dmxdevfilter
->
buffer
.
pwrite
=
dmxdevfilter
->
buffer
.
pread
;
dmxdevfilter
->
buffer
.
error
=-
EOVERFLOW
;
}
if
(
dmxdevfilter
->
params
.
sec
.
flags
&
DMX_ONESHOT
)
dmxdevfilter
->
state
=
DMXDEV_STATE_DONE
;
dmxdevfilter
->
state
=
DMXDEV_STATE_DONE
;
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
return
0
;
}
static
int
dvb_dmxdev_ts_callback
(
u8
*
buffer1
,
size_t
buffer1_len
,
u8
*
buffer2
,
size_t
buffer2_len
,
dmx_ts_feed_t
*
feed
,
dmx_success_t
success
)
dvb_dmxdev_ts_callback
(
const
u8
*
buffer1
,
size_t
buffer1_len
,
const
u8
*
buffer2
,
size_t
buffer2_len
,
dmx_ts_feed_t
*
feed
,
dmx_success_t
success
)
{
dmxdev_filter_t
*
dmxdevfilter
=
(
dmxdev_filter_t
*
)
feed
->
priv
;
dmxdev_filter_t
*
dmxdevfilter
=
(
dmxdev_filter_t
*
)
feed
->
priv
;
dmxdev_buffer_t
*
buffer
;
int
ret
;
int
ret
;
spin_lock
(
&
dmxdevfilter
->
dev
->
lock
);
if
(
dmxdevfilter
->
params
.
pes
.
output
==
DMX_OUT_DECODER
)
{
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
...
...
@@ -410,20 +410,20 @@ dvb_dmxdev_ts_callback(u8 *buffer1, size_t buffer1_len,
}
if
(
dmxdevfilter
->
params
.
pes
.
output
==
DMX_OUT_TAP
)
buffer
=&
dmxdevfilter
->
buffer
;
buffer
=&
dmxdevfilter
->
buffer
;
else
buffer
=&
dmxdevfilter
->
dev
->
dvr_buffer
;
buffer
=&
dmxdevfilter
->
dev
->
dvr_buffer
;
if
(
buffer
->
error
)
{
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
wake_up
(
&
buffer
->
queue
);
return
0
;
return
0
;
}
ret
=
dvb_dmxdev_buffer_write
(
buffer
,
buffer1
,
buffer1_len
);
if
(
ret
==
buffer1_len
)
ret
=
dvb_dmxdev_buffer_write
(
buffer
,
buffer2
,
buffer2_len
);
if
(
ret
<
0
)
{
buffer
->
pwrite
=
buffer
->
pread
;
buffer
->
error
=-
EOVERFLOW
;
ret
=
dvb_dmxdev_buffer_write
(
buffer
,
buffer1
,
buffer1_len
);
if
(
ret
==
buffer1_len
)
ret
=
dvb_dmxdev_buffer_write
(
buffer
,
buffer2
,
buffer2_len
);
if
(
ret
<
0
)
{
buffer
->
pwrite
=
buffer
->
pread
;
buffer
->
error
=-
EOVERFLOW
;
}
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
wake_up
(
&
buffer
->
queue
);
...
...
@@ -440,49 +440,50 @@ dvb_dmxdev_feed_stop(dmxdev_filter_t *dmxdevfilter)
switch
(
dmxdevfilter
->
type
)
{
case
DMXDEV_TYPE_SEC
:
del_timer
(
&
dmxdevfilter
->
timer
);
dmxdevfilter
->
feed
.
sec
->
stop_filtering
(
dmxdevfilter
->
feed
.
sec
);
del_timer
(
&
dmxdevfilter
->
timer
);
dmxdevfilter
->
feed
.
sec
->
stop_filtering
(
dmxdevfilter
->
feed
.
sec
);
break
;
case
DMXDEV_TYPE_PES
:
dmxdevfilter
->
feed
.
ts
->
stop_filtering
(
dmxdevfilter
->
feed
.
ts
);
dmxdevfilter
->
feed
.
ts
->
stop_filtering
(
dmxdevfilter
->
feed
.
ts
);
break
;
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
return
0
;
return
0
;
}
/* start feed associated with the specified filter */
static
int
dvb_dmxdev_feed_start
(
dmxdev_filter_t
*
dmxdev
filter
)
static
int
dvb_dmxdev_feed_start
(
dmxdev_filter_t
*
filter
)
{
dvb_dmxdev_filter_state_set
(
dmxdev
filter
,
DMXDEV_STATE_GO
);
dvb_dmxdev_filter_state_set
(
filter
,
DMXDEV_STATE_GO
);
switch
(
dmxdev
filter
->
type
)
{
switch
(
filter
->
type
)
{
case
DMXDEV_TYPE_SEC
:
dmxdevfilter
->
feed
.
sec
->
start_filtering
(
dmxdev
filter
->
feed
.
sec
);
return
filter
->
feed
.
sec
->
start_filtering
(
filter
->
feed
.
sec
);
break
;
case
DMXDEV_TYPE_PES
:
dmxdevfilter
->
feed
.
ts
->
start_filtering
(
dmxdev
filter
->
feed
.
ts
);
return
filter
->
feed
.
ts
->
start_filtering
(
filter
->
feed
.
ts
);
break
;
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
return
0
;
return
0
;
}
/* restart section feed if it has filters left associated with it,
otherwise release the feed */
static
int
dvb_dmxdev_feed_restart
(
dmxdev_filter_t
*
dmxdev
filter
)
static
int
dvb_dmxdev_feed_restart
(
dmxdev_filter_t
*
filter
)
{
int
i
;
dmxdev_t
*
dmxdev
=
dmxdev
filter
->
dev
;
uint16_t
pid
=
dmxdev
filter
->
params
.
sec
.
pid
;
dmxdev_t
*
dmxdev
=
filter
->
dev
;
uint16_t
pid
=
filter
->
params
.
sec
.
pid
;
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
if
(
dmxdev
->
filter
[
i
].
state
>=
DMXDEV_STATE_GO
&&
...
...
@@ -492,36 +493,34 @@ dvb_dmxdev_feed_restart(dmxdev_filter_t *dmxdevfilter)
return
0
;
}
dmxdevfilter
->
dev
->
demux
->
release_section_feed
(
dmxdev
->
demux
,
dmxdevfilter
->
feed
.
sec
);
filter
->
dev
->
demux
->
release_section_feed
(
dmxdev
->
demux
,
filter
->
feed
.
sec
);
return
0
;
return
0
;
}
static
int
dvb_dmxdev_filter_stop
(
dmxdev_filter_t
*
dmxdevfilter
)
{
if
(
dmxdevfilter
->
state
<
DMXDEV_STATE_GO
)
return
0
;
if
(
dmxdevfilter
->
state
<
DMXDEV_STATE_GO
)
return
0
;
switch
(
dmxdevfilter
->
type
)
{
case
DMXDEV_TYPE_SEC
:
if
(
!
dmxdevfilter
->
feed
.
sec
)
break
;
dvb_dmxdev_feed_stop
(
dmxdevfilter
);
if
(
dmxdevfilter
->
filter
.
sec
)
dmxdevfilter
->
feed
.
sec
->
if
(
!
dmxdevfilter
->
feed
.
sec
)
break
;
dvb_dmxdev_feed_stop
(
dmxdevfilter
);
if
(
dmxdevfilter
->
filter
.
sec
)
dmxdevfilter
->
feed
.
sec
->
release_filter
(
dmxdevfilter
->
feed
.
sec
,
dmxdevfilter
->
filter
.
sec
);
dvb_dmxdev_feed_restart
(
dmxdevfilter
);
dvb_dmxdev_feed_restart
(
dmxdevfilter
);
dmxdevfilter
->
feed
.
sec
=
0
;
break
;
case
DMXDEV_TYPE_PES
:
if
(
!
dmxdevfilter
->
feed
.
ts
)
break
;
dvb_dmxdev_feed_stop
(
dmxdevfilter
);
dmxdevfilter
->
dev
->
demux
->
if
(
!
dmxdevfilter
->
feed
.
ts
)
break
;
dvb_dmxdev_feed_stop
(
dmxdevfilter
);
dmxdevfilter
->
dev
->
demux
->
release_ts_feed
(
dmxdevfilter
->
dev
->
demux
,
dmxdevfilter
->
feed
.
ts
);
dmxdevfilter
->
feed
.
ts
=
0
;
...
...
@@ -529,10 +528,10 @@ dvb_dmxdev_filter_stop(dmxdev_filter_t *dmxdevfilter)
default:
if
(
dmxdevfilter
->
state
==
DMXDEV_STATE_ALLOCATED
)
return
0
;
return
-
EINVAL
;
return
-
EINVAL
;
}
dmxdevfilter
->
buffer
.
pwrite
=
dmxdevfilter
->
buffer
.
pread
=
0
;
return
0
;
return
0
;
}
static
inline
int
...
...
@@ -544,58 +543,58 @@ dvb_dmxdev_filter_reset(dmxdev_filter_t *dmxdevfilter)
dmxdevfilter
->
type
=
DMXDEV_TYPE_NONE
;
dmxdevfilter
->
pid
=
0xffff
;
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_ALLOCATED
);
return
0
;
return
0
;
}
static
int
dvb_dmxdev_filter_start
(
dmxdev_filter_t
*
dmxdev
filter
)
dvb_dmxdev_filter_start
(
dmxdev_filter_t
*
filter
)
{
dmxdev_t
*
dmxdev
=
dmxdev
filter
->
dev
;
dmxdev_t
*
dmxdev
=
filter
->
dev
;
void
*
mem
;
int
ret
,
i
;
if
(
dmxdevfilter
->
state
<
DMXDEV_STATE_SET
)
return
-
EINVAL
;
if
(
dmxdevfilter
->
state
>=
DMXDEV_STATE_GO
)
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
mem
=
dmxdevfilter
->
buffer
.
data
;
if
(
!
mem
)
{
mem
=
vmalloc
(
dmxdev
filter
->
buffer
.
size
);
spin_lock_irq
(
&
dmxdev
filter
->
dev
->
lock
);
dmxdev
filter
->
buffer
.
data
=
mem
;
spin_unlock_irq
(
&
dmxdev
filter
->
dev
->
lock
);
if
(
!
dmxdev
filter
->
buffer
.
data
)
return
-
ENOMEM
;
if
(
filter
->
state
<
DMXDEV_STATE_SET
)
return
-
EINVAL
;
if
(
filter
->
state
>=
DMXDEV_STATE_GO
)
dvb_dmxdev_filter_stop
(
filter
);
if
(
!
(
mem
=
filter
->
buffer
.
data
)
)
{
mem
=
vmalloc
(
filter
->
buffer
.
size
);
spin_lock_irq
(
&
filter
->
dev
->
lock
);
filter
->
buffer
.
data
=
mem
;
spin_unlock_irq
(
&
filter
->
dev
->
lock
);
if
(
!
filter
->
buffer
.
data
)
return
-
ENOMEM
;
}
dmxdevfilter
->
buffer
.
pwrite
=
dmxdevfilter
->
buffer
.
pread
=
0
;
filter
->
buffer
.
pwrite
=
filter
->
buffer
.
pread
=
0
;
switch
(
dmxdev
filter
->
type
)
{
switch
(
filter
->
type
)
{
case
DMXDEV_TYPE_SEC
:
{
struct
dmx_sct_filter_params
*
para
=&
dmxdev
filter
->
params
.
sec
;
dmx_section_filter_t
**
secfilter
=&
dmxdev
filter
->
filter
.
sec
;
dmx_section_feed_t
**
secfeed
=&
dmxdev
filter
->
feed
.
sec
;
struct
dmx_sct_filter_params
*
para
=&
filter
->
params
.
sec
;
dmx_section_filter_t
**
secfilter
=&
filter
->
filter
.
sec
;
dmx_section_feed_t
**
secfeed
=&
filter
->
feed
.
sec
;
*
secfilter
=
0
;
*
secfeed
=
0
;
/* find active filter/feed with same PID */
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
if
(
dmxdev
->
filter
[
i
].
state
>=
DMXDEV_STATE_GO
&&
dmxdev
->
filter
[
i
].
pid
==
para
->
pid
)
{
if
(
dmxdev
->
filter
[
i
].
type
!=
DMXDEV_TYPE_SEC
)
return
-
EBUSY
;
*
secfeed
=
dmxdev
->
filter
[
i
].
feed
.
sec
;
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
{
if
(
dmxdev
->
filter
[
i
].
state
>=
DMXDEV_STATE_GO
&&
dmxdev
->
filter
[
i
].
pid
==
para
->
pid
&&
dmxdev
->
filter
[
i
].
type
==
DMXDEV_TYPE_SEC
)
{
*
secfeed
=
dmxdev
->
filter
[
i
].
feed
.
sec
;
break
;
}
}
/* if no feed found, try to allocate new one */
if
(
!*
secfeed
)
{
ret
=
dmxdev
->
demux
->
allocate_section_feed
(
dmxdev
->
demux
,
secfeed
,
dvb_dmxdev_section_callback
);
secfeed
,
dvb_dmxdev_section_callback
);
if
(
ret
<
0
)
{
printk
(
"DVB (%s): could not alloc feed
\n
"
,
__FUNCTION__
);
...
...
@@ -608,22 +607,23 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
if
(
ret
<
0
)
{
printk
(
"DVB (%s): could not set feed
\n
"
,
__FUNCTION__
);
dvb_dmxdev_feed_restart
(
dmxdev
filter
);
dvb_dmxdev_feed_restart
(
filter
);
return
ret
;
}
}
else
{
dvb_dmxdev_feed_stop
(
filter
);
}
else
dvb_dmxdev_feed_stop
(
dmxdevfilter
);
ret
=
(
*
secfeed
)
->
allocate_filter
(
*
secfeed
,
secfilter
);
if
(
ret
<
0
)
{
dvb_dmxdev_feed_restart
(
dmxdevfilter
);
dmxdevfilter
->
feed
.
sec
->
start_filtering
(
*
secfeed
);
if
(
ret
<
0
)
{
dvb_dmxdev_feed_restart
(
filter
);
filter
->
feed
.
sec
->
start_filtering
(
*
secfeed
);
dprintk
(
"could not get filter
\n
"
);
return
ret
;
}
(
*
secfilter
)
->
priv
=
(
void
*
)
dmxdev
filter
;
(
*
secfilter
)
->
priv
=
filter
;
memcpy
(
&
((
*
secfilter
)
->
filter_value
[
3
]),
&
(
para
->
filter
.
filter
[
1
]),
DMX_FILTER_SIZE
-
1
);
...
...
@@ -638,23 +638,28 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
(
*
secfilter
)
->
filter_mask
[
1
]
=
0
;
(
*
secfilter
)
->
filter_mask
[
2
]
=
0
;
dmxdevfilter
->
todo
=
0
;
dmxdevfilter
->
feed
.
sec
->
start_filtering
(
dmxdevfilter
->
feed
.
sec
);
dvb_dmxdev_filter_timer
(
dmxdevfilter
);
filter
->
todo
=
0
;
ret
=
filter
->
feed
.
sec
->
start_filtering
(
filter
->
feed
.
sec
);
if
(
ret
<
0
)
return
ret
;
dvb_dmxdev_filter_timer
(
filter
);
break
;
}
case
DMXDEV_TYPE_PES
:
{
struct
timespec
timeout
=
{
0
};
struct
dmx_pes_filter_params
*
para
=&
dmxdev
filter
->
params
.
pes
;
struct
dmx_pes_filter_params
*
para
=
&
filter
->
params
.
pes
;
dmx_output_t
otype
;
int
ret
;
int
ts_type
;
dmx_ts_pes_t
ts_pes
;
dmx_ts_feed_t
**
tsfeed
=&
dmxdev
filter
->
feed
.
ts
;
dmx_ts_feed_t
**
tsfeed
=
&
filter
->
feed
.
ts
;
dmxdevfilter
->
feed
.
ts
=
0
;
filter
->
feed
.
ts
=
0
;
otype
=
para
->
output
;
ts_pes
=
(
dmx_ts_pes_t
)
para
->
pes_type
;
...
...
@@ -664,11 +669,11 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
else
ts_type
=
0
;
if
(
otype
==
DMX_OUT_TS_TAP
)
ts_type
|=
TS_PACKET
;
if
(
otype
==
DMX_OUT_TS_TAP
)
ts_type
|=
TS_PACKET
;
if
(
otype
==
DMX_OUT_TAP
)
ts_type
|=
TS_PAYLOAD_ONLY
|
TS_PACKET
;
if
(
otype
==
DMX_OUT_TAP
)
ts_type
|=
TS_PAYLOAD_ONLY
|
TS_PACKET
;
ret
=
dmxdev
->
demux
->
allocate_ts_feed
(
dmxdev
->
demux
,
tsfeed
,
...
...
@@ -676,75 +681,97 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
if
(
ret
<
0
)
return
ret
;
(
*
tsfeed
)
->
priv
=
(
void
*
)
dmxdevfilter
;
ret
=
(
*
tsfeed
)
->
set
(
*
tsfeed
,
para
->
pid
,
ts_type
,
ts_pes
,
188
,
32768
,
0
,
timeout
);
if
(
ret
<
0
)
{
(
*
tsfeed
)
->
priv
=
(
void
*
)
filter
;
ret
=
(
*
tsfeed
)
->
set
(
*
tsfeed
,
para
->
pid
,
ts_type
,
ts_pes
,
188
,
32768
,
0
,
timeout
);
if
(
ret
<
0
)
{
dmxdev
->
demux
->
release_ts_feed
(
dmxdev
->
demux
,
*
tsfeed
);
return
ret
;
}
dmxdevfilter
->
feed
.
ts
->
start_filtering
(
dmxdevfilter
->
feed
.
ts
);
ret
=
filter
->
feed
.
ts
->
start_filtering
(
filter
->
feed
.
ts
);
if
(
ret
<
0
)
return
ret
;
break
;
}
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_GO
);
return
0
;
dvb_dmxdev_filter_state_set
(
filter
,
DMXDEV_STATE_GO
);
return
0
;
}
static
int
dvb_demux_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
int
i
;
dmxdev_filter_t
*
dmxdevfilter
;
int
i
;
dmxdev_filter_t
*
dmxdevfilter
;
if
(
!
dmxdev
->
filter
)
return
-
EINVAL
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
EINVAL
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
if
(
dmxdev
->
filter
[
i
].
state
==
DMXDEV_STATE_FREE
)
break
;
if
(
i
==
dmxdev
->
filternum
)
{
up
(
&
dmxdev
->
mutex
);
return
-
EMFILE
;
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
if
(
dmxdev
->
filter
[
i
].
state
==
DMXDEV_STATE_FREE
)
break
;
if
(
i
==
dmxdev
->
filternum
)
{
up
(
&
dmxdev
->
mutex
);
return
-
EMFILE
;
}
dmxdevfilter
=&
dmxdev
->
filter
[
i
];
dmxdevfilter
->
dvbdev
=
dmxdev
->
dvbdev
;
dmxdevfilter
=&
dmxdev
->
filter
[
i
];
sema_init
(
&
dmxdevfilter
->
mutex
,
1
);
dmxdevfilter
->
dvbdev
=
dmxdev
->
dvbdev
;
file
->
private_data
=
dmxdevfilter
;
dvb_dmxdev_buffer_init
(
&
dmxdevfilter
->
buffer
);
dmxdevfilter
->
type
=
DMXDEV_TYPE_NONE
;
dmxdevfilter
->
type
=
DMXDEV_TYPE_NONE
;
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_ALLOCATED
);
dmxdevfilter
->
feed
.
ts
=
0
;
init_timer
(
&
dmxdevfilter
->
timer
);
up
(
&
dmxdev
->
mutex
);
return
0
;
up
(
&
dmxdev
->
mutex
);
return
0
;
}
int
dvb_dmxdev_filter_free
(
dmxdev_t
*
dmxdev
,
dmxdev_filter_t
*
dmxdevfilter
)
static
int
dvb_dmxdev_filter_free
(
dmxdev_t
*
dmxdev
,
dmxdev_filter_t
*
dmxdevfilter
)
{
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
if
(
down_interruptible
(
&
dmxdevfilter
->
mutex
))
{
up
(
&
dmxdev
->
mutex
);
return
-
ERESTARTSYS
;
}
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
dvb_dmxdev_filter_reset
(
dmxdevfilter
);
if
(
dmxdevfilter
->
buffer
.
data
)
{
void
*
mem
=
dmxdevfilter
->
buffer
.
data
;
if
(
dmxdevfilter
->
buffer
.
data
)
{
void
*
mem
=
dmxdevfilter
->
buffer
.
data
;
spin_lock_irq
(
&
dmxdev
->
lock
);
spin_lock_irq
(
&
dmxdev
->
lock
);
dmxdevfilter
->
buffer
.
data
=
0
;
spin_unlock_irq
(
&
dmxdev
->
lock
);
spin_unlock_irq
(
&
dmxdev
->
lock
);
vfree
(
mem
);
}
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_FREE
);
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
up
(
&
dmxdevfilter
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
0
;
return
0
;
}
static
inline
void
...
...
@@ -759,83 +786,83 @@ invert_mode(dmx_filter_t *filter)
static
int
dvb_dmxdev_filter_set
(
dmxdev_t
*
dmxdev
,
dmxdev_filter_t
*
dmxdevfilter
,
dmxdev_filter_t
*
dmxdevfilter
,
struct
dmx_sct_filter_params
*
params
)
{
dprintk
(
"function : %s
\n
"
,
__FUNCTION__
);
dprintk
(
"function : %s
\n
"
,
__FUNCTION__
);
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
dmxdevfilter
->
type
=
DMXDEV_TYPE_SEC
;
dmxdevfilter
->
pid
=
params
->
pid
;
dmxdevfilter
->
type
=
DMXDEV_TYPE_SEC
;
dmxdevfilter
->
pid
=
params
->
pid
;
memcpy
(
&
dmxdevfilter
->
params
.
sec
,
params
,
sizeof
(
struct
dmx_sct_filter_params
));
invert_mode
(
&
dmxdevfilter
->
params
.
sec
.
filter
);
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_SET
);
if
(
params
->
flags
&
DMX_IMMEDIATE_START
)
return
dvb_dmxdev_filter_start
(
dmxdevfilter
);
if
(
params
->
flags
&
DMX_IMMEDIATE_START
)
return
dvb_dmxdev_filter_start
(
dmxdevfilter
);
return
0
;
return
0
;
}
static
int
dvb_dmxdev_pes_filter_set
(
dmxdev_t
*
dmxdev
,
dmxdev_filter_t
*
dmxdevfilter
,
struct
dmx_pes_filter_params
*
params
)
dmxdev_filter_t
*
dmxdevfilter
,
struct
dmx_pes_filter_params
*
params
)
{
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
if
(
params
->
pes_type
>
DMX_PES_OTHER
||
params
->
pes_type
<
0
)
return
-
EINVAL
;
return
-
EINVAL
;
dmxdevfilter
->
type
=
DMXDEV_TYPE_PES
;
dmxdevfilter
->
pid
=
params
->
pid
;
dmxdevfilter
->
type
=
DMXDEV_TYPE_PES
;
dmxdevfilter
->
pid
=
params
->
pid
;
memcpy
(
&
dmxdevfilter
->
params
,
params
,
sizeof
(
struct
dmx_pes_filter_params
));
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_SET
);
if
(
params
->
flags
&
DMX_IMMEDIATE_START
)
return
dvb_dmxdev_filter_start
(
dmxdevfilter
);
if
(
params
->
flags
&
DMX_IMMEDIATE_START
)
return
dvb_dmxdev_filter_start
(
dmxdevfilter
);
return
0
;
return
0
;
}
static
ssize_t
dvb_dmxdev_read_sec
(
dmxdev_filter_t
*
dfil
,
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
int
result
,
hcount
;
int
result
,
hcount
;
int
done
=
0
;
if
(
dfil
->
todo
<=
0
)
{
hcount
=
3
+
dfil
->
todo
;
if
(
hcount
>
count
)
hcount
=
count
;
hcount
=
3
+
dfil
->
todo
;
if
(
hcount
>
count
)
hcount
=
count
;
result
=
dvb_dmxdev_buffer_read
(
&
dfil
->
buffer
,
file
->
f_flags
&
O_NONBLOCK
,
buf
,
hcount
,
ppos
);
if
(
result
<
0
)
{
dfil
->
todo
=
0
;
return
result
;
return
result
;
}
if
(
copy_from_user
(
dfil
->
secheader
-
dfil
->
todo
,
buf
,
result
))
return
-
EFAULT
;
return
-
EFAULT
;
buf
+=
result
;
done
=
result
;
count
-=
result
;
dfil
->
todo
-=
result
;
if
(
dfil
->
todo
>-
3
)
return
done
;
return
done
;
dfil
->
todo
=
((
dfil
->
secheader
[
1
]
<<
8
)
|
dfil
->
secheader
[
2
])
&
0xfff
;
if
(
!
count
)
return
done
;
return
done
;
}
if
(
count
>
dfil
->
todo
)
count
=
dfil
->
todo
;
result
=
dvb_dmxdev_buffer_read
(
&
dfil
->
buffer
,
file
->
f_flags
&
O_NONBLOCK
,
count
=
dfil
->
todo
;
result
=
dvb_dmxdev_buffer_read
(
&
dfil
->
buffer
,
file
->
f_flags
&
O_NONBLOCK
,
buf
,
count
,
ppos
);
if
(
result
<
0
)
return
result
;
return
result
;
dfil
->
todo
-=
result
;
return
(
result
+
done
);
}
...
...
@@ -844,19 +871,20 @@ dvb_dmxdev_read_sec(dmxdev_filter_t *dfil, struct file *file,
ssize_t
dvb_demux_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
dmxdev_filter_t
*
dmxdevfilter
=
dvb_dmxdev_file_to_filter
(
file
);
//dmxdev_t *dmxdev=dmxdevfilter->dev;
dmxdev_filter_t
*
dmxdevfilter
=
dvb_dmxdev_file_to_filter
(
file
);
int
ret
=
0
;
// semaphore should not be necessary (I hope ...)
//down(&dmxdev->mutex);
if
(
down_interruptible
(
&
dmxdevfilter
->
mutex
))
return
-
ERESTARTSYS
;
if
(
dmxdevfilter
->
type
==
DMXDEV_TYPE_SEC
)
ret
=
dvb_dmxdev_read_sec
(
dmxdevfilter
,
file
,
buf
,
count
,
ppos
);
ret
=
dvb_dmxdev_read_sec
(
dmxdevfilter
,
file
,
buf
,
count
,
ppos
);
else
ret
=
dvb_dmxdev_buffer_read
(
&
dmxdevfilter
->
buffer
,
ret
=
dvb_dmxdev_buffer_read
(
&
dmxdevfilter
->
buffer
,
file
->
f_flags
&
O_NONBLOCK
,
buf
,
count
,
ppos
);
//up(&dmxdev->mutex);
up
(
&
dmxdevfilter
->
mutex
);
return
ret
;
}
...
...
@@ -864,102 +892,131 @@ dvb_demux_read(struct file *file, char *buf, size_t count, loff_t *ppos)
static
int
dvb_demux_do_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
void
*
parg
)
{
dmxdev_filter_t
*
dmxdevfilter
=
dvb_dmxdev_file_to_filter
(
file
);
dmxdev_filter_t
*
dmxdevfilter
=
dvb_dmxdev_file_to_filter
(
file
);
dmxdev_t
*
dmxdev
=
dmxdevfilter
->
dev
;
unsigned
long
arg
=
(
unsigned
long
)
parg
;
unsigned
long
arg
=
(
unsigned
long
)
parg
;
int
ret
=
0
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
switch
(
cmd
)
{
case
DMX_START
:
if
(
dmxdevfilter
->
state
<
DMXDEV_STATE_SET
)
ret
=-
EINVAL
;
case
DMX_START
:
if
(
down_interruptible
(
&
dmxdevfilter
->
mutex
))
{
up
(
&
dmxdev
->
mutex
);
return
-
ERESTARTSYS
;
}
if
(
dmxdevfilter
->
state
<
DMXDEV_STATE_SET
)
ret
=
-
EINVAL
;
else
ret
=
dvb_dmxdev_filter_start
(
dmxdevfilter
);
ret
=
dvb_dmxdev_filter_start
(
dmxdevfilter
);
up
(
&
dmxdevfilter
->
mutex
);
break
;
case
DMX_STOP
:
case
DMX_STOP
:
if
(
down_interruptible
(
&
dmxdevfilter
->
mutex
))
{
up
(
&
dmxdev
->
mutex
);
return
-
ERESTARTSYS
;
}
ret
=
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
up
(
&
dmxdevfilter
->
mutex
);
break
;
case
DMX_SET_FILTER
:
ret
=
dvb_dmxdev_filter_set
(
dmxdev
,
dmxdevfilter
,
if
(
down_interruptible
(
&
dmxdevfilter
->
mutex
))
{
up
(
&
dmxdev
->
mutex
);
return
-
ERESTARTSYS
;
}
ret
=
dvb_dmxdev_filter_set
(
dmxdev
,
dmxdevfilter
,
(
struct
dmx_sct_filter_params
*
)
parg
);
up
(
&
dmxdevfilter
->
mutex
);
break
;
case
DMX_SET_PES_FILTER
:
if
(
down_interruptible
(
&
dmxdevfilter
->
mutex
))
{
up
(
&
dmxdev
->
mutex
);
return
-
ERESTARTSYS
;
}
ret
=
dvb_dmxdev_pes_filter_set
(
dmxdev
,
dmxdevfilter
,
(
struct
dmx_pes_filter_params
*
)
parg
);
up
(
&
dmxdevfilter
->
mutex
);
break
;
case
DMX_SET_BUFFER_SIZE
:
ret
=
dvb_dmxdev_set_buffer_size
(
dmxdevfilter
,
arg
);
if
(
down_interruptible
(
&
dmxdevfilter
->
mutex
))
{
up
(
&
dmxdev
->
mutex
);
return
-
ERESTARTSYS
;
}
ret
=
dvb_dmxdev_set_buffer_size
(
dmxdevfilter
,
arg
);
up
(
&
dmxdevfilter
->
mutex
);
break
;
case
DMX_GET_EVENT
:
break
;
case
DMX_GET_EVENT
:
break
;
case
DMX_GET_PES_PIDS
:
case
DMX_GET_PES_PIDS
:
if
(
!
dmxdev
->
demux
->
get_pes_pids
)
{
ret
=-
EINVAL
;
ret
=-
EINVAL
;
break
;
}
dmxdev
->
demux
->
get_pes_pids
(
dmxdev
->
demux
,
(
uint16_t
*
)
parg
);
break
;
break
;
case
DMX_GET_STC
:
if
(
!
dmxdev
->
demux
->
get_stc
)
{
ret
=-
EINVAL
;
break
;
}
ret
=
dmxdev
->
demux
->
get_stc
(
dmxdev
->
demux
,
((
struct
dmx_stc
*
)
parg
)
->
num
,
&
((
struct
dmx_stc
*
)
parg
)
->
stc
,
&
((
struct
dmx_stc
*
)
parg
)
->
base
);
break
;
default:
ret
=-
EINVAL
;
ret
=-
EINVAL
;
}
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
ret
;
}
static
int
dvb_demux_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
return
video
_usercopy
(
inode
,
file
,
cmd
,
arg
,
dvb_demux_do_ioctl
);
return
dvb
_usercopy
(
inode
,
file
,
cmd
,
arg
,
dvb_demux_do_ioctl
);
}
static
unsigned
int
dvb_demux_poll
(
struct
file
*
file
,
poll_table
*
wait
)
static
unsigned
int
dvb_demux_poll
(
struct
file
*
file
,
poll_table
*
wait
)
{
dmxdev_filter_t
*
dmxdevfilter
=
dvb_dmxdev_file_to_filter
(
file
);
dmxdev_filter_t
*
dmxdevfilter
=
dvb_dmxdev_file_to_filter
(
file
);
unsigned
int
mask
=
0
;
if
(
!
dmxdevfilter
)
return
-
EINVAL
;
if
(
dmxdevfilter
->
state
==
DMXDEV_STATE_FREE
)
return
0
;
if
(
dmxdevfilter
->
buffer
.
error
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
|
POLLERR
);
if
(
dmxdevfilter
->
buffer
.
pread
!=
dmxdevfilter
->
buffer
.
pwrite
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
if
(
dmxdevfilter
->
state
!=
DMXDEV_STATE_GO
)
return
0
;
return
-
EINVAL
;
poll_wait
(
file
,
&
dmxdevfilter
->
buffer
.
queue
,
wait
);
if
(
dmxdevfilter
->
state
==
DMXDEV_STATE_FREE
)
return
0
;
if
(
dmxdevfilter
->
state
!=
DMXDEV_STATE_GO
&&
dmxdevfilter
->
state
!=
DMXDEV_STATE_DONE
)
return
0
;
if
(
dmxdevfilter
->
buffer
.
error
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
|
POLLERR
);
mask
|=
(
POLLIN
|
POLLRDNORM
|
POLLPRI
|
POLLERR
);
if
(
dmxdevfilter
->
buffer
.
pread
!=
dmxdevfilter
->
buffer
.
pwrite
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
if
(
dmxdevfilter
->
buffer
.
pread
!=
dmxdevfilter
->
buffer
.
pwrite
)
mask
|=
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
return
0
;
return
mask
;
}
static
int
dvb_demux_release
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
dvb_demux_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
dmxdev_filter_t
*
dmxdevfilter
=
dvb_dmxdev_file_to_filter
(
file
);
dmxdev_t
*
dmxdev
=
dmxdevfilter
->
dev
;
dmxdev_filter_t
*
dmxdevfilter
=
dvb_dmxdev_file_to_filter
(
file
);
dmxdev_t
*
dmxdev
=
dmxdevfilter
->
dev
;
return
dvb_dmxdev_filter_free
(
dmxdev
,
dmxdevfilter
);
}
...
...
@@ -988,64 +1045,62 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
int
ret
=
0
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
switch
(
cmd
)
{
case
DMX_SET_BUFFER_SIZE
:
// FIXME: implement
ret
=
0
;
ret
=
0
;
break
;
default:
ret
=-
EINVAL
;
ret
=-
EINVAL
;
}
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
ret
;
}
static
int
dvb_dvr_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
return
video
_usercopy
(
inode
,
file
,
cmd
,
arg
,
dvb_dvr_do_ioctl
);
return
dvb
_usercopy
(
inode
,
file
,
cmd
,
arg
,
dvb_dvr_do_ioctl
);
}
static
unsigned
int
dvb_dvr_poll
(
struct
file
*
file
,
poll_table
*
wait
)
static
unsigned
int
dvb_dvr_poll
(
struct
file
*
file
,
poll_table
*
wait
)
{
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
unsigned
int
mask
=
0
;
dprintk
(
"function : %s
\n
"
,
__FUNCTION__
);
dprintk
(
"function : %s
\n
"
,
__FUNCTION__
);
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDONLY
)
{
if
(
dmxdev
->
dvr_buffer
.
error
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
|
POLLERR
);
poll_wait
(
file
,
&
dmxdev
->
dvr_buffer
.
queue
,
wait
);
if
(
dmxdev
->
dvr_buffer
.
pread
!=
dmxdev
->
dvr_buffer
.
pwrite
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
poll_wait
(
file
,
&
dmxdev
->
dvr_buffer
.
queue
,
wait
);
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDONLY
)
{
if
(
dmxdev
->
dvr_buffer
.
error
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
|
POLLERR
);
mask
|=
(
POLLIN
|
POLLRDNORM
|
POLLPRI
|
POLLERR
);
if
(
dmxdev
->
dvr_buffer
.
pread
!=
dmxdev
->
dvr_buffer
.
pwrite
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
return
0
;
mask
|=
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
}
else
return
(
POLLOUT
|
POLLWRNORM
|
POLLPRI
);
mask
|=
(
POLLOUT
|
POLLWRNORM
|
POLLPRI
);
return
mask
;
}
static
struct
file_operations
dvb_dvr_fops
=
{
static
struct
file_operations
dvb_dvr_fops
=
{
.
owner
=
THIS_MODULE
,
.
read
=
dvb_dvr_read
,
.
write
=
dvb_dvr_write
,
.
ioctl
=
dvb_dvr_ioctl
,
.
open
=
dvb_dvr_open
,
.
release
=
dvb_dvr_release
,
.
poll
=
dvb_dvr_poll
,
.
poll
=
dvb_dvr_poll
,
};
static
struct
dvb_device
dvbdev_dvr
=
{
...
...
@@ -1058,37 +1113,38 @@ static struct dvb_device dvbdev_dvr = {
int
dvb_dmxdev_init
(
dmxdev_t
*
dmxdev
,
struct
dvb_adapter
*
dvb_adapter
)
{
int
i
;
int
i
;
if
(
dmxdev
->
demux
->
open
(
dmxdev
->
demux
)
<
0
)
return
-
EUSERS
;
dmxdev
->
filter
=
vmalloc
(
dmxdev
->
filternum
*
sizeof
(
dmxdev_filter_t
));
if
(
!
dmxdev
->
filter
)
return
-
ENOMEM
;
return
-
ENOMEM
;
dmxdev
->
dvr
=
vmalloc
(
dmxdev
->
filternum
*
sizeof
(
dmxdev_dvr_t
));
if
(
!
dmxdev
->
dvr
)
{
vfree
(
dmxdev
->
filter
);
dmxdev
->
filter
=
0
;
return
-
ENOMEM
;
return
-
ENOMEM
;
}
sema_init
(
&
dmxdev
->
mutex
,
1
);
sema_init
(
&
dmxdev
->
mutex
,
1
);
spin_lock_init
(
&
dmxdev
->
lock
);
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
{
dmxdev
->
filter
[
i
].
dev
=
dmxdev
;
dmxdev
->
filter
[
i
].
buffer
.
data
=
0
;
dvb_dmxdev_filter_state_set
(
&
dmxdev
->
filter
[
i
],
DMXDEV_STATE_FREE
);
dmxdev
->
dvr
[
i
].
dev
=
dmxdev
;
dmxdev
->
dvr
[
i
].
buffer
.
data
=
0
;
dvb_dmxdev_filter_state_set
(
&
dmxdev
->
filter
[
i
],
DMXDEV_STATE_FREE
);
dvb_dmxdev_dvr_state_set
(
&
dmxdev
->
dvr
[
i
],
DMXDEV_STATE_FREE
);
dmxdev
->
filter
[
i
].
dev
=
dmxdev
;
dmxdev
->
filter
[
i
].
buffer
.
data
=
0
;
dvb_dmxdev_filter_state_set
(
&
dmxdev
->
filter
[
i
],
DMXDEV_STATE_FREE
);
dmxdev
->
dvr
[
i
].
dev
=
dmxdev
;
dmxdev
->
dvr
[
i
].
buffer
.
data
=
0
;
dvb_dmxdev_filter_state_set
(
&
dmxdev
->
filter
[
i
],
DMXDEV_STATE_FREE
);
dvb_dmxdev_dvr_state_set
(
&
dmxdev
->
dvr
[
i
],
DMXDEV_STATE_FREE
);
}
dvb_register_device
(
dvb_adapter
,
&
dmxdev
->
dvbdev
,
&
dvbdev_demux
,
dmxdev
,
DVB_DEVICE_DEMUX
);
dvb_register_device
(
dvb_adapter
,
&
dmxdev
->
dvr_dvbdev
,
&
dvbdev_dvr
,
dmxdev
,
DVB_DEVICE_DVR
);
dvb_dmxdev_buffer_init
(
&
dmxdev
->
dvr_buffer
);
MOD_INC_USE_COUNT
;
/* fixme: is this correct? */
try_module_get
(
THIS_MODULE
);
return
0
;
}
...
...
@@ -1098,15 +1154,16 @@ dvb_dmxdev_release(dmxdev_t *dmxdev)
dvb_unregister_device
(
dmxdev
->
dvbdev
);
dvb_unregister_device
(
dmxdev
->
dvr_dvbdev
);
if
(
dmxdev
->
filter
)
{
vfree
(
dmxdev
->
filter
);
vfree
(
dmxdev
->
filter
);
dmxdev
->
filter
=
0
;
}
if
(
dmxdev
->
dvr
)
{
vfree
(
dmxdev
->
dvr
);
vfree
(
dmxdev
->
dvr
);
dmxdev
->
dvr
=
0
;
}
dmxdev
->
demux
->
close
(
dmxdev
->
demux
);
MOD_DEC_USE_COUNT
;
dmxdev
->
demux
->
close
(
dmxdev
->
demux
);
/* fixme: is this correct? */
module_put
(
THIS_MODULE
);
}
drivers/media/dvb/dvb-core/dmxdev.h
View file @
28003225
...
...
@@ -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
;
...
...
drivers/media/dvb/dvb-core/dvb_demux.c
View file @
28003225
...
...
@@ -2,8 +2,8 @@
* dvb_demux.c - DVB kernel demux API
*
* Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
*
& Marcus Metzler <marcus@convergence.de>
*
for convergence integrated media GmbH
*
& Marcus Metzler <marcus@convergence.de>
*
for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
...
...
@@ -27,27 +27,36 @@
#include <linux/version.h>
#include <asm/uaccess.h>
#include "compat.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#include "compat.h"
#else
#include <linux/crc32.h>
#endif
#include "dvb_demux.h"
#define NOBUFS
LIST_HEAD
(
dmx_muxs
);
int
dmx_register_demux
(
dmx_demux_t
*
demux
)
{
struct
list_head
*
pos
,
*
head
=&
dmx_muxs
;
struct
list_head
*
pos
;
if
(
!
(
demux
->
id
&&
demux
->
vendor
&&
demux
->
model
))
return
-
EINVAL
;
list_for_each
(
pos
,
head
)
{
if
(
!
strcmp
(
DMX_DIR_ENTRY
(
pos
)
->
id
,
demux
->
id
))
return
-
EEXIST
;
return
-
EINVAL
;
list_for_each
(
pos
,
&
dmx_muxs
)
{
if
(
!
strcmp
(
DMX_DIR_ENTRY
(
pos
)
->
id
,
demux
->
id
))
return
-
EEXIST
;
}
demux
->
users
=
0
;
list_add
(
&
(
demux
->
reg_list
),
head
);
MOD_INC_USE_COUNT
;
demux
->
users
=
0
;
list_add
(
&
demux
->
reg_list
,
&
dmx_muxs
);
/* fixme: is this correct? */
try_module_get
(
THIS_MODULE
);
return
0
;
}
...
...
@@ -55,25 +64,25 @@ int dmx_unregister_demux(dmx_demux_t* demux)
{
struct
list_head
*
pos
,
*
n
,
*
head
=&
dmx_muxs
;
list_for_each_safe
(
pos
,
n
,
head
)
{
if
(
DMX_DIR_ENTRY
(
pos
)
==
demux
)
{
if
(
demux
->
users
>
0
)
return
-
EINVAL
;
list_del
(
pos
);
MOD_DEC_USE_COUNT
;
list_for_each_safe
(
pos
,
n
,
head
)
{
if
(
DMX_DIR_ENTRY
(
pos
)
==
demux
)
{
if
(
demux
->
users
>
0
)
return
-
EINVAL
;
list_del
(
pos
);
/* fixme: is this correct? */
module_put
(
THIS_MODULE
);
return
0
;
}
}
return
-
ENODEV
;
}
struct
list_head
*
dmx_get_demuxes
(
void
)
{
if
(
list_empty
(
&
dmx_muxs
))
return
NULL
;
if
(
list_empty
(
&
dmx_muxs
))
return
NULL
;
return
&
dmx_muxs
;
}
...
...
@@ -82,628 +91,661 @@ struct list_head *dmx_get_demuxes(void)
* static inlined helper functions
******************************************************************************/
static
inline
u16
section_length
(
const
u8
*
buf
)
static
inline
u16
section_length
(
const
u8
*
buf
)
{
return
3
+
((
buf
[
1
]
&
0x0f
)
<<
8
)
+
buf
[
2
];
return
3
+
((
buf
[
1
]
&
0x0f
)
<<
8
)
+
buf
[
2
];
}
static
inline
u16
ts_pid
(
const
u8
*
buf
)
static
inline
u16
ts_pid
(
const
u8
*
buf
)
{
return
((
buf
[
1
]
&
0x1f
)
<<
8
)
+
buf
[
2
];
return
((
buf
[
1
]
&
0x1f
)
<<
8
)
+
buf
[
2
];
}
static
inline
int
payload
(
const
u8
*
tsp
)
static
inline
int
payload
(
const
u8
*
tsp
)
{
if
(
!
(
tsp
[
3
]
&
0x10
))
// no payload?
return
0
;
if
(
tsp
[
3
]
&
0x20
)
{
// adaptation field?
if
(
!
(
tsp
[
3
]
&
0x10
))
// no payload?
return
0
;
if
(
tsp
[
3
]
&
0x20
)
{
// adaptation field?
if
(
tsp
[
4
]
>
183
)
// corrupted data?
return
0
;
else
return
184
-
1
-
tsp
[
4
];
}
return
184
;
return
184
;
}
static
u32
dvb_crc_table
[
256
]
=
{
0x00000000
,
0x04c11db7
,
0x09823b6e
,
0x0d4326d9
,
0x130476dc
,
0x17c56b6b
,
0x1a864db2
,
0x1e475005
,
0x2608edb8
,
0x22c9f00f
,
0x2f8ad6d6
,
0x2b4bcb61
,
0x350c9b64
,
0x31cd86d3
,
0x3c8ea00a
,
0x384fbdbd
,
0x4c11db70
,
0x48d0c6c7
,
0x4593e01e
,
0x4152fda9
,
0x5f15adac
,
0x5bd4b01b
,
0x569796c2
,
0x52568b75
,
0x6a1936c8
,
0x6ed82b7f
,
0x639b0da6
,
0x675a1011
,
0x791d4014
,
0x7ddc5da3
,
0x709f7b7a
,
0x745e66cd
,
0x9823b6e0
,
0x9ce2ab57
,
0x91a18d8e
,
0x95609039
,
0x8b27c03c
,
0x8fe6dd8b
,
0x82a5fb52
,
0x8664e6e5
,
0xbe2b5b58
,
0xbaea46ef
,
0xb7a96036
,
0xb3687d81
,
0xad2f2d84
,
0xa9ee3033
,
0xa4ad16ea
,
0xa06c0b5d
,
0xd4326d90
,
0xd0f37027
,
0xddb056fe
,
0xd9714b49
,
0xc7361b4c
,
0xc3f706fb
,
0xceb42022
,
0xca753d95
,
0xf23a8028
,
0xf6fb9d9f
,
0xfbb8bb46
,
0xff79a6f1
,
0xe13ef6f4
,
0xe5ffeb43
,
0xe8bccd9a
,
0xec7dd02d
,
0x34867077
,
0x30476dc0
,
0x3d044b19
,
0x39c556ae
,
0x278206ab
,
0x23431b1c
,
0x2e003dc5
,
0x2ac12072
,
0x128e9dcf
,
0x164f8078
,
0x1b0ca6a1
,
0x1fcdbb16
,
0x018aeb13
,
0x054bf6a4
,
0x0808d07d
,
0x0cc9cdca
,
0x7897ab07
,
0x7c56b6b0
,
0x71159069
,
0x75d48dde
,
0x6b93dddb
,
0x6f52c06c
,
0x6211e6b5
,
0x66d0fb02
,
0x5e9f46bf
,
0x5a5e5b08
,
0x571d7dd1
,
0x53dc6066
,
0x4d9b3063
,
0x495a2dd4
,
0x44190b0d
,
0x40d816ba
,
0xaca5c697
,
0xa864db20
,
0xa527fdf9
,
0xa1e6e04e
,
0xbfa1b04b
,
0xbb60adfc
,
0xb6238b25
,
0xb2e29692
,
0x8aad2b2f
,
0x8e6c3698
,
0x832f1041
,
0x87ee0df6
,
0x99a95df3
,
0x9d684044
,
0x902b669d
,
0x94ea7b2a
,
0xe0b41de7
,
0xe4750050
,
0xe9362689
,
0xedf73b3e
,
0xf3b06b3b
,
0xf771768c
,
0xfa325055
,
0xfef34de2
,
0xc6bcf05f
,
0xc27dede8
,
0xcf3ecb31
,
0xcbffd686
,
0xd5b88683
,
0xd1799b34
,
0xdc3abded
,
0xd8fba05a
,
0x690ce0ee
,
0x6dcdfd59
,
0x608edb80
,
0x644fc637
,
0x7a089632
,
0x7ec98b85
,
0x738aad5c
,
0x774bb0eb
,
0x4f040d56
,
0x4bc510e1
,
0x46863638
,
0x42472b8f
,
0x5c007b8a
,
0x58c1663d
,
0x558240e4
,
0x51435d53
,
0x251d3b9e
,
0x21dc2629
,
0x2c9f00f0
,
0x285e1d47
,
0x36194d42
,
0x32d850f5
,
0x3f9b762c
,
0x3b5a6b9b
,
0x0315d626
,
0x07d4cb91
,
0x0a97ed48
,
0x0e56f0ff
,
0x1011a0fa
,
0x14d0bd4d
,
0x19939b94
,
0x1d528623
,
0xf12f560e
,
0xf5ee4bb9
,
0xf8ad6d60
,
0xfc6c70d7
,
0xe22b20d2
,
0xe6ea3d65
,
0xeba91bbc
,
0xef68060b
,
0xd727bbb6
,
0xd3e6a601
,
0xdea580d8
,
0xda649d6f
,
0xc423cd6a
,
0xc0e2d0dd
,
0xcda1f604
,
0xc960ebb3
,
0xbd3e8d7e
,
0xb9ff90c9
,
0xb4bcb610
,
0xb07daba7
,
0xae3afba2
,
0xaafbe615
,
0xa7b8c0cc
,
0xa379dd7b
,
0x9b3660c6
,
0x9ff77d71
,
0x92b45ba8
,
0x9675461f
,
0x8832161a
,
0x8cf30bad
,
0x81b02d74
,
0x857130c3
,
0x5d8a9099
,
0x594b8d2e
,
0x5408abf7
,
0x50c9b640
,
0x4e8ee645
,
0x4a4ffbf2
,
0x470cdd2b
,
0x43cdc09c
,
0x7b827d21
,
0x7f436096
,
0x7200464f
,
0x76c15bf8
,
0x68860bfd
,
0x6c47164a
,
0x61043093
,
0x65c52d24
,
0x119b4be9
,
0x155a565e
,
0x18197087
,
0x1cd86d30
,
0x029f3d35
,
0x065e2082
,
0x0b1d065b
,
0x0fdc1bec
,
0x3793a651
,
0x3352bbe6
,
0x3e119d3f
,
0x3ad08088
,
0x2497d08d
,
0x2056cd3a
,
0x2d15ebe3
,
0x29d4f654
,
0xc5a92679
,
0xc1683bce
,
0xcc2b1d17
,
0xc8ea00a0
,
0xd6ad50a5
,
0xd26c4d12
,
0xdf2f6bcb
,
0xdbee767c
,
0xe3a1cbc1
,
0xe760d676
,
0xea23f0af
,
0xeee2ed18
,
0xf0a5bd1d
,
0xf464a0aa
,
0xf9278673
,
0xfde69bc4
,
0x89b8fd09
,
0x8d79e0be
,
0x803ac667
,
0x84fbdbd0
,
0x9abc8bd5
,
0x9e7d9662
,
0x933eb0bb
,
0x97ffad0c
,
0xafb010b1
,
0xab710d06
,
0xa6322bdf
,
0xa2f33668
,
0xbcb4666d
,
0xb8757bda
,
0xb5365d03
,
0xb1f740b4
};
u32
dvb_crc32
(
u8
*
data
,
int
len
)
void
dvb_set_crc32
(
u8
*
data
,
int
length
)
{
int
i
;
u32
crc
=
0xffffffff
;
u32
crc
;
crc
=
crc32_le
(
~
0
,
data
,
length
);
for
(
i
=
0
;
i
<
len
;
i
++
)
crc
=
(
crc
<<
8
)
^
dvb_crc_table
[((
crc
>>
24
)
^
*
data
++
)
&
0xff
];
return
crc
;
data
[
length
]
=
(
crc
>>
24
)
&
0xff
;
data
[
length
+
1
]
=
(
crc
>>
16
)
&
0xff
;
data
[
length
+
2
]
=
(
crc
>>
8
)
&
0xff
;
data
[
length
+
3
]
=
(
crc
)
&
0xff
;
}
void
dvb_set_crc32
(
u8
*
data
,
int
length
)
static
u32
dvb_dmx_crc32
(
struct
dvb_demux_feed
*
f
,
const
u8
*
src
,
size_t
len
)
{
u32
crc
;
return
(
f
->
feed
.
sec
.
crc_val
=
crc32_le
(
f
->
feed
.
sec
.
crc_val
,
src
,
len
));
}
crc
=
dvb_crc32
(
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
void
dvb_dmx_memcopy
(
struct
dvb_demux_feed
*
f
,
u8
*
d
,
const
u8
*
s
,
size_t
len
)
{
memcpy
(
d
,
s
,
len
)
;
}
/******************************************************************************
* Software filter functions
******************************************************************************/
static
inline
int
dvb_dmx_swfilter_payload
(
struct
dvb_demux_feed
*
dvbdmx
feed
,
const
u8
*
buf
)
static
inline
int
dvb_dmx_swfilter_payload
(
struct
dvb_demux_feed
*
feed
,
const
u8
*
buf
)
{
int
p
,
count
;
int
count
=
payload
(
buf
);
int
p
;
//int ccok;
//u8 cc;
if
(
!
(
count
=
payload
(
buf
)))
return
-
1
;
p
=
188
-
count
;
/*
if
(
count
==
0
)
return
-
1
;
p
=
188
-
count
;
/*
cc=buf[3]&0x0f;
ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0;
dvbdmxfeed->cc=cc;
if (!ccok)
printk("missed packet!\n");
*/
if
(
buf
[
1
]
&
0x40
)
// PUSI ?
dvbdmxfeed
->
peslen
=
0xfffa
;
dvbdmxfeed
->
peslen
+=
count
;
return
dvbdmxfeed
->
cb
.
ts
((
u8
*
)
&
buf
[
p
],
count
,
0
,
0
,
&
dvbdmxfeed
->
feed
.
ts
,
DMX_OK
);
ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0;
dvbdmxfeed->cc=cc;
if (!ccok)
printk("missed packet!\n");
*/
if
(
buf
[
1
]
&
0x40
)
// PUSI ?
feed
->
peslen
=
0xfffa
;
feed
->
peslen
+=
count
;
return
feed
->
cb
.
ts
(
&
buf
[
p
],
count
,
0
,
0
,
&
feed
->
feed
.
ts
,
DMX_OK
);
}
static
int
dvb_dmx_swfilter_sectionfilter
(
struct
dvb_demux_feed
*
dvbdmx
feed
,
struct
dvb_demux_filter
*
f
)
static
int
dvb_dmx_swfilter_sectionfilter
(
struct
dvb_demux_feed
*
feed
,
struct
dvb_demux_filter
*
f
)
{
dmx_section_filter_t
*
filter
=&
f
->
filter
;
int
i
;
u8
xor
,
neq
=
0
;
u8
neq
=
0
;
int
i
;
for
(
i
=
0
;
i
<
DVB_DEMUX_MASK_MAX
;
i
++
)
{
u8
xor
=
f
->
filter
.
filter_value
[
i
]
^
feed
->
feed
.
sec
.
secbuf
[
i
];
for
(
i
=
0
;
i
<
DVB_DEMUX_MASK_MAX
;
i
++
)
{
xor
=
filter
->
filter_value
[
i
]
^
dvbdmxfeed
->
secbuf
[
i
];
if
(
f
->
maskandmode
[
i
]
&
xor
)
if
(
f
->
maskandmode
[
i
]
&
xor
)
return
0
;
neq
|=
f
->
maskandnotmode
[
i
]
&
xor
;
neq
|=
f
->
maskandnotmode
[
i
]
&
xor
;
}
if
(
f
->
doneq
&&
!
neq
)
if
(
f
->
doneq
&
!
neq
)
return
0
;
return
dvbdmxfeed
->
cb
.
sec
(
dvbdmxfeed
->
secbuf
,
dvbdmxfeed
->
seclen
,
0
,
0
,
filter
,
DMX_OK
);
return
feed
->
cb
.
sec
(
feed
->
feed
.
sec
.
secbuf
,
feed
->
feed
.
sec
.
seclen
,
0
,
0
,
&
f
->
filter
,
DMX_OK
);
}
static
inline
int
dvb_dmx_swfilter_section_feed
(
struct
dvb_demux_feed
*
dvbdmxfeed
)
static
inline
int
dvb_dmx_swfilter_section_feed
(
struct
dvb_demux_feed
*
feed
)
{
u8
*
buf
=
dvbdmxfeed
->
secbuf
;
struct
dvb_demux_filter
*
f
;
if
(
dvbdmxfeed
->
secbufp
!=
dvbdmxfeed
->
seclen
)
return
-
1
;
if
(
!
dvbdmxfeed
->
feed
.
sec
.
is_filtering
)
return
0
;
if
(
!
(
f
=
dvbdmxfeed
->
filter
))
return
0
;
do
if
(
dvb_dmx_swfilter_sectionfilter
(
dvbdmxfeed
,
f
)
<
0
)
return
-
1
;
while
((
f
=
f
->
next
)
&&
dvbdmxfeed
->
feed
.
sec
.
is_filtering
);
dvbdmxfeed
->
secbufp
=
dvbdmxfeed
->
seclen
=
0
;
memset
(
buf
,
0
,
DVB_DEMUX_MASK_MAX
);
return
0
;
struct
dvb_demux
*
demux
=
feed
->
demux
;
struct
dvb_demux_filter
*
f
=
feed
->
filter
;
dmx_section_feed_t
*
sec
=
&
feed
->
feed
.
sec
;
u8
*
buf
=
sec
->
secbuf
;
if
(
sec
->
secbufp
!=
sec
->
seclen
)
return
-
1
;
if
(
!
sec
->
is_filtering
)
return
0
;
if
(
!
f
)
return
0
;
if
(
sec
->
check_crc
&&
demux
->
check_crc32
(
feed
,
sec
->
secbuf
,
sec
->
seclen
))
return
-
1
;
do
{
if
(
dvb_dmx_swfilter_sectionfilter
(
feed
,
f
)
<
0
)
return
-
1
;
}
while
((
f
=
f
->
next
)
&&
sec
->
is_filtering
);
sec
->
secbufp
=
sec
->
seclen
=
0
;
memset
(
buf
,
0
,
DVB_DEMUX_MASK_MAX
);
return
0
;
}
static
inline
int
dvb_dmx_swfilter_section_packet
(
struct
dvb_demux_feed
*
dvbdmxfeed
,
const
u8
*
buf
)
static
int
dvb_dmx_swfilter_section_packet
(
struct
dvb_demux_feed
*
feed
,
const
u8
*
buf
)
{
int
p
,
count
;
int
ccok
,
rest
;
struct
dvb_demux
*
demux
=
feed
->
demux
;
dmx_section_feed_t
*
sec
=
&
feed
->
feed
.
sec
;
int
p
,
count
;
int
ccok
,
rest
;
u8
cc
;
if
(
!
(
count
=
payload
(
buf
)))
return
-
1
;
p
=
188
-
count
;
if
(
!
(
count
=
payload
(
buf
)))
return
-
1
;
cc
=
buf
[
3
]
&
0x0f
;
ccok
=
((
dvbdmxfeed
->
cc
+
1
)
&
0x0f
)
==
cc
?
1
:
0
;
dvbdmxfeed
->
cc
=
cc
;
p
=
188
-
count
;
if
(
buf
[
1
]
&
0x40
)
{
// PUSI set
// offset to start of first section is in buf[p]
cc
=
buf
[
3
]
&
0x0f
;
ccok
=
((
feed
->
cc
+
1
)
&
0x0f
)
==
cc
?
1
:
0
;
feed
->
cc
=
cc
;
if
(
buf
[
1
]
&
0x40
)
{
// PUSI set
// offset to start of first section is in buf[p]
if
(
p
+
buf
[
p
]
>
187
)
// trash if it points beyond packet
return
-
1
;
if
(
buf
[
p
]
&&
ccok
)
{
// rest of previous section?
// did we have enough data in last packet to calc length?
int
tmp
=
3
-
dvbdmxfeed
->
secbufp
;
if
(
tmp
>
0
&&
tmp
!=
3
)
{
if
(
p
+
tmp
>=
187
)
if
(
buf
[
p
]
&&
ccok
)
{
// rest of previous section?
// did we have enough data in last packet to calc length?
int
tmp
=
3
-
sec
->
secbufp
;
if
(
tmp
>
0
&&
tmp
!=
3
)
{
if
(
p
+
tmp
>=
187
)
return
-
1
;
memcpy
(
dvbdmxfeed
->
secbuf
+
dvbdmxfeed
->
secbufp
,
buf
+
p
+
1
,
tmp
);
dvbdmxfeed
->
seclen
=
section_length
(
dvbdmxfeed
->
secbuf
);
if
(
dvbdmxfeed
->
seclen
>
4096
)
demux
->
memcopy
(
feed
,
sec
->
secbuf
+
sec
->
secbufp
,
buf
+
p
+
1
,
tmp
);
sec
->
seclen
=
section_length
(
sec
->
secbuf
);
if
(
sec
->
seclen
>
4096
)
return
-
1
;
}
rest
=
dvbdmxfeed
->
seclen
-
dvbdmxfeed
->
secbufp
;
if
(
rest
==
buf
[
p
]
&&
dvbdmxfeed
->
seclen
)
{
memcpy
(
dvbdmxfeed
->
secbuf
+
dvbdmxfeed
->
secbufp
,
buf
+
p
+
1
,
buf
[
p
]);
dvbdmxfeed
->
secbufp
+=
buf
[
p
];
dvb_dmx_swfilter_section_feed
(
dvbdmxfeed
);
}
}
p
+=
buf
[
p
]
+
1
;
// skip rest of last section
count
=
188
-
p
;
while
(
count
>
0
)
{
if
((
count
>
2
)
&&
// enough data to determine sec length?
((
dvbdmxfeed
->
seclen
=
section_length
(
buf
+
p
))
<=
count
))
{
if
(
dvbdmxfeed
->
seclen
>
4096
)
}
rest
=
sec
->
seclen
-
sec
->
secbufp
;
if
(
rest
==
buf
[
p
]
&&
sec
->
seclen
)
{
demux
->
memcopy
(
feed
,
sec
->
secbuf
+
sec
->
secbufp
,
buf
+
p
+
1
,
buf
[
p
]);
sec
->
secbufp
+=
buf
[
p
];
dvb_dmx_swfilter_section_feed
(
feed
);
}
}
p
+=
buf
[
p
]
+
1
;
// skip rest of last section
count
=
188
-
p
;
while
(
count
)
{
sec
->
crc_val
=
~
0
;
if
((
count
>
2
)
&&
// enough data to determine sec length?
((
sec
->
seclen
=
section_length
(
buf
+
p
))
<=
count
))
{
if
(
sec
->
seclen
>
4096
)
return
-
1
;
memcpy
(
dvbdmxfeed
->
secbuf
,
buf
+
p
,
dvbdmxfeed
->
seclen
);
dvbdmxfeed
->
secbufp
=
dvbdmxfeed
->
seclen
;
p
+=
dvbdmxfeed
->
seclen
;
count
=
188
-
p
;
dvb_dmx_swfilter_section_feed
(
dvbdmxfeed
);
// filling bytes until packet end?
if
(
count
&&
buf
[
p
]
==
0xff
)
count
=
0
;
}
else
{
// section continues to following TS packet
memcpy
(
dvbdmxfeed
->
secbuf
,
buf
+
p
,
count
);
dvbdmxfeed
->
secbufp
+=
count
;
count
=
0
;
}
}
demux
->
memcopy
(
feed
,
sec
->
secbuf
,
buf
+
p
,
sec
->
seclen
);
sec
->
secbufp
=
sec
->
seclen
;
p
+=
sec
->
seclen
;
count
=
188
-
p
;
dvb_dmx_swfilter_section_feed
(
feed
);
// filling bytes until packet end?
if
(
count
&&
buf
[
p
]
==
0xff
)
count
=
0
;
}
else
{
// section continues to following TS packet
demux
->
memcopy
(
feed
,
sec
->
secbuf
,
buf
+
p
,
count
);
sec
->
secbufp
+=
count
;
count
=
0
;
}
}
return
0
;
}
// section continued below
if
(
!
ccok
)
return
-
1
;
if
(
!
dvbdmxfeed
->
secbufp
)
// any data in last ts packet?
if
(
!
sec
->
secbufp
)
// any data in last ts packet?
return
-
1
;
// did we have enough data in last packet to calc section length?
if
(
dvbdmxfeed
->
secbufp
<
3
)
{
int
tmp
=
3
-
dvbdmxfeed
->
secbufp
;
if
(
sec
->
secbufp
<
3
)
{
int
tmp
=
3
-
sec
->
secbufp
;
if
(
tmp
>
count
)
return
-
1
;
memcpy
(
dvbdmxfeed
->
secbuf
+
dvbdmxfeed
->
secbufp
,
buf
+
p
,
tmp
);
dvbdmxfeed
->
seclen
=
section_length
(
dvbdmxfeed
->
secbuf
);
if
(
dvbdmxfeed
->
seclen
>
4096
)
sec
->
crc_val
=
~
0
;
demux
->
memcopy
(
feed
,
sec
->
secbuf
+
sec
->
secbufp
,
buf
+
p
,
tmp
);
sec
->
seclen
=
section_length
(
sec
->
secbuf
);
if
(
sec
->
seclen
>
4096
)
return
-
1
;
}
rest
=
dvbdmxfeed
->
seclen
-
dvbdmxfeed
->
secbufp
;
if
(
rest
<
0
)
rest
=
sec
->
seclen
-
sec
->
secbufp
;
if
(
rest
<
0
)
return
-
1
;
if
(
rest
<=
count
)
{
// section completed in this TS packet
memcpy
(
dvbdmxfeed
->
secbuf
+
dvbdmxfeed
->
secbufp
,
buf
+
p
,
rest
);
dvbdmxfeed
->
secbufp
+=
rest
;
dvb_dmx_swfilter_section_feed
(
dvbdmxfeed
);
if
(
rest
<=
count
)
{
// section completed in this TS packet
demux
->
memcopy
(
feed
,
sec
->
secbuf
+
sec
->
secbufp
,
buf
+
p
,
rest
);
sec
->
secbufp
+=
rest
;
dvb_dmx_swfilter_section_feed
(
feed
);
}
else
{
// section continues in following ts packet
memcpy
(
dvbdmxfeed
->
secbuf
+
dvbdmxfeed
->
secbufp
,
buf
+
p
,
count
);
dvbdmxfeed
->
secbufp
+=
count
;
demux
->
memcopy
(
feed
,
sec
->
secbuf
+
sec
->
secbufp
,
buf
+
p
,
count
);
sec
->
secbufp
+=
count
;
}
return
0
;
return
0
;
}
static
inline
void
dvb_dmx_swfilter_packet_type
(
struct
dvb_demux_feed
*
dvbdmxfeed
,
const
u8
*
buf
)
static
inline
void
dvb_dmx_swfilter_packet_type
(
struct
dvb_demux_feed
*
feed
,
const
u8
*
buf
)
{
switch
(
dvbdmxfeed
->
type
)
{
case
DMX_TYPE_TS
:
if
(
!
dvbdmxfeed
->
feed
.
ts
.
is_filtering
)
break
;
if
(
dvbdmxfeed
->
ts_type
&
TS_PACKET
)
{
if
(
dvbdmxfeed
->
ts_type
&
TS_PAYLOAD_ONLY
)
dvb_dmx_swfilter_payload
(
dvbdmxfeed
,
buf
);
else
dvbdmxfeed
->
cb
.
ts
((
u8
*
)
buf
,
188
,
0
,
0
,
&
dvbdmxfeed
->
feed
.
ts
,
DMX_OK
);
}
if
(
dvbdmxfeed
->
ts_type
&
TS_DECODER
)
if
(
dvbdmxfeed
->
demux
->
write_to_decoder
)
dvbdmxfeed
->
demux
->
write_to_decoder
(
dvbdmxfeed
,
(
u8
*
)
buf
,
188
);
break
;
case
DMX_TYPE_SEC
:
if
(
!
dvbdmxfeed
->
feed
.
sec
.
is_filtering
)
break
;
if
(
dvb_dmx_swfilter_section_packet
(
dvbdmxfeed
,
buf
)
<
0
)
dvbdmxfeed
->
seclen
=
dvbdmxfeed
->
secbufp
=
0
;
break
;
default:
break
;
}
switch
(
feed
->
type
)
{
case
DMX_TYPE_TS
:
if
(
!
feed
->
feed
.
ts
.
is_filtering
)
break
;
if
(
feed
->
ts_type
&
TS_PACKET
)
{
if
(
feed
->
ts_type
&
TS_PAYLOAD_ONLY
)
dvb_dmx_swfilter_payload
(
feed
,
buf
);
else
feed
->
cb
.
ts
(
buf
,
188
,
0
,
0
,
&
feed
->
feed
.
ts
,
DMX_OK
);
}
if
(
feed
->
ts_type
&
TS_DECODER
)
if
(
feed
->
demux
->
write_to_decoder
)
feed
->
demux
->
write_to_decoder
(
feed
,
buf
,
188
);
break
;
case
DMX_TYPE_SEC
:
if
(
!
feed
->
feed
.
sec
.
is_filtering
)
break
;
if
(
dvb_dmx_swfilter_section_packet
(
feed
,
buf
)
<
0
)
feed
->
feed
.
sec
.
seclen
=
feed
->
feed
.
sec
.
secbufp
=
0
;
break
;
default:
break
;
}
}
void
dvb_dmx_swfilter_packet
(
struct
dvb_demux
*
dvbdmx
,
const
u8
*
buf
)
{
struct
dvb_demux_feed
*
dvbdmxfeed
;
if
(
!
(
dvbdmxfeed
=
dvbdmx
->
pid2feed
[
ts_pid
(
buf
)]))
return
;
dvb_dmx_swfilter_packet_type
(
dvbdmxfeed
,
buf
);
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
;
u16
pid
=
ts_pid
(
buf
);
list_for_each
(
pos
,
head
)
{
feed
=
list_entry
(
pos
,
struct
dvb_demux_feed
,
list_head
);
if
(
feed
->
pid
==
pid
)
dvb_dmx_swfilter_packet_type
(
feed
,
buf
);
if
(
feed
->
pid
==
0x2000
)
feed
->
cb
.
ts
(
buf
,
188
,
0
,
0
,
&
feed
->
feed
.
ts
,
DMX_OK
);
}
}
void
dvb_dmx_swfilter_packets
(
struct
dvb_demux
*
dvbdmx
,
const
u8
*
buf
,
in
t
count
)
void
dvb_dmx_swfilter_packets
(
struct
dvb_demux
*
demux
,
const
u8
*
buf
,
size_
t
count
)
{
struct
dvb_demux_feed
*
dvbdmxfeed
;
spin_lock
(
&
dvbdmx
->
lock
);
if
((
dvbdmxfeed
=
dvbdmx
->
pid2feed
[
0x2000
]))
dvbdmxfeed
->
cb
.
ts
((
u8
*
)
buf
,
count
*
188
,
0
,
0
,
&
dvbdmxfeed
->
feed
.
ts
,
DMX_OK
);
while
(
count
)
{
dvb_dmx_swfilter_packet
(
dvbdmx
,
buf
);
count
--
;
buf
+=
188
;
spin_lock
(
&
demux
->
lock
);
while
(
count
--
)
{
dvb_dmx_swfilter_packet
(
demux
,
buf
);
buf
+=
188
;
}
spin_unlock
(
&
dvbdmx
->
lock
);
spin_unlock
(
&
demux
->
lock
);
}
static
inline
void
dvb_dmx_swfilter
(
struct
dvb_demux
*
dvbdm
x
,
const
u8
*
buf
,
size_t
count
)
void
dvb_dmx_swfilter
(
struct
dvb_demux
*
demu
x
,
const
u8
*
buf
,
size_t
count
)
{
int
p
=
0
,
i
,
j
;
if
((
i
=
dvbdm
x
->
tsbufp
))
{
if
(
count
<
(
j
=
188
-
i
))
{
memcpy
(
&
dvbdm
x
->
tsbuf
[
i
],
buf
,
count
);
dvbdmx
->
tsbufp
+=
count
;
return
;
}
memcpy
(
&
dvbdm
x
->
tsbuf
[
i
],
buf
,
j
);
dvb_dmx_swfilter_packet
(
dvbdmx
,
dvbdm
x
->
tsbuf
);
dvbdmx
->
tsbufp
=
0
;
p
+=
j
;
}
while
(
p
<
count
)
{
if
(
buf
[
p
]
==
0x47
)
{
if
(
count
-
p
>=
188
)
{
dvb_dmx_swfilter_packet
(
dvbdm
x
,
buf
+
p
);
p
+=
188
;
}
else
{
i
=
count
-
p
;
memcpy
(
dvbdm
x
->
tsbuf
,
buf
+
p
,
i
);
dvbdm
x
->
tsbufp
=
i
;
int
p
=
0
,
i
,
j
;
if
((
i
=
demu
x
->
tsbufp
))
{
if
(
count
<
(
j
=
188
-
i
))
{
memcpy
(
&
demu
x
->
tsbuf
[
i
],
buf
,
count
);
demux
->
tsbufp
+=
count
;
return
;
}
memcpy
(
&
demu
x
->
tsbuf
[
i
],
buf
,
j
);
dvb_dmx_swfilter_packet
(
demux
,
demu
x
->
tsbuf
);
demux
->
tsbufp
=
0
;
p
+=
j
;
}
while
(
p
<
count
)
{
if
(
buf
[
p
]
==
0x47
)
{
if
(
count
-
p
>=
188
)
{
dvb_dmx_swfilter_packet
(
demu
x
,
buf
+
p
);
p
+=
188
;
}
else
{
i
=
count
-
p
;
memcpy
(
demu
x
->
tsbuf
,
buf
+
p
,
i
);
demu
x
->
tsbufp
=
i
;
return
;
}
}
else
p
++
;
}
}
}
else
p
++
;
}
}
/******************************************************************************
******************************************************************************
* DVB DEMUX API LEVEL FUNCTIONS
******************************************************************************
******************************************************************************/
static
struct
dvb_demux_filter
*
dvb_dmx_filter_alloc
(
struct
dvb_demux
*
dvbdmx
)
static
struct
dvb_demux_filter
*
dvb_dmx_filter_alloc
(
struct
dvb_demux
*
demux
)
{
int
i
;
for
(
i
=
0
;
i
<
dvbdmx
->
filternum
;
i
++
)
if
(
dvbdmx
->
filter
[
i
].
state
==
DMX_STATE_FREE
)
break
;
if
(
i
==
dvbdmx
->
filternum
)
return
0
;
dvbdmx
->
filter
[
i
].
state
=
DMX_STATE_ALLOCATED
;
return
&
dvbdmx
->
filter
[
i
];
int
i
;
for
(
i
=
0
;
i
<
demux
->
filternum
;
i
++
)
if
(
demux
->
filter
[
i
].
state
==
DMX_STATE_FREE
)
break
;
if
(
i
==
demux
->
filternum
)
return
NULL
;
demux
->
filter
[
i
].
state
=
DMX_STATE_ALLOCATED
;
return
&
demux
->
filter
[
i
];
}
static
struct
dvb_demux_feed
*
dvb_dmx_feed_alloc
(
struct
dvb_demux
*
dvbdm
x
)
static
struct
dvb_demux_feed
*
dvb_dmx_feed_alloc
(
struct
dvb_demux
*
demu
x
)
{
int
i
;
for
(
i
=
0
;
i
<
dvbdmx
->
feednum
;
i
++
)
if
(
dvbdmx
->
feed
[
i
].
state
==
DMX_STATE_FREE
)
break
;
if
(
i
==
dvbdmx
->
feednum
)
return
0
;
dvbdmx
->
feed
[
i
].
state
=
DMX_STATE_ALLOCATED
;
return
&
dvbdmx
->
feed
[
i
];
}
int
i
;
for
(
i
=
0
;
i
<
demux
->
feednum
;
i
++
)
if
(
demux
->
feed
[
i
].
state
==
DMX_STATE_FREE
)
break
;
/******************************************************************************
* dmx_ts_feed API calls
******************************************************************************/
if
(
i
==
demux
->
feednum
)
return
NULL
;
static
int
dmx_pid_set
(
u16
pid
,
struct
dvb_demux_feed
*
dvbdmxfeed
)
demux
->
feed
[
i
].
state
=
DMX_STATE_ALLOCATED
;
return
&
demux
->
feed
[
i
];
}
static
int
dmx_pid_set
(
u16
pid
,
struct
dvb_demux_feed
*
feed
)
{
struct
dvb_demux
*
dvbdmx
=
dvbdmxfeed
->
demux
;
struct
dvb_demux_feed
**
pid2feed
=
dvbdmx
->
pid2feed
;
if
(
pid
>
DMX_MAX_PID
)
return
-
EINVAL
;
if
(
dvbdmxfeed
->
pid
!=
0xffff
)
{
if
(
dvbdmxfeed
->
pid
<=
DMX_MAX_PID
)
pid2feed
[
dvbdmxfeed
->
pid
]
=
0
;
dvbdmxfeed
->
pid
=
0xffff
;
}
if
(
pid2feed
[
pid
])
{
return
-
EBUSY
;
}
pid2feed
[
pid
]
=
dvbdmxfeed
;
dvbdmxfeed
->
pid
=
pid
;
struct
dvb_demux
*
demux
=
feed
->
demux
;
struct
list_head
*
pos
,
*
n
,
*
head
=&
demux
->
feed_list
;
if
(
pid
>
DMX_MAX_PID
)
return
-
EINVAL
;
if
(
pid
==
feed
->
pid
)
return
0
;
if
(
feed
->
pid
<=
DMX_MAX_PID
)
list_for_each_safe
(
pos
,
n
,
head
)
if
(
DMX_FEED_ENTRY
(
pos
)
->
pid
==
feed
->
pid
)
{
list_del
(
pos
);
break
;
}
list_add
(
&
feed
->
list_head
,
head
);
feed
->
pid
=
pid
;
return
0
;
}
static
int
dmx_ts_feed_set
(
struct
dmx_ts_feed_s
*
feed
,
u16
pid
,
int
ts_type
,
dmx_ts_pes_t
pes_type
,
size_t
callback_length
,
size_t
circular_buffer_size
,
int
descramble
,
struct
timespec
timeout
)
static
int
dmx_ts_feed_set
(
struct
dmx_ts_feed_s
*
ts_feed
,
u16
pid
,
int
ts_type
,
dmx_ts_pes_t
pes_type
,
size_t
callback_length
,
size_t
circular_buffer_size
,
int
descramble
,
struct
timespec
timeout
)
{
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmx
feed
->
demux
;
struct
dvb_demux_feed
*
feed
=
(
struct
dvb_demux_feed
*
)
ts_
feed
;
struct
dvb_demux
*
demux
=
feed
->
demux
;
int
ret
;
if
(
down_interruptible
(
&
dvbdm
x
->
mutex
))
if
(
down_interruptible
(
&
demu
x
->
mutex
))
return
-
ERESTARTSYS
;
if
(
ts_type
&
TS_DECODER
)
{
if
(
pes_type
>=
DMX_TS_PES_OTHER
)
{
up
(
&
d
vbdm
x
->
mutex
);
return
-
EINVAL
;
if
(
pes_type
>=
DMX_TS_PES_OTHER
)
{
up
(
&
d
emu
x
->
mutex
);
return
-
EINVAL
;
}
if
(
dvbdmx
->
pesfilter
[
pes_type
]
&&
(
dvbdmx
->
pesfilter
[
pes_type
]
!=
dvbdmxfeed
))
{
up
(
&
dvbdmx
->
mutex
);
return
-
EINVAL
;
if
(
demux
->
pesfilter
[
pes_type
]
&&
demux
->
pesfilter
[
pes_type
]
!=
feed
)
{
up
(
&
demux
->
mutex
);
return
-
EINVAL
;
}
if
((
pes_type
!=
DMX_TS_PES_PCR0
)
&&
(
pes_type
!=
DMX_TS_PES_PCR1
)
&&
(
pes_type
!=
DMX_TS_PES_PCR2
)
&&
(
pes_type
!=
DMX_TS_PES_PCR3
))
{
if
((
ret
=
dmx_pid_set
(
pid
,
dvbdmx
feed
))
<
0
)
{
up
(
&
d
vbdm
x
->
mutex
);
if
((
ret
=
dmx_pid_set
(
pid
,
feed
))
<
0
)
{
up
(
&
d
emu
x
->
mutex
);
return
ret
;
}
else
dvbdmxfeed
->
pid
=
pid
;
}
dvbdmx
->
pesfilter
[
pes_type
]
=
dvbdmxfeed
;
dvbdmx
->
pids
[
pes_type
]
=
dvbdmxfeed
->
pid
;
}
else
if
((
ret
=
dmx_pid_set
(
pid
,
dvbdmxfeed
))
<
0
)
{
up
(
&
dvbdmx
->
mutex
);
}
}
else
feed
->
pid
=
pid
;
demux
->
pesfilter
[
pes_type
]
=
feed
;
demux
->
pids
[
pes_type
]
=
feed
->
pid
;
}
else
{
if
((
ret
=
dmx_pid_set
(
pid
,
feed
))
<
0
)
{
up
(
&
demux
->
mutex
);
return
ret
;
}
}
dvbdmxfeed
->
buffer_size
=
circular_buffer_size
;
dvbdmxfeed
->
descramble
=
descramble
;
dvbdmxfeed
->
timeout
=
timeout
;
dvbdmxfeed
->
cb_length
=
callback_length
;
dvbdmxfeed
->
ts_type
=
ts_type
;
dvbdmxfeed
->
pes_type
=
pes_type
;
feed
->
buffer_size
=
circular_buffer_size
;
feed
->
descramble
=
descramble
;
feed
->
timeout
=
timeout
;
feed
->
cb_length
=
callback_length
;
feed
->
ts_type
=
ts_type
;
feed
->
pes_type
=
pes_type
;
if
(
dvbdmx
feed
->
descramble
)
{
up
(
&
d
vbdm
x
->
mutex
);
return
-
ENOSYS
;
if
(
feed
->
descramble
)
{
up
(
&
d
emu
x
->
mutex
);
return
-
ENOSYS
;
}
if
(
dvbdmx
feed
->
buffer_size
)
{
if
(
feed
->
buffer_size
)
{
#ifdef NOBUFS
dvbdmx
feed
->
buffer
=
0
;
feed
->
buffer
=
0
;
#else
dvbdmxfeed
->
buffer
=
vmalloc
(
dvbdmx
feed
->
buffer_size
);
if
(
!
dvbdmx
feed
->
buffer
)
{
up
(
&
d
vbdm
x
->
mutex
);
feed
->
buffer
=
vmalloc
(
feed
->
buffer_size
);
if
(
!
feed
->
buffer
)
{
up
(
&
d
emu
x
->
mutex
);
return
-
ENOMEM
;
}
#endif
}
dvbdmxfeed
->
state
=
DMX_STATE_READY
;
up
(
&
dvbdmx
->
mutex
);
return
0
;
}
feed
->
state
=
DMX_STATE_READY
;
up
(
&
demux
->
mutex
);
return
0
;
}
static
int
dmx_ts_feed_start_filtering
(
struct
dmx_ts_feed_s
*
feed
)
static
int
dmx_ts_feed_start_filtering
(
struct
dmx_ts_feed_s
*
ts_feed
)
{
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmx
feed
->
demux
;
struct
dvb_demux_feed
*
feed
=
(
struct
dvb_demux_feed
*
)
ts_
feed
;
struct
dvb_demux
*
demux
=
feed
->
demux
;
int
ret
;
if
(
down_interruptible
(
&
dvbdm
x
->
mutex
))
if
(
down_interruptible
(
&
demu
x
->
mutex
))
return
-
ERESTARTSYS
;
if
(
dvbdmxfeed
->
state
!=
DMX_STATE_READY
||
dvbdmxfeed
->
type
!=
DMX_TYPE_TS
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
EINVAL
;
if
(
feed
->
state
!=
DMX_STATE_READY
||
feed
->
type
!=
DMX_TYPE_TS
)
{
up
(
&
demux
->
mutex
);
return
-
EINVAL
;
}
if
(
!
dvbdmx
->
start_feed
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
1
;
if
(
!
demux
->
start_feed
)
{
up
(
&
demux
->
mutex
);
return
-
ENODEV
;
}
ret
=
dvbdmx
->
start_feed
(
dvbdmxfeed
);
if
(
ret
<
0
)
{
up
(
&
d
vbdm
x
->
mutex
);
if
((
ret
=
demux
->
start_feed
(
feed
))
<
0
)
{
up
(
&
d
emu
x
->
mutex
);
return
ret
;
}
spin_lock_irq
(
&
dvbdmx
->
lock
);
feed
->
is_filtering
=
1
;
dvbdmxfeed
->
state
=
DMX_STATE_GO
;
spin_unlock_irq
(
&
dvbdmx
->
lock
);
up
(
&
dvbdmx
->
mutex
);
spin_lock_irq
(
&
demux
->
lock
);
ts_feed
->
is_filtering
=
1
;
feed
->
state
=
DMX_STATE_GO
;
spin_unlock_irq
(
&
demux
->
lock
);
up
(
&
demux
->
mutex
);
return
0
;
}
static
int
dmx_ts_feed_stop_filtering
(
struct
dmx_ts_feed_s
*
feed
)
static
int
dmx_ts_feed_stop_filtering
(
struct
dmx_ts_feed_s
*
ts_
feed
)
{
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmx
feed
->
demux
;
struct
dvb_demux_feed
*
feed
=
(
struct
dvb_demux_feed
*
)
ts_
feed
;
struct
dvb_demux
*
demux
=
feed
->
demux
;
int
ret
;
if
(
down_interruptible
(
&
dvbdm
x
->
mutex
))
if
(
down_interruptible
(
&
demu
x
->
mutex
))
return
-
ERESTARTSYS
;
if
(
dvbdmx
feed
->
state
<
DMX_STATE_GO
)
{
up
(
&
d
vbdm
x
->
mutex
);
return
-
EINVAL
;
if
(
feed
->
state
<
DMX_STATE_GO
)
{
up
(
&
d
emu
x
->
mutex
);
return
-
EINVAL
;
}
if
(
!
dvbdmx
->
stop_feed
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
1
;
if
(
!
demux
->
stop_feed
)
{
up
(
&
demux
->
mutex
);
return
-
ENODEV
;
}
ret
=
dvbdmx
->
stop_feed
(
dvbdmxfeed
);
spin_lock_irq
(
&
dvbdmx
->
lock
);
feed
->
is_filtering
=
0
;
dvbdmxfeed
->
state
=
DMX_STATE_ALLOCATED
;
spin_unlock_irq
(
&
dvbdmx
->
lock
);
up
(
&
dvbdmx
->
mutex
);
return
ret
;
ret
=
demux
->
stop_feed
(
feed
);
spin_lock_irq
(
&
demux
->
lock
);
ts_feed
->
is_filtering
=
0
;
feed
->
state
=
DMX_STATE_ALLOCATED
;
spin_unlock_irq
(
&
demux
->
lock
);
up
(
&
demux
->
mutex
);
return
ret
;
}
static
int
dvbdmx_allocate_ts_feed
(
dmx_demux_t
*
demux
,
dmx_ts_feed_t
**
feed
,
dmx_ts_cb
callback
)
static
int
dvbdmx_allocate_ts_feed
(
dmx_demux_t
*
dmx
,
dmx_ts_feed_t
**
ts_
feed
,
dmx_ts_cb
callback
)
{
struct
dvb_demux
*
dvbdmx
=
(
struct
dvb_demux
*
)
demu
x
;
struct
dvb_demux_feed
*
dvbdmx
feed
;
struct
dvb_demux
*
demux
=
(
struct
dvb_demux
*
)
dm
x
;
struct
dvb_demux_feed
*
feed
;
if
(
down_interruptible
(
&
dvbdm
x
->
mutex
))
if
(
down_interruptible
(
&
demu
x
->
mutex
))
return
-
ERESTARTSYS
;
if
(
!
(
dvbdmxfeed
=
dvb_dmx_feed_alloc
(
dvbdm
x
)))
{
up
(
&
d
vbdm
x
->
mutex
);
return
-
EBUSY
;
if
(
!
(
feed
=
dvb_dmx_feed_alloc
(
demu
x
)))
{
up
(
&
d
emu
x
->
mutex
);
return
-
EBUSY
;
}
dvbdmxfeed
->
type
=
DMX_TYPE_TS
;
dvbdmxfeed
->
cb
.
ts
=
callback
;
dvbdmxfeed
->
demux
=
dvbdmx
;
dvbdmxfeed
->
pid
=
0xffff
;
dvbdmxfeed
->
peslen
=
0xfffa
;
dvbdmxfeed
->
buffer
=
0
;
(
*
feed
)
=&
dvbdmxfeed
->
feed
.
ts
;
(
*
feed
)
->
is_filtering
=
0
;
(
*
feed
)
->
parent
=
demux
;
(
*
feed
)
->
priv
=
0
;
(
*
feed
)
->
set
=
dmx_ts_feed_set
;
(
*
feed
)
->
start_filtering
=
dmx_ts_feed_start_filtering
;
(
*
feed
)
->
stop_filtering
=
dmx_ts_feed_stop_filtering
;
if
(
!
(
dvbdmxfeed
->
filter
=
dvb_dmx_filter_alloc
(
dvbdmx
)))
{
dvbdmxfeed
->
state
=
DMX_STATE_FREE
;
up
(
&
dvbdmx
->
mutex
);
return
-
EBUSY
;
}
dvbdmxfeed
->
filter
->
type
=
DMX_TYPE_TS
;
dvbdmxfeed
->
filter
->
feed
=
dvbdmxfeed
;
dvbdmxfeed
->
filter
->
state
=
DMX_STATE_READY
;
up
(
&
dvbdmx
->
mutex
);
return
0
;
feed
->
type
=
DMX_TYPE_TS
;
feed
->
cb
.
ts
=
callback
;
feed
->
demux
=
demux
;
feed
->
pid
=
0xffff
;
feed
->
peslen
=
0xfffa
;
feed
->
buffer
=
0
;
(
*
ts_feed
)
=
&
feed
->
feed
.
ts
;
(
*
ts_feed
)
->
is_filtering
=
0
;
(
*
ts_feed
)
->
parent
=
dmx
;
(
*
ts_feed
)
->
priv
=
0
;
(
*
ts_feed
)
->
set
=
dmx_ts_feed_set
;
(
*
ts_feed
)
->
start_filtering
=
dmx_ts_feed_start_filtering
;
(
*
ts_feed
)
->
stop_filtering
=
dmx_ts_feed_stop_filtering
;
if
(
!
(
feed
->
filter
=
dvb_dmx_filter_alloc
(
demux
)))
{
feed
->
state
=
DMX_STATE_FREE
;
up
(
&
demux
->
mutex
);
return
-
EBUSY
;
}
feed
->
filter
->
type
=
DMX_TYPE_TS
;
feed
->
filter
->
feed
=
feed
;
feed
->
filter
->
state
=
DMX_STATE_READY
;
up
(
&
demux
->
mutex
);
return
0
;
}
static
int
dvbdmx_release_ts_feed
(
dmx_demux_t
*
demux
,
dmx_ts_feed_t
*
feed
)
static
int
dvbdmx_release_ts_feed
(
dmx_demux_t
*
dmx
,
dmx_ts_feed_t
*
ts_feed
)
{
struct
dvb_demux
*
dvbdmx
=
(
struct
dvb_demux
*
)
demux
;
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
demux
=
(
struct
dvb_demux
*
)
dmx
;
struct
dvb_demux_feed
*
feed
=
(
struct
dvb_demux_feed
*
)
ts_feed
;
struct
list_head
*
pos
,
*
n
,
*
head
=&
demux
->
feed_list
;
if
(
down_interruptible
(
&
dvbdm
x
->
mutex
))
if
(
down_interruptible
(
&
demu
x
->
mutex
))
return
-
ERESTARTSYS
;
if
(
dvbdmxfeed
->
state
==
DMX_STATE_FREE
)
{
up
(
&
d
vbdm
x
->
mutex
);
return
-
EINVAL
;
if
(
feed
->
state
==
DMX_STATE_FREE
)
{
up
(
&
d
emu
x
->
mutex
);
return
-
EINVAL
;
}
#ifndef NOBUFS
if
(
dvbdmx
feed
->
buffer
)
{
vfree
(
dvbdmx
feed
->
buffer
);
dvbdmx
feed
->
buffer
=
0
;
}
if
(
feed
->
buffer
)
{
vfree
(
feed
->
buffer
);
feed
->
buffer
=
0
;
}
#endif
dvbdmxfeed
->
state
=
DMX_STATE_FREE
;
dvbdmxfeed
->
filter
->
state
=
DMX_STATE_FREE
;
if
(
dvbdmxfeed
->
pid
<=
DMX_MAX_PID
)
{
dvbdmxfeed
->
demux
->
pid2feed
[
dvbdmxfeed
->
pid
]
=
0
;
dvbdmxfeed
->
pid
=
0xffff
;
}
up
(
&
dvbdmx
->
mutex
);
return
0
;
feed
->
state
=
DMX_STATE_FREE
;
feed
->
filter
->
state
=
DMX_STATE_FREE
;
if
(
feed
->
pid
<=
DMX_MAX_PID
)
{
list_for_each_safe
(
pos
,
n
,
head
)
if
(
DMX_FEED_ENTRY
(
pos
)
->
pid
==
feed
->
pid
)
{
list_del
(
pos
);
break
;
}
feed
->
pid
=
0xffff
;
}
if
(
feed
->
ts_type
&
TS_DECODER
)
demux
->
pesfilter
[
feed
->
pes_type
]
=
NULL
;
up
(
&
demux
->
mutex
);
return
0
;
}
...
...
@@ -713,92 +755,92 @@ static int dvbdmx_release_ts_feed(dmx_demux_t *demux, dmx_ts_feed_t *feed)
static
int
dmx_section_feed_allocate_filter
(
struct
dmx_section_feed_s
*
feed
,
dmx_section_filter_t
**
filter
)
dmx_section_filter_t
**
filter
)
{
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdemux
=
dvbdmxfeed
->
demux
;
struct
dvb_demux_filter
*
dvbdmxfilter
;
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
);
if
(
!
dvbdmxfilter
)
{
dvbdmxfilter
=
dvb_dmx_filter_alloc
(
dvbdemux
);
if
(
!
dvbdmxfilter
)
{
up
(
&
dvbdemux
->
mutex
);
return
-
ENOSPC
;
return
-
ENOSPC
;
}
spin_lock_irq
(
&
dvbdemux
->
lock
);
*
filter
=&
dvbdmxfilter
->
filter
;
(
*
filter
)
->
parent
=
feed
;
(
*
filter
)
->
priv
=
0
;
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
=
0
;
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
;
up
(
&
dvbdemux
->
mutex
);
return
0
;
}
static
int
dmx_section_feed_set
(
struct
dmx_section_feed_s
*
feed
,
u16
pid
,
size_t
circular_buffer_size
,
int
descramble
,
int
check_crc
)
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
;
struct
list_head
*
pos
,
*
n
,
*
head
=&
dvbdmx
->
feed_list
;
if
(
pid
>
0x1fff
)
return
-
EINVAL
;
if
(
pid
>
0x1fff
)
return
-
EINVAL
;
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
return
-
ERESTARTSYS
;
if
(
dvbdmxfeed
->
pid
!=
0xffff
)
{
dvbdmx
->
pid2feed
[
dvbdmxfeed
->
pid
]
=
0
;
dvbdmxfeed
->
pid
=
0xffff
;
}
if
(
dvbdmx
->
pid2feed
[
pid
])
{
if
(
dvbdmxfeed
->
pid
<=
DMX_MAX_PID
)
list_for_each_safe
(
pos
,
n
,
head
)
if
(
DMX_FEED_ENTRY
(
pos
)
->
pid
==
dvbdmxfeed
->
pid
)
{
list_del
(
pos
);
break
;
}
list_add
(
&
dvbdmxfeed
->
list_head
,
head
);
dvbdmxfeed
->
pid
=
pid
;
dvbdmxfeed
->
buffer_size
=
circular_buffer_size
;
dvbdmxfeed
->
descramble
=
descramble
;
if
(
dvbdmxfeed
->
descramble
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
E
BUSY
;
return
-
E
NOSYS
;
}
dvbdmx
->
pid2feed
[
pid
]
=
dvbdmxfeed
;
dvbdmxfeed
->
pid
=
pid
;
dvbdmxfeed
->
buffer_size
=
circular_buffer_size
;
dvbdmxfeed
->
descramble
=
descramble
;
if
(
dvbdmxfeed
->
descramble
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
ENOSYS
;
}
dvbdmxfeed
->
check_crc
=
check_crc
;
dvbdmxfeed
->
feed
.
sec
.
check_crc
=
check_crc
;
#ifdef NOBUFS
dvbdmxfeed
->
buffer
=
0
;
dvbdmxfeed
->
buffer
=
0
;
#else
dvbdmxfeed
->
buffer
=
vmalloc
(
dvbdmxfeed
->
buffer_size
);
if
(
!
dvbdmxfeed
->
buffer
)
{
dvbdmxfeed
->
buffer
=
vmalloc
(
dvbdmxfeed
->
buffer_size
);
if
(
!
dvbdmxfeed
->
buffer
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
ENOMEM
;
}
#endif
dvbdmxfeed
->
state
=
DMX_STATE_READY
;
up
(
&
dvbdmx
->
mutex
);
return
0
;
dvbdmxfeed
->
state
=
DMX_STATE_READY
;
up
(
&
dvbdmx
->
mutex
);
return
0
;
}
static
void
prepare_secfilters
(
struct
dvb_demux_feed
*
dvbdmxfeed
)
{
int
i
;
dmx_section_filter_t
*
sf
;
dmx_section_filter_t
*
sf
;
struct
dvb_demux_filter
*
f
;
u8
mask
,
mode
,
doneq
;
if
(
!
(
f
=
dvbdmxfeed
->
filter
))
return
;
do
{
return
;
do
{
sf
=&
f
->
filter
;
doneq
=
0
;
for
(
i
=
0
;
i
<
DVB_DEMUX_MASK_MAX
;
i
++
)
{
...
...
@@ -815,159 +857,169 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
static
int
dmx_section_feed_start_filtering
(
dmx_section_feed_t
*
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
))
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
return
-
ERESTARTSYS
;
if
(
feed
->
is_filtering
)
{
if
(
feed
->
is_filtering
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
EBUSY
;
}
if
(
!
dvbdmxfeed
->
filter
)
{
if
(
!
dvbdmxfeed
->
filter
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
dvbdmxfeed
->
secbufp
=
0
;
dvbdmxfeed
->
seclen
=
0
;
if
(
!
dvbdmx
->
start_feed
)
{
dvbdmxfeed
->
feed
.
sec
.
secbufp
=
0
;
dvbdmxfeed
->
feed
.
sec
.
seclen
=
0
;
if
(
!
dvbdmx
->
start_feed
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
1
;
return
-
ENODEV
;
}
prepare_secfilters
(
dvbdmxfeed
);
ret
=
dvbdmx
->
start_feed
(
dvbdmxfeed
);
if
(
ret
<
0
)
{
if
(
(
ret
=
dvbdmx
->
start_feed
(
dvbdmxfeed
))
<
0
)
{
up
(
&
dvbdmx
->
mutex
);
return
ret
;
}
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
);
up
(
&
dvbdmx
->
mutex
);
return
0
;
}
static
int
dmx_section_feed_stop_filtering
(
struct
dmx_section_feed_s
*
feed
)
{
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmxfeed
->
demux
;
int
ret
;
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmxfeed
->
demux
;
int
ret
;
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
return
-
ERESTARTSYS
;
if
(
!
dvbdmx
->
stop_feed
)
{
if
(
!
dvbdmx
->
stop_feed
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
1
;
return
-
ENODEV
;
}
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
);
up
(
&
dvbdmx
->
mutex
);
return
ret
;
}
static
int
dmx_section_feed_release_filter
(
dmx_section_feed_t
*
feed
,
dmx_section_filter_t
*
filter
)
dmx_section_filter_t
*
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
))
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
return
-
ERESTARTSYS
;
if
(
dvbdmxfilter
->
feed
!=
dvbdmxfeed
)
{
if
(
dvbdmxfilter
->
feed
!=
dvbdmxfeed
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
if
(
feed
->
is_filtering
)
feed
->
stop_filtering
(
feed
);
if
(
feed
->
is_filtering
)
feed
->
stop_filtering
(
feed
);
spin_lock_irq
(
&
dvbdmx
->
lock
);
f
=
dvbdmxfeed
->
filter
;
if
(
f
==
dvbdmxfilter
)
dvbdmxfeed
->
filter
=
dvbdmxfilter
->
next
;
else
{
while
(
f
->
next
!=
dvbdmxfilter
)
f
=
f
->
next
;
f
->
next
=
f
->
next
->
next
;
}
dvbdmxfilter
->
state
=
DMX_STATE_FREE
;
f
=
dvbdmxfeed
->
filter
;
if
(
f
==
dvbdmxfilter
)
dvbdmxfeed
->
filter
=
dvbdmxfilter
->
next
;
else
{
while
(
f
->
next
!=
dvbdmxfilter
)
f
=
f
->
next
;
f
->
next
=
f
->
next
->
next
;
}
dvbdmxfilter
->
state
=
DMX_STATE_FREE
;
spin_unlock_irq
(
&
dvbdmx
->
lock
);
up
(
&
dvbdmx
->
mutex
);
return
0
;
up
(
&
dvbdmx
->
mutex
);
return
0
;
}
static
int
dvbdmx_allocate_section_feed
(
dmx_demux_t
*
demux
,
dmx_section_feed_t
**
feed
,
dmx_section_cb
callback
)
dmx_section_feed_t
**
feed
,
dmx_section_cb
callback
)
{
struct
dvb_demux
*
dvbdmx
=
(
struct
dvb_demux
*
)
demux
;
struct
dvb_demux_feed
*
dvbdmxfeed
;
struct
dvb_demux
*
dvbdmx
=
(
struct
dvb_demux
*
)
demux
;
struct
dvb_demux_feed
*
dvbdmxfeed
;
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
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
;
return
-
EBUSY
;
}
dvbdmxfeed
->
type
=
DMX_TYPE_SEC
;
dvbdmxfeed
->
cb
.
sec
=
callback
;
dvbdmxfeed
->
demux
=
dvbdmx
;
dvbdmxfeed
->
pid
=
0xffff
;
dvbdmxfeed
->
secbufp
=
0
;
dvbdmxfeed
->
filter
=
0
;
dvbdmxfeed
->
buffer
=
0
;
(
*
feed
)
=&
dvbdmxfeed
->
feed
.
sec
;
(
*
feed
)
->
is_filtering
=
0
;
(
*
feed
)
->
parent
=
demux
;
(
*
feed
)
->
priv
=
0
;
(
*
feed
)
->
set
=
dmx_section_feed_set
;
(
*
feed
)
->
allocate_filter
=
dmx_section_feed_allocate_filter
;
(
*
feed
)
->
release_filter
=
dmx_section_feed_release_filter
;
(
*
feed
)
->
start_filtering
=
dmx_section_feed_start_filtering
;
(
*
feed
)
->
stop_filtering
=
dmx_section_feed_stop_filtering
;
up
(
&
dvbdmx
->
mutex
);
return
0
;
dvbdmxfeed
->
type
=
DMX_TYPE_SEC
;
dvbdmxfeed
->
cb
.
sec
=
callback
;
dvbdmxfeed
->
demux
=
dvbdmx
;
dvbdmxfeed
->
pid
=
0xffff
;
dvbdmxfeed
->
feed
.
sec
.
secbufp
=
0
;
dvbdmxfeed
->
filter
=
0
;
dvbdmxfeed
->
buffer
=
0
;
(
*
feed
)
=&
dvbdmxfeed
->
feed
.
sec
;
(
*
feed
)
->
is_filtering
=
0
;
(
*
feed
)
->
parent
=
demux
;
(
*
feed
)
->
priv
=
0
;
(
*
feed
)
->
set
=
dmx_section_feed_set
;
(
*
feed
)
->
allocate_filter
=
dmx_section_feed_allocate_filter
;
(
*
feed
)
->
release_filter
=
dmx_section_feed_release_filter
;
(
*
feed
)
->
start_filtering
=
dmx_section_feed_start_filtering
;
(
*
feed
)
->
stop_filtering
=
dmx_section_feed_stop_filtering
;
up
(
&
dvbdmx
->
mutex
);
return
0
;
}
static
int
dvbdmx_release_section_feed
(
dmx_demux_t
*
demux
,
dmx_section_feed_t
*
feed
)
dmx_section_feed_t
*
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
;
struct
list_head
*
pos
,
*
n
,
*
head
=&
dvbdmx
->
feed_list
;
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
return
-
ERESTARTSYS
;
if
(
dvbdmxfeed
->
state
==
DMX_STATE_FREE
)
{
if
(
dvbdmxfeed
->
state
==
DMX_STATE_FREE
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
#ifndef NOBUFS
if
(
dvbdmxfeed
->
buffer
)
{
vfree
(
dvbdmxfeed
->
buffer
);
dvbdmxfeed
->
buffer
=
0
;
}
if
(
dvbdmxfeed
->
buffer
)
{
vfree
(
dvbdmxfeed
->
buffer
);
dvbdmxfeed
->
buffer
=
0
;
}
#endif
dvbdmxfeed
->
state
=
DMX_STATE_FREE
;
dvbdmxfeed
->
demux
->
pid2feed
[
dvbdmxfeed
->
pid
]
=
0
;
if
(
dvbdmxfeed
->
pid
!=
0xffff
)
dvbdmxfeed
->
demux
->
pid2feed
[
dvbdmxfeed
->
pid
]
=
0
;
up
(
&
dvbdmx
->
mutex
);
return
0
;
dvbdmxfeed
->
state
=
DMX_STATE_FREE
;
if
(
dvbdmxfeed
->
pid
<=
DMX_MAX_PID
)
{
list_for_each_safe
(
pos
,
n
,
head
)
if
(
DMX_FEED_ENTRY
(
pos
)
->
pid
==
dvbdmxfeed
->
pid
)
{
list_del
(
pos
);
break
;
}
dvbdmxfeed
->
pid
=
0xffff
;
}
up
(
&
dvbdmx
->
mutex
);
return
0
;
}
...
...
@@ -977,72 +1029,72 @@ static int dvbdmx_release_section_feed(dmx_demux_t *demux,
static
int
dvbdmx_open
(
dmx_demux_t
*
demux
)
{
struct
dvb_demux
*
dvbdemux
=
(
struct
dvb_demux
*
)
demux
;
struct
dvb_demux
*
dvbdemux
=
(
struct
dvb_demux
*
)
demux
;
if
(
dvbdemux
->
users
>=
MAX_DVB_DEMUX_USERS
)
return
-
EUSERS
;
dvbdemux
->
users
++
;
return
0
;
if
(
dvbdemux
->
users
>=
MAX_DVB_DEMUX_USERS
)
return
-
EUSERS
;
dvbdemux
->
users
++
;
return
0
;
}
static
int
dvbdmx_close
(
struct
dmx_demux_s
*
demux
)
{
struct
dvb_demux
*
dvbdemux
=
(
struct
dvb_demux
*
)
demux
;
struct
dvb_demux
*
dvbdemux
=
(
struct
dvb_demux
*
)
demux
;
if
(
dvbdemux
->
users
==
0
)
return
-
ENODEV
;
dvbdemux
->
users
--
;
//FIXME: release any unneeded resources if users==0
return
0
;
if
(
dvbdemux
->
users
==
0
)
return
-
ENODEV
;
dvbdemux
->
users
--
;
//FIXME: release any unneeded resources if users==0
return
0
;
}
static
int
dvbdmx_write
(
dmx_demux_t
*
demux
,
const
char
*
buf
,
size_t
count
)
{
struct
dvb_demux
*
dvbdemux
=
(
struct
dvb_demux
*
)
demux
;
struct
dvb_demux
*
dvbdemux
=
(
struct
dvb_demux
*
)
demux
;
if
((
!
demux
->
frontend
)
||
(
demux
->
frontend
->
source
!=
DMX_MEMORY_FE
))
return
-
EINVAL
;
if
((
!
demux
->
frontend
)
||
(
demux
->
frontend
->
source
!=
DMX_MEMORY_FE
))
return
-
EINVAL
;
if
(
down_interruptible
(
&
dvbdemux
->
mutex
))
if
(
down_interruptible
(
&
dvbdemux
->
mutex
))
return
-
ERESTARTSYS
;
dvb_dmx_swfilter
(
dvbdemux
,
buf
,
count
);
up
(
&
dvbdemux
->
mutex
);
return
count
;
dvb_dmx_swfilter
(
dvbdemux
,
buf
,
count
);
up
(
&
dvbdemux
->
mutex
);
return
count
;
}
static
int
dvbdmx_add_frontend
(
dmx_demux_t
*
demux
,
dmx_frontend_t
*
frontend
)
dmx_frontend_t
*
frontend
)
{
struct
dvb_demux
*
dvbdemux
=
(
struct
dvb_demux
*
)
demux
;
struct
list_head
*
pos
,
*
head
=&
dvbdemux
->
frontend_list
;
struct
dvb_demux
*
dvbdemux
=
(
struct
dvb_demux
*
)
demux
;
struct
list_head
*
pos
,
*
head
=&
dvbdemux
->
frontend_list
;
if
(
!
(
frontend
->
id
&&
frontend
->
vendor
&&
frontend
->
model
))
return
-
EINVAL
;
return
-
EINVAL
;
list_for_each
(
pos
,
head
)
{
if
(
!
strcmp
(
DMX_FE_ENTRY
(
pos
)
->
id
,
frontend
->
id
))
return
-
EEXIST
;
if
(
!
strcmp
(
DMX_FE_ENTRY
(
pos
)
->
id
,
frontend
->
id
))
return
-
EEXIST
;
}
list_add
(
&
(
frontend
->
connectivity_list
),
head
);
return
0
;
return
0
;
}
static
int
dvbdmx_remove_frontend
(
dmx_demux_t
*
demux
,
dmx_frontend_t
*
frontend
)
dmx_frontend_t
*
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
)
{
list_del
(
pos
);
if
(
DMX_FE_ENTRY
(
pos
)
==
frontend
)
{
list_del
(
pos
);
return
0
;
}
}
...
...
@@ -1052,123 +1104,129 @@ dvbdmx_remove_frontend(dmx_demux_t *demux,
static
struct
list_head
*
dvbdmx_get_frontends
(
dmx_demux_t
*
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
;
return
&
dvbdemux
->
frontend_list
;
if
(
list_empty
(
&
dvbdemux
->
frontend_list
))
return
NULL
;
return
&
dvbdemux
->
frontend_list
;
}
static
int
dvbdmx_connect_frontend
(
dmx_demux_t
*
demux
,
dmx_frontend_t
*
frontend
)
dmx_frontend_t
*
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
))
if
(
demux
->
frontend
)
return
-
EINVAL
;
if
(
down_interruptible
(
&
dvbdemux
->
mutex
))
return
-
ERESTARTSYS
;
demux
->
frontend
=
frontend
;
up
(
&
dvbdemux
->
mutex
);
return
0
;
demux
->
frontend
=
frontend
;
up
(
&
dvbdemux
->
mutex
);
return
0
;
}
static
int
dvbdmx_disconnect_frontend
(
dmx_demux_t
*
demux
)
{
struct
dvb_demux
*
dvbdemux
=
(
struct
dvb_demux
*
)
demux
;
struct
dvb_demux
*
dvbdemux
=
(
struct
dvb_demux
*
)
demux
;
if
(
down_interruptible
(
&
dvbdemux
->
mutex
))
if
(
down_interruptible
(
&
dvbdemux
->
mutex
))
return
-
ERESTARTSYS
;
demux
->
frontend
=
NULL
;
up
(
&
dvbdemux
->
mutex
);
return
0
;
demux
->
frontend
=
NULL
;
up
(
&
dvbdemux
->
mutex
);
return
0
;
}
static
int
dvbdmx_get_pes_pids
(
dmx_demux_t
*
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
;
memcpy
(
pids
,
dvbdemux
->
pids
,
5
*
sizeof
(
u16
));
return
0
;
}
int
dvb_dmx_init
(
struct
dvb_demux
*
dvbdemux
)
{
int
i
;
dmx_demux_t
*
dmx
=&
dvbdemux
->
dmx
;
int
i
;
dmx_demux_t
*
dmx
=&
dvbdemux
->
dmx
;
dvbdemux
->
users
=
0
;
dvbdemux
->
users
=
0
;
dvbdemux
->
filter
=
vmalloc
(
dvbdemux
->
filternum
*
sizeof
(
struct
dvb_demux_filter
));
if
(
!
dvbdemux
->
filter
)
return
-
ENOMEM
;
return
-
ENOMEM
;
dvbdemux
->
feed
=
vmalloc
(
dvbdemux
->
feednum
*
sizeof
(
struct
dvb_demux_feed
));
if
(
!
dvbdemux
->
feed
)
{
vfree
(
dvbdemux
->
filter
);
return
-
ENOMEM
;
vfree
(
dvbdemux
->
filter
);
return
-
ENOMEM
;
}
for
(
i
=
0
;
i
<
dvbdemux
->
filternum
;
i
++
)
{
dvbdemux
->
filter
[
i
].
state
=
DMX_STATE_FREE
;
dvbdemux
->
filter
[
i
].
index
=
i
;
}
for
(
i
=
0
;
i
<
dvbdemux
->
filternum
;
i
++
)
{
dvbdemux
->
filter
[
i
].
state
=
DMX_STATE_FREE
;
dvbdemux
->
filter
[
i
].
index
=
i
;
}
for
(
i
=
0
;
i
<
dvbdemux
->
feednum
;
i
++
)
dvbdemux
->
feed
[
i
].
state
=
DMX_STATE_FREE
;
dvbdemux
->
frontend_list
.
next
=
dvbdemux
->
frontend_list
.
prev
=
&
dvbdemux
->
frontend_list
;
for
(
i
=
0
;
i
<
DMX_TS_PES_OTHER
;
i
++
)
{
dvbdemux
->
pesfilter
[
i
]
=
NULL
;
dvbdemux
->
pids
[
i
]
=
0xffff
;
for
(
i
=
0
;
i
<
dvbdemux
->
feednum
;
i
++
)
dvbdemux
->
feed
[
i
].
state
=
DMX_STATE_FREE
;
dvbdemux
->
frontend_list
.
next
=
dvbdemux
->
frontend_list
.
prev
=
&
dvbdemux
->
frontend_list
;
for
(
i
=
0
;
i
<
DMX_TS_PES_OTHER
;
i
++
)
{
dvbdemux
->
pesfilter
[
i
]
=
NULL
;
dvbdemux
->
pids
[
i
]
=
0xffff
;
}
dvbdemux
->
playing
=
dvbdemux
->
recording
=
0
;
memset
(
dvbdemux
->
pid2feed
,
0
,
(
DMX_MAX_PID
+
1
)
*
sizeof
(
struct
dvb_demux_feed
*
));
dvbdemux
->
tsbufp
=
0
;
dmx
->
frontend
=
0
;
dmx
->
reg_list
.
next
=
dmx
->
reg_list
.
prev
=&
dmx
->
reg_list
;
dmx
->
priv
=
(
void
*
)
dvbdemux
;
//dmx->users=0; // reset in dmx_register_demux()
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
);
dvbdemux
->
playing
=
dvbdemux
->
recording
=
0
;
INIT_LIST_HEAD
(
&
dvbdemux
->
feed_list
);
dvbdemux
->
tsbufp
=
0
;
if
(
!
dvbdemux
->
check_crc32
)
dvbdemux
->
check_crc32
=
dvb_dmx_crc32
;
if
(
!
dvbdemux
->
memcopy
)
dvbdemux
->
memcopy
=
dvb_dmx_memcopy
;
dmx
->
frontend
=
0
;
dmx
->
reg_list
.
next
=
dmx
->
reg_list
.
prev
=&
dmx
->
reg_list
;
dmx
->
priv
=
(
void
*
)
dvbdemux
;
//dmx->users=0; // reset in dmx_register_demux()
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
(
dmx_register_demux
(
dmx
)
<
0
)
return
-
1
;
if
(
dmx_register_demux
(
dmx
)
<
0
)
return
-
1
;
return
0
;
return
0
;
}
int
dvb_dmx_release
(
struct
dvb_demux
*
dvbdemux
)
{
dmx_demux_t
*
dmx
=&
dvbdemux
->
dmx
;
dmx_demux_t
*
dmx
=&
dvbdemux
->
dmx
;
dmx_unregister_demux
(
dmx
);
dmx_unregister_demux
(
dmx
);
if
(
dvbdemux
->
filter
)
vfree
(
dvbdemux
->
filter
);
vfree
(
dvbdemux
->
filter
);
if
(
dvbdemux
->
feed
)
vfree
(
dvbdemux
->
feed
);
return
0
;
vfree
(
dvbdemux
->
feed
);
return
0
;
}
#if 0
...
...
drivers/media/dvb/dvb-core/dvb_demux.h
View file @
28003225
...
...
@@ -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_ */
drivers/media/dvb/dvb-core/dvb_filter.c
View file @
28003225
#include <linux/module.h>
#include <linux/videodev.h>
#include "dvb_filter.h"
unsigned
int
bitrates
[
3
][
16
]
=
...
...
@@ -52,10 +51,10 @@ void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
if (buf[1]&PAY_START) {
if (p->plength == MMAX_PLENGTH-6 && p->found>6){
p->plength = p->found-6;
p->found = 0;
p->found = 0;
send_ipack(p);
dvb_filter_ipack_reset(p);
}
}
}
if (buf[3] & ADAPT_FIELD) { // adaptation field?
off = buf[4] + 1;
...
...
@@ -71,12 +70,12 @@ static
int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr)
{
uint8_t pct;
if (pr) printk( "Pic header: ");
pic->temporal_reference[field] = (( headr[0] << 2 ) |
(headr[1] & 0x03) )& 0x03ff;
if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
pct = ( headr[1] >> 2 ) & 0x07;
pic->picture_coding_type[field] = pct;
if (pr) {
...
...
@@ -90,26 +89,26 @@ int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr)
case P_FRAME:
printk( " P-FRAME");
break;
}
}
}
}
pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) |
( (headr[3] & 0x1F) << 11) ) & 0xffff;
if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
((headr[4] & 0x80) >> 3);
if ( pct == B_FRAME ){
pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
}
}
if (pr) printk( " pic head param: 0x%x",
pic->picture_header_parameter);
return pct;
}
}
#endif
#if 0
...
...
@@ -130,14 +129,14 @@ int read_gop_header(uint8_t *headr, mpg_picture *pic, int pr)
pic->closed_gop = 1;
} else {
pic->closed_gop = 0;
}
}
if (pr) printk("closed: %d", pic->closed_gop);
if ( ( headr[3] & 0x20 ) != 0 ){
pic->broken_link = 1;
} else {
} else {
pic->broken_link = 0;
}
}
if (pr) printk(" broken: %d\n", pic->broken_link);
return 0;
...
...
@@ -160,37 +159,37 @@ int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr)
sw = (int)((headr[3]&0xF0) >> 4) ;
switch( sw ){
case 1:
case 1:
if (pr)
printk("Videostream: ASPECT: 1:1");
vi->aspect_ratio = 100;
break;
case 2:
break;
case 2:
if (pr)
printk("Videostream: ASPECT: 4:3");
vi->aspect_ratio = 133;
break;
case 3:
break;
case 3:
if (pr)
printk("Videostream: ASPECT: 16:9");
vi->aspect_ratio = 177;
break;
break;
case 4:
if (pr)
printk("Videostream: ASPECT: 2.21:1");
vi->aspect_ratio = 221;
break;
break;
case 5 ... 15:
if (pr)
printk("Videostream: ASPECT: reserved");
vi->aspect_ratio = 0;
break;
break;
default:
vi->aspect_ratio = 0;
return -1;
}
}
if (pr)
printk(" Size = %dx%d",vi->horizontal_size,vi->vertical_size);
...
...
@@ -221,29 +220,29 @@ int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr)
printk(" FRate: 29.97 fps");
vi->framerate = 29970;
form = VIDEO_MODE_NTSC;
break;
case 5:
break;
case 5:
if (pr)
printk(" FRate: 30 fps");
vi->framerate = 30000;
form = VIDEO_MODE_NTSC;
break;
case 6:
break;
case 6:
if (pr)
printk(" FRate: 50 fps");
vi->framerate = 50000;
form = VIDEO_MODE_PAL;
break;
case 7:
break;
case 7:
if (pr)
printk(" FRate: 60 fps");
vi->framerate = 60000;
form = VIDEO_MODE_NTSC;
break;
}
vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
break;
}
vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
vi->vbv_buffer_size
= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
...
...
@@ -259,7 +258,7 @@ int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr)
}
#endif
#if 0
static
int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
...
...
@@ -267,7 +266,7 @@ int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
uint8_t *headr;
int found = 0;
int c = 0;
while (found < 4 && c+4 < count){
uint8_t *b;
...
...
@@ -277,7 +276,7 @@ int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
else {
c++;
}
}
}
if (! found) return -1;
c += 4;
...
...
@@ -288,7 +287,7 @@ int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
return 0;
}
#endif
#if 0
static
...
...
@@ -306,9 +305,9 @@ int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
found = 2;
else {
c++;
}
}
c++;
}
}
if (!found) return -1;
...
...
@@ -330,7 +329,7 @@ int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
printk(" BRate: reserved");
else
printk(" BRate: %d kb/s", ai->bit_rate/1000);
}
}
fr = (headr[2] & 0x0c ) >> 2;
ai->frequency = freq[fr]*100;
...
...
@@ -340,41 +339,41 @@ int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
else
printk(" Freq: %d kHz\n",ai->frequency);
}
}
ai->off = c;
return 0;
}
#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
;
int
c
=
0
;
uint8_t
frame
=
0
;
int
fr
=
0
;
while
(
!
found
&&
c
<
count
){
uint8_t
*
b
=
mbuf
+
c
;
if
(
b
[
0
]
==
0x0b
&&
b
[
1
]
==
0x77
)
found
=
1
;
else
{
c
++
;
}
}
c
++
;
}
}
if
(
!
found
)
return
-
1
;
if
(
pr
)
printk
(
"Audiostream: AC3"
);
ai
->
off
=
c
;
if
(
c
+
5
>=
count
)
return
-
1
;
ai
->
layer
=
0
;
// 0 for AC3
headr
=
mbuf
+
c
+
2
;
frame
=
(
headr
[
2
]
&
0x3f
);
ai
->
bit_rate
=
ac3_bitrates
[
frame
>>
1
]
*
1000
;
...
...
@@ -420,8 +419,8 @@ uint8_t *skip_pes_header(uint8_t **bufp)
} else { /* mpeg1 */
for (buf = inbuf + 6; *buf == 0xff; buf++)
if (buf == inbuf + 6 + 16) {
break;
}
break;
}
if ((*buf & 0xc0) == 0x40)
buf += 2;
skip = mpeg1_skip_table [*buf >> 4];
...
...
@@ -433,7 +432,7 @@ uint8_t *skip_pes_header(uint8_t **bufp)
*bufp = buf;
return pts;
}
}
#endif
#if 0
...
...
@@ -509,7 +508,7 @@ void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic )
pic->progressive_frame = 1;
pic->picture_coding_parameter = 0x000010;
}
/* Reset flag */
pic->picture_display_extension_flag[field_type] = 0;
...
...
@@ -527,7 +526,7 @@ void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic )
} else {
pic->frame_centre_horizontal_offset[3] = last_h_offset;
pic->frame_centre_vertical_offset[3] = last_v_offset;
}
}
}
#endif
...
...
@@ -566,7 +565,7 @@ void dvb_filter_pes2ts_init(dvb_filter_pes2ts_t *p2ts, unsigned short pid,
dvb_filter_pes2ts_cb_t
*
cb
,
void
*
priv
)
{
unsigned
char
*
buf
=
p2ts
->
buf
;
buf
[
0
]
=
0x47
;
buf
[
1
]
=
(
pid
>>
8
);
buf
[
2
]
=
pid
&
0xff
;
...
...
@@ -579,7 +578,7 @@ int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len)
{
unsigned
char
*
buf
=
p2ts
->
buf
;
int
ret
=
0
,
rest
;
//len=6+((pes[4]<<8)|pes[5]);
buf
[
1
]
|=
0x40
;
...
...
@@ -592,7 +591,7 @@ int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len)
buf
[
1
]
&=~
0x40
;
}
if
(
!
len
)
return
0
;
return
0
;
buf
[
3
]
=
0x30
|
((
p2ts
->
cc
++
)
&
0x0f
);
rest
=
183
-
len
;
if
(
rest
)
{
...
...
@@ -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
;
}
drivers/media/dvb/dvb-core/dvb_filter.h
View file @
28003225
...
...
@@ -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
drivers/media/dvb/dvb-core/dvb_frontend.c
View file @
28003225
...
...
@@ -27,16 +27,14 @@
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/compatmac.h>
#include <linux/list.h>
#include "compat.h"
#include "dvb_frontend.h"
#include "dvbdev.h"
static
int
dvb_frontend_debug
=
0
;
static
int
dvb_shutdown_timeout
=
0
;
static
int
dvb_shutdown_timeout
=
5
;
#define dprintk if (dvb_frontend_debug) printk
...
...
@@ -52,18 +50,10 @@ struct dvb_fe_events {
};
struct
dvb_fe_notifier_callbacks
{
struct
list_head
list_head
;
void
(
*
callback
)
(
fe_status_t
s
,
void
*
data
);
void
*
data
;
};
struct
dvb_frontend_data
{
struct
dvb_frontend_info
*
info
;
struct
dvb_frontend
frontend
;
struct
dvb_device
*
dvbdev
;
struct
list_head
notifier_callbacks
;
struct
dvb_frontend_parameters
parameters
;
struct
dvb_fe_events
events
;
struct
semaphore
sem
;
...
...
@@ -92,8 +82,17 @@ struct dvb_frontend_ioctl_data {
};
struct
dvb_frontend_notifier_data
{
struct
list_head
list_head
;
struct
dvb_adapter
*
adapter
;
void
(
*
callback
)
(
fe_status_t
s
,
void
*
data
);
void
*
data
;
};
static
LIST_HEAD
(
frontend_list
);
static
LIST_HEAD
(
frontend_ioctl_list
);
static
LIST_HEAD
(
frontend_notifier_list
);
static
DECLARE_MUTEX
(
frontend_mutex
);
...
...
@@ -153,6 +152,7 @@ void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive)
if
(
!
recursive
)
{
if
(
down_interruptible
(
&
frontend_mutex
))
return
;
this_fe
->
bending
=
0
;
}
...
...
@@ -170,7 +170,7 @@ void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive)
frequency
+=
this_fe
->
lnb_drift
;
frequency
+=
this_fe
->
bending
;
if
(
this_fe
!=
fe
&&
if
(
this_fe
!=
fe
&&
fe
->
lost_sync_count
!=
-
1
&&
frequency
>
f
-
stepsize
&&
frequency
<
f
+
stepsize
)
{
if
(
recursive
%
2
)
...
...
@@ -192,9 +192,6 @@ static
void
dvb_call_frontend_notifiers
(
struct
dvb_frontend_data
*
fe
,
fe_status_t
s
)
{
struct
list_head
*
e
;
struct
dvb_fe_notifier_callbacks
*
c
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
((
fe
->
status
&
FE_HAS_LOCK
)
&&
!
(
s
&
FE_HAS_LOCK
))
...
...
@@ -211,10 +208,8 @@ void dvb_call_frontend_notifiers (struct dvb_frontend_data *fe,
/**
* now tell the Demux about the TS status changes...
*/
list_for_each
(
e
,
&
fe
->
notifier_callbacks
)
{
c
=
list_entry
(
e
,
struct
dvb_fe_notifier_callbacks
,
list_head
);
c
->
callback
(
fe
->
status
,
c
->
data
);
}
if
(
fe
->
frontend
.
notifier_callback
)
fe
->
frontend
.
notifier_callback
(
fe
->
status
,
fe
->
frontend
.
notifier_data
);
}
...
...
@@ -296,38 +291,6 @@ int dvb_frontend_get_event (struct dvb_frontend_data *fe,
}
static
struct
dvb_frontend_parameters
default_param
[]
=
{
{
/* NTV on Astra */
frequency:
12669500
-
10600000
,
inversion:
INVERSION_OFF
,
{
qpsk
:
{
symbol_rate
:
22000000
,
fec_inner
:
FEC_AUTO
}
}
},
{
/* Cable */
frequency:
394000000
,
inversion:
INVERSION_OFF
,
{
qam
:
{
symbol_rate
:
6900000
,
fec_inner:
FEC_AUTO
,
modulation:
QAM_64
}
}
},
{
/* DVB-T */
frequency:
730000000
,
inversion:
INVERSION_OFF
,
{
ofdm
:
{
bandwidth
:
BANDWIDTH_8_MHZ
,
code_rate_HP:
FEC_2_3
,
code_rate_LP:
FEC_1_2
,
constellation:
QAM_16
,
transmission_mode:
TRANSMISSION_MODE_2K
,
guard_interval:
GUARD_INTERVAL_1_8
,
hierarchy_information:
HIERARCHY_NONE
}
}
}
};
static
int
dvb_frontend_set_parameters
(
struct
dvb_frontend_data
*
fe
,
struct
dvb_frontend_parameters
*
param
,
...
...
@@ -336,8 +299,6 @@ int dvb_frontend_set_parameters (struct dvb_frontend_data *fe,
struct
dvb_frontend
*
frontend
=
&
fe
->
frontend
;
int
err
;
dvb_bend_frequency
(
fe
,
0
);
if
(
first_trial
)
{
fe
->
timeout_count
=
0
;
fe
->
lost_sync_count
=
0
;
...
...
@@ -349,6 +310,8 @@ int dvb_frontend_set_parameters (struct dvb_frontend_data *fe,
sizeof
(
struct
dvb_frontend_parameters
));
}
dvb_bend_frequency
(
fe
,
0
);
dprintk
(
"%s: f == %i, drift == %i
\n
"
,
__FUNCTION__
,
param
->
frequency
,
fe
->
lnb_drift
);
...
...
@@ -365,23 +328,12 @@ static
void
dvb_frontend_init
(
struct
dvb_frontend_data
*
fe
)
{
struct
dvb_frontend
*
frontend
=
&
fe
->
frontend
;
struct
dvb_frontend_parameters
*
init_param
;
printk
(
"DVB: initialising frontend %i:%i (%s)...
\n
"
,
frontend
->
i2c
->
adapter
->
num
,
frontend
->
i2c
->
id
,
fe
->
info
->
name
);
dprintk
(
"DVB: initialising frontend %i:%i (%s)...
\n
"
,
frontend
->
i2c
->
adapter
->
num
,
frontend
->
i2c
->
id
,
fe
->
info
->
name
);
dvb_frontend_internal_ioctl
(
frontend
,
FE_INIT
,
NULL
);
if
(
fe
->
info
->
type
==
FE_QPSK
)
{
dvb_frontend_internal_ioctl
(
frontend
,
FE_SET_VOLTAGE
,
(
void
*
)
SEC_VOLTAGE_13
);
dvb_frontend_internal_ioctl
(
frontend
,
FE_SET_TONE
,
(
void
*
)
SEC_TONE_ON
);
}
init_param
=
&
default_param
[
fe
->
info
->
type
-
FE_QPSK
];
dvb_frontend_set_parameters
(
fe
,
init_param
,
1
);
}
...
...
@@ -464,7 +416,7 @@ int dvb_frontend_is_exiting (struct dvb_frontend_data *fe)
if
(
fe
->
exit
)
return
1
;
if
(
fe
->
dvbdev
->
users
==
0
&&
dvb_shutdown_timeout
)
if
(
fe
->
dvbdev
->
writers
==
1
)
if
(
jiffies
-
fe
->
release_jiffies
>
dvb_shutdown_timeout
*
HZ
)
return
1
;
...
...
@@ -482,13 +434,27 @@ int dvb_frontend_thread (void *data)
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
lock_kernel
();
daemonize
(
"kdvb-fe"
);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61))
daemonize
();
#else
daemonize
(
"dvb fe"
);
#endif
/* not needed anymore in 2.5.x, done in daemonize() */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
reparent_to_init
();
#endif
sigfillset
(
&
current
->
blocked
);
fe
->
thread
=
current
;
snprintf
(
current
->
comm
,
sizeof
(
current
->
comm
),
"kdvb-fe-%i:%i"
,
fe
->
frontend
.
i2c
->
adapter
->
num
,
fe
->
frontend
.
i2c
->
id
);
unlock_kernel
();
dvb_call_frontend_notifiers
(
fe
,
0
);
dvb_frontend_init
(
fe
);
fe
->
lost_sync_count
=
-
1
;
while
(
!
dvb_frontend_is_exiting
(
fe
))
{
up
(
&
fe
->
sem
);
/* is locked when we enter the thread... */
...
...
@@ -499,6 +465,9 @@ int dvb_frontend_thread (void *data)
return
-
ERESTARTSYS
;
}
if
(
fe
->
lost_sync_count
==
-
1
)
continue
;
if
(
dvb_frontend_is_exiting
(
fe
))
break
;
...
...
@@ -513,10 +482,14 @@ int dvb_frontend_thread (void *data)
fe
->
lost_sync_count
=
0
;
}
else
{
fe
->
lost_sync_count
++
;
if
(
fe
->
lost_sync_count
<
10
)
/* XXX FIXME CHECKME! */
continue
;
dvb_frontend_recover
(
fe
);
delay
=
HZ
/
5
;
if
(
!
(
fe
->
info
->
caps
&
FE_CAN_RECOVER
))
{
if
(
!
(
fe
->
info
->
caps
&
FE_CAN_CLEAN_SETUP
))
{
if
(
fe
->
lost_sync_count
<
10
)
continue
;
}
dvb_frontend_recover
(
fe
);
delay
=
HZ
/
5
;
}
if
(
jiffies
-
fe
->
lost_sync_jiffies
>
TIMEOUT
)
{
s
|=
FE_TIMEDOUT
;
if
((
fe
->
status
&
FE_TIMEDOUT
)
==
0
)
...
...
@@ -528,7 +501,9 @@ int dvb_frontend_thread (void *data)
dvb_frontend_add_event
(
fe
,
s
);
};
dvb_frontend_internal_ioctl
(
&
fe
->
frontend
,
FE_SLEEP
,
NULL
);
if
(
dvb_shutdown_timeout
)
dvb_frontend_internal_ioctl
(
&
fe
->
frontend
,
FE_SLEEP
,
NULL
);
up
(
&
fe
->
sem
);
fe
->
thread
=
NULL
;
return
0
;
...
...
@@ -536,30 +511,36 @@ int dvb_frontend_thread (void *data)
static
void
dvb_frontend_st
art
(
struct
dvb_frontend_data
*
fe
)
void
dvb_frontend_st
op
(
struct
dvb_frontend_data
*
fe
)
{
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
!
fe
->
exit
&&
!
fe
->
thread
)
{
if
(
down_interruptible
(
&
fe
->
sem
))
return
;
kernel_thread
(
dvb_frontend_thread
,
fe
,
0
);
}
while
(
fe
->
thread
)
{
fe
->
exit
=
1
;
wake_up_interruptible
(
&
fe
->
wait_queue
);
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
(
5
);
if
(
signal_pending
(
current
))
break
;
};
}
static
void
dvb_frontend_st
op
(
struct
dvb_frontend_data
*
fe
)
void
dvb_frontend_st
art
(
struct
dvb_frontend_data
*
fe
)
{
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
fe
->
exit
=
1
;
wake_up_interruptible
(
&
fe
->
wait_queu
e
);
if
(
fe
->
thread
)
dvb_frontend_stop
(
f
e
);
while
(
fe
->
thread
)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
(
5
);
};
if
(
down_interruptible
(
&
fe
->
sem
))
return
;
fe
->
exit
=
0
;
fe
->
thread
=
(
void
*
)
~
0
;
kernel_thread
(
dvb_frontend_thread
,
fe
,
0
);
}
...
...
@@ -615,9 +596,6 @@ unsigned int dvb_frontend_poll (struct file *file, struct poll_table_struct *wai
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
fe
->
events
.
eventw
!=
fe
->
events
.
eventr
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
poll_wait
(
file
,
&
fe
->
events
.
wait_queue
,
wait
);
if
(
fe
->
events
.
eventw
!=
fe
->
events
.
eventr
)
...
...
@@ -639,10 +617,12 @@ int dvb_frontend_open (struct inode *inode, struct file *file)
if
((
ret
=
dvb_generic_open
(
inode
,
file
))
<
0
)
return
ret
;
dvb_frontend_start
(
fe
);
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_RDONLY
)
{
dvb_frontend_start
(
fe
);
/* empty event queue */
fe
->
events
.
eventr
=
fe
->
events
.
eventw
;
/* empty event queue */
fe
->
events
.
eventr
=
fe
->
events
.
eventw
;
}
return
ret
;
}
...
...
@@ -656,7 +636,8 @@ int dvb_frontend_release (struct inode *inode, struct file *file)
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
fe
->
release_jiffies
=
jiffies
;
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_RDONLY
)
fe
->
release_jiffies
=
jiffies
;
return
dvb_generic_release
(
inode
,
file
);
}
...
...
@@ -673,7 +654,6 @@ dvb_add_frontend_ioctls (struct dvb_adapter *adapter,
{
struct
dvb_frontend_ioctl_data
*
ioctl
;
struct
list_head
*
entry
;
int
frontend_count
=
0
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
...
...
@@ -706,14 +686,12 @@ dvb_add_frontend_ioctls (struct dvb_adapter *adapter,
fe
->
frontend
.
before_ioctl
=
before_ioctl
;
fe
->
frontend
.
after_ioctl
=
after_ioctl
;
fe
->
frontend
.
before_after_data
=
before_after_data
;
dvb_frontend_start
(
fe
);
frontend_count
++
;
}
}
up
(
&
frontend_mutex
);
return
frontend_count
;
return
0
;
}
...
...
@@ -724,12 +702,11 @@ dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
int
(
*
after_ioctl
)
(
struct
dvb_frontend
*
frontend
,
unsigned
int
cmd
,
void
*
arg
))
{
struct
list_head
*
entry
;
struct
list_head
*
entry
,
*
n
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
down_interruptible
(
&
frontend_mutex
))
return
;
down
(
&
frontend_mutex
);
list_for_each
(
entry
,
&
frontend_list
)
{
struct
dvb_frontend_data
*
fe
;
...
...
@@ -746,6 +723,22 @@ dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
}
}
list_for_each_safe
(
entry
,
n
,
&
frontend_ioctl_list
)
{
struct
dvb_frontend_ioctl_data
*
ioctl
;
ioctl
=
list_entry
(
entry
,
struct
dvb_frontend_ioctl_data
,
list_head
);
if
(
ioctl
->
adapter
==
adapter
&&
ioctl
->
before_ioctl
==
before_ioctl
&&
ioctl
->
after_ioctl
==
after_ioctl
)
{
list_del
(
&
ioctl
->
list_head
);
kfree
(
ioctl
);
break
;
}
}
up
(
&
frontend_mutex
);
}
...
...
@@ -755,41 +748,43 @@ dvb_add_frontend_notifier (struct dvb_adapter *adapter,
void
(
*
callback
)
(
fe_status_t
s
,
void
*
data
),
void
*
data
)
{
struct
list_head
*
entry
;
struct
dvb_frontend_notifier_data
*
notifier
;
struct
list_head
*
entry
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
down_interruptible
(
&
frontend_mutex
))
return
-
ERESTARTSYS
;
list_for_each
(
entry
,
&
frontend_list
)
{
struct
dvb_frontend_data
*
fe
;
notifier
=
kmalloc
(
sizeof
(
struct
dvb_frontend_notifier_data
),
GFP_KERNEL
);
fe
=
list_entry
(
entry
,
struct
dvb_frontend_data
,
list_head
);
if
(
!
notifier
)
{
up
(
&
frontend_mutex
);
return
-
ENOMEM
;
}
if
(
fe
->
frontend
.
i2c
->
adapter
==
adapter
)
{
struct
dvb_fe_notifier_callbacks
*
e
;
notifier
->
adapter
=
adapter
;
notifier
->
callback
=
callback
;
notifier
->
data
=
data
;
e
=
kmalloc
(
sizeof
(
struct
dvb_fe_notifier_callbacks
),
GFP_KERNEL
);
list_add_tail
(
&
notifier
->
list_head
,
&
frontend_notifier_list
);
if
(
!
e
)
{
up
(
&
frontend_mutex
);
return
-
ENOMEM
;
}
list_for_each
(
entry
,
&
frontend_list
)
{
struct
dvb_frontend_data
*
fe
;
e
->
callback
=
callback
;
e
->
data
=
data
;
list_add_tail
(
&
e
->
list_head
,
&
fe
->
notifier_callbacks
);
fe
=
list_entry
(
entry
,
struct
dvb_frontend_data
,
list_head
);
up
(
&
frontend_mutex
);
return
0
;
if
(
fe
->
frontend
.
i2c
->
adapter
==
adapter
&&
fe
->
frontend
.
notifier_callback
==
NULL
)
{
fe
->
frontend
.
notifier_callback
=
callback
;
fe
->
frontend
.
notifier_data
=
data
;
}
}
up
(
&
frontend_mutex
);
return
-
ENODEV
;
return
0
;
}
...
...
@@ -797,30 +792,37 @@ void
dvb_remove_frontend_notifier
(
struct
dvb_adapter
*
adapter
,
void
(
*
callback
)
(
fe_status_t
s
,
void
*
data
))
{
struct
list_head
*
entry
;
struct
list_head
*
entry
,
*
n
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
down_interruptible
(
&
frontend_mutex
))
return
;
down
(
&
frontend_mutex
);
list_for_each
(
entry
,
&
frontend_list
)
{
struct
dvb_frontend_data
*
fe
;
fe
=
list_entry
(
entry
,
struct
dvb_frontend_data
,
list_head
);
if
(
fe
->
frontend
.
i2c
->
adapter
==
adapter
)
{
struct
list_head
*
e0
,
*
n0
;
if
(
fe
->
frontend
.
i2c
->
adapter
==
adapter
&&
fe
->
frontend
.
notifier_callback
==
callback
)
{
fe
->
frontend
.
notifier_callback
=
NULL
;
list_for_each_safe
(
e0
,
n0
,
&
fe
->
notifier_callbacks
)
{
struct
dvb_fe_notifier_callbacks
*
e
;
}
}
e
=
list_entry
(
e0
,
struct
dvb_fe_notifier_callbacks
,
list_head
);
list_del
(
&
e
->
list_head
);
kfree
(
e
);
}
list_for_each_safe
(
entry
,
n
,
&
frontend_notifier_list
)
{
struct
dvb_frontend_notifier_data
*
notifier
;
notifier
=
list_entry
(
entry
,
struct
dvb_frontend_notifier_data
,
list_head
);
if
(
notifier
->
adapter
==
adapter
&&
notifier
->
callback
==
callback
)
{
list_del
(
&
notifier
->
list_head
);
kfree
(
notifier
);
break
;
}
}
...
...
@@ -849,7 +851,7 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
struct
list_head
*
entry
;
struct
dvb_frontend_data
*
fe
;
static
const
struct
dvb_device
dvbdev_template
=
{
.
users
=
1
,
.
users
=
~
0
,
.
writers
=
1
,
.
fops
=
&
dvb_frontend_fops
,
.
kernel_ioctl
=
dvb_frontend_ioctl
...
...
@@ -873,7 +875,6 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
init_MUTEX
(
&
fe
->
events
.
sem
);
fe
->
events
.
eventw
=
fe
->
events
.
eventr
=
0
;
fe
->
events
.
overflow
=
0
;
INIT_LIST_HEAD
(
&
fe
->
notifier_callbacks
);
fe
->
frontend
.
ioctl
=
ioctl
;
fe
->
frontend
.
i2c
=
i2c
;
...
...
@@ -891,13 +892,30 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
fe
->
frontend
.
before_ioctl
=
ioctl
->
before_ioctl
;
fe
->
frontend
.
after_ioctl
=
ioctl
->
after_ioctl
;
fe
->
frontend
.
before_after_data
=
ioctl
->
before_after_data
;
dvb_frontend_start
(
fe
);
break
;
}
}
list_for_each
(
entry
,
&
frontend_notifier_list
)
{
struct
dvb_frontend_notifier_data
*
notifier
;
notifier
=
list_entry
(
entry
,
struct
dvb_frontend_notifier_data
,
list_head
);
if
(
notifier
->
adapter
==
i2c
->
adapter
)
{
fe
->
frontend
.
notifier_callback
=
notifier
->
callback
;
fe
->
frontend
.
notifier_data
=
notifier
->
data
;
break
;
}
}
list_add_tail
(
&
fe
->
list_head
,
&
frontend_list
);
printk
(
"DVB: registering frontend %i:%i (%s)...
\n
"
,
fe
->
frontend
.
i2c
->
adapter
->
num
,
fe
->
frontend
.
i2c
->
id
,
fe
->
info
->
name
);
dvb_register_device
(
i2c
->
adapter
,
&
fe
->
dvbdev
,
&
dvbdev_template
,
fe
,
DVB_DEVICE_FRONTEND
);
...
...
@@ -915,8 +933,7 @@ int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend,
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
down_interruptible
(
&
frontend_mutex
))
return
-
ERESTARTSYS
;
down
(
&
frontend_mutex
);
list_for_each_safe
(
entry
,
n
,
&
frontend_list
)
{
struct
dvb_frontend_data
*
fe
;
...
...
@@ -925,10 +942,8 @@ int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend,
if
(
fe
->
frontend
.
ioctl
==
ioctl
&&
fe
->
frontend
.
i2c
==
i2c
)
{
dvb_unregister_device
(
fe
->
dvbdev
);
list_del
(
entry
);
up
(
&
frontend_mutex
);
dvb_frontend_stop
(
fe
);
kfree
(
fe
);
return
0
;
...
...
drivers/media/dvb/dvb-core/dvb_frontend.h
View file @
28003225
...
...
@@ -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... */
};
...
...
drivers/media/dvb/dvb-core/dvb_i2c.c
View file @
28003225
...
...
@@ -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,15 +92,17 @@ 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
);
}
}
}
...
...
@@ -100,9 +110,9 @@ void unregister_i2c_client_from_bus (struct dvb_i2c_device *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
;
de
tach_device
(
i2c
,
client
);
de
v
=
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)
}
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
,
struct
i2c_msg
msgs
[],
int
num
),
void
*
data
,
struct
dvb_adapter
*
adapter
,
int
id
)
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
;
...
...
drivers/media/dvb/dvb-core/dvb_i2c.h
View file @
28003225
...
...
@@ -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
),
void
*
data
,
struct
dvb_adapter
*
adapter
,
int
id
);
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
);
...
...
drivers/media/dvb/dvb-core/dvb_ksyms.c
View file @
28003225
...
...
@@ -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
);
drivers/media/dvb/dvb-core/dvb_net.c
View file @
28003225
...
...
@@ -3,29 +3,52 @@
*
* Copyright (C) 2001 Convergence integrated media GmbH
* Ralph Metzler <ralph@convergence.de>
* Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU
Lesser
General Public License
* as published by the Free Software Foundation; either version 2
.1
* 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
Lesser
General Public License
* 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.
*
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*/
#include <linux/dvb/net.h>
#include <asm/uaccess.h>
#include "demux.h"
#include <linux/dvb/net.h>
#include "dvb_demux.h"
#include "dvb_net.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#include "compat.h"
#endif
#define DVB_NET_MULTICAST_MAX 10
struct
dvb_net_priv
{
struct
net_device_stats
stats
;
char
name
[
6
];
u16
pid
;
struct
dmx_demux_s
*
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
];
int
mode
;
};
/*
* Determine the packet's protocol ID. The rule here is that we
* assume 802.3 if the type field is short enough to be a length.
...
...
@@ -73,7 +96,7 @@ unsigned short my_eth_type_trans(struct sk_buff *skb, struct net_device *dev)
}
static
void
dvb_net_sec
(
struct
net_device
*
dev
,
u8
*
pkt
,
int
pkt_len
)
dvb_net_sec
(
struct
net_device
*
dev
,
const
u8
*
pkt
,
int
pkt_len
)
{
u8
*
eth
;
struct
sk_buff
*
skb
;
...
...
@@ -86,7 +109,7 @@ dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
if
(
skb
==
NULL
)
{
printk
(
KERN_NOTICE
"%s: Memory squeeze, dropping packet.
\n
"
,
dev
->
name
);
((
dvb_net_priv_t
*
)
dev
->
priv
)
->
stats
.
rx_dropped
++
;
((
struct
dvb_net_priv
*
)
dev
->
priv
)
->
stats
.
rx_dropped
++
;
return
;
}
eth
=
(
u8
*
)
skb_put
(
skb
,
pkt_len
+
2
);
...
...
@@ -104,15 +127,14 @@ dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
skb
->
protocol
=
my_eth_type_trans
(
skb
,
dev
);
skb
->
dev
=
dev
;
((
dvb_net_priv_t
*
)
dev
->
priv
)
->
stats
.
rx_packets
++
;
((
dvb_net_priv_t
*
)
dev
->
priv
)
->
stats
.
rx_bytes
+=
skb
->
len
;
//sti();
((
struct
dvb_net_priv
*
)
dev
->
priv
)
->
stats
.
rx_packets
++
;
((
struct
dvb_net_priv
*
)
dev
->
priv
)
->
stats
.
rx_bytes
+=
skb
->
len
;
netif_rx
(
skb
);
}
static
int
dvb_net_callback
(
u8
*
buffer1
,
size_t
buffer1_len
,
u8
*
buffer2
,
size_t
buffer2_len
,
dvb_net_callback
(
const
u8
*
buffer1
,
size_t
buffer1_len
,
const
u8
*
buffer2
,
size_t
buffer2_len
,
dmx_section_filter_t
*
filter
,
dmx_success_t
success
)
{
...
...
@@ -130,18 +152,21 @@ dvb_net_tx(struct sk_buff *skb, struct net_device *dev)
return
0
;
}
#define MASK 0x00;
static
u8
mask_normal
[
6
]
=
{
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
};
static
u8
mask_allmulti
[
6
]
=
{
0xff
,
0xff
,
0xff
,
0x00
,
0x00
,
0x00
};
static
u8
mac_allmulti
[
6
]
=
{
0x01
,
0x00
,
0x5e
,
0x00
,
0x00
,
0x00
};
static
u8
mask_promisc
[
6
]
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
static
int
dvb_net_filter_set
(
struct
net_device
*
dev
,
dmx_section_filter_t
**
secfilter
,
u
nsigned
char
*
mac
)
u
8
*
mac
,
u8
*
mac_mask
)
{
dvb_net_priv_t
*
priv
=
(
dvb_net_priv_t
*
)
dev
->
priv
;
struct
dvb_net_priv
*
priv
=
(
struct
dvb_net_priv
*
)
dev
->
priv
;
int
ret
;
*
secfilter
=
0
;
ret
=
priv
->
secfeed
->
allocate_filter
(
priv
->
secfeed
,
secfilter
);
ret
=
priv
->
secfeed
->
allocate_filter
(
priv
->
secfeed
,
secfilter
);
if
(
ret
<
0
)
{
printk
(
"%s: could not get filter
\n
"
,
dev
->
name
);
return
ret
;
...
...
@@ -149,25 +174,26 @@ dvb_net_filter_set(struct net_device *dev,
(
*
secfilter
)
->
priv
=
(
void
*
)
dev
;
memset
((
*
secfilter
)
->
filter_value
,
0
,
DMX_MAX_FILTER_SIZE
);
memset
((
*
secfilter
)
->
filter_mask
,
0
,
DMX_MAX_FILTER_SIZE
);
memset
((
*
secfilter
)
->
filter_value
,
0x00
,
DMX_MAX_FILTER_SIZE
);
memset
((
*
secfilter
)
->
filter_mask
,
0x00
,
DMX_MAX_FILTER_SIZE
);
memset
((
*
secfilter
)
->
filter_mode
,
0xff
,
DMX_MAX_FILTER_SIZE
);
(
*
secfilter
)
->
filter_value
[
0
]
=
0x3e
;
(
*
secfilter
)
->
filter_mask
[
0
]
=
MASK
;
(
*
secfilter
)
->
filter_mask
[
0
]
=
0xff
;
(
*
secfilter
)
->
filter_value
[
3
]
=
mac
[
5
];
(
*
secfilter
)
->
filter_mask
[
3
]
=
MASK
;
(
*
secfilter
)
->
filter_mask
[
3
]
=
mac_mask
[
5
]
;
(
*
secfilter
)
->
filter_value
[
4
]
=
mac
[
4
];
(
*
secfilter
)
->
filter_mask
[
4
]
=
MASK
;
(
*
secfilter
)
->
filter_mask
[
4
]
=
mac_mask
[
4
]
;
(
*
secfilter
)
->
filter_value
[
8
]
=
mac
[
3
];
(
*
secfilter
)
->
filter_mask
[
8
]
=
MASK
;
(
*
secfilter
)
->
filter_mask
[
8
]
=
mac_mask
[
3
]
;
(
*
secfilter
)
->
filter_value
[
9
]
=
mac
[
2
];
(
*
secfilter
)
->
filter_mask
[
9
]
=
MASK
;
(
*
secfilter
)
->
filter_mask
[
9
]
=
mac_mask
[
2
]
;
(
*
secfilter
)
->
filter_value
[
10
]
=
mac
[
1
];
(
*
secfilter
)
->
filter_mask
[
10
]
=
MASK
;
(
*
secfilter
)
->
filter_mask
[
10
]
=
mac_mask
[
1
]
;
(
*
secfilter
)
->
filter_value
[
11
]
=
mac
[
0
];
(
*
secfilter
)
->
filter_mask
[
11
]
=
MASK
;
(
*
secfilter
)
->
filter_mask
[
11
]
=
mac_mask
[
0
]
;
printk
(
"%s: filter mac=%02x %02x %02x %02x %02x %02x
\n
"
,
dev
->
name
,
mac
[
0
],
mac
[
1
],
mac
[
2
],
mac
[
3
],
mac
[
4
],
mac
[
5
]);
...
...
@@ -178,9 +204,9 @@ static int
dvb_net_feed_start
(
struct
net_device
*
dev
)
{
int
ret
,
i
;
dvb_net_priv_t
*
priv
=
(
dvb_net_priv_t
*
)
dev
->
priv
;
dmx_demux_t
*
demux
=
priv
->
demux
;
unsigned
char
*
mac
=
(
unsigned
char
*
)
dev
->
dev_addr
;
struct
dvb_net_priv
*
priv
=
(
struct
dvb_net_priv
*
)
dev
->
priv
;
dmx_demux_t
*
demux
=
priv
->
demux
;
unsigned
char
*
mac
=
(
unsigned
char
*
)
dev
->
dev_addr
;
priv
->
secfeed
=
0
;
priv
->
secfilter
=
0
;
...
...
@@ -200,28 +226,41 @@ dvb_net_feed_start(struct net_device *dev)
priv
->
secfeed
=
0
;
return
ret
;
}
MOD_INC_USE_COUNT
;
/* fixme: is this correct? */
try_module_get
(
THIS_MODULE
);
dvb_net_filter_set
(
dev
,
&
priv
->
secfilter
,
mac
);
for
(
i
=
0
;
i
<
priv
->
multi_num
;
i
++
)
dvb_net_filter_set
(
dev
,
&
priv
->
secfilter
,
priv
->
multi_macs
[
i
]);
if
(
priv
->
mode
<
3
)
dvb_net_filter_set
(
dev
,
&
priv
->
secfilter
,
mac
,
mask_normal
);
switch
(
priv
->
mode
)
{
case
1
:
for
(
i
=
0
;
i
<
priv
->
multi_num
;
i
++
)
dvb_net_filter_set
(
dev
,
&
priv
->
multi_secfilter
[
i
],
priv
->
multi_macs
[
i
],
mask_normal
);
break
;
case
2
:
priv
->
multi_num
=
1
;
dvb_net_filter_set
(
dev
,
&
priv
->
multi_secfilter
[
0
],
mac_allmulti
,
mask_allmulti
);
break
;
case
3
:
priv
->
multi_num
=
0
;
dvb_net_filter_set
(
dev
,
&
priv
->
secfilter
,
mac
,
mask_promisc
);
break
;
}
priv
->
secfeed
->
start_filtering
(
priv
->
secfeed
);
printk
(
"%s: feed_started
\n
"
,
dev
->
name
);
return
0
;
}
static
void
dvb_net_feed_stop
(
struct
net_device
*
dev
)
{
dvb_net_priv_t
*
priv
=
(
dvb_net_priv_t
*
)
dev
->
priv
;
struct
dvb_net_priv
*
priv
=
(
struct
dvb_net_priv
*
)
dev
->
priv
;
int
i
;
if
(
priv
->
secfeed
)
{
if
(
priv
->
secfeed
->
is_filtering
)
priv
->
secfeed
->
stop_filtering
(
priv
->
secfeed
);
printk
(
"%s: feed_stopped
\n
"
,
dev
->
name
);
if
(
priv
->
secfilter
)
priv
->
secfeed
->
release_filter
(
priv
->
secfeed
,
...
...
@@ -238,62 +277,70 @@ dvb_net_feed_stop(struct net_device *dev)
priv
->
demux
->
release_section_feed
(
priv
->
demux
,
priv
->
secfeed
);
priv
->
secfeed
=
0
;
MOD_DEC_USE_COUNT
;
/* fixme: is this correct? */
module_put
(
THIS_MODULE
);
}
else
printk
(
"%s: no feed to stop
\n
"
,
dev
->
name
);
}
static
int
dvb_
set
_mc_filter
(
struct
net_device
*
dev
,
struct
dev_mc_list
*
mc
)
dvb_
add
_mc_filter
(
struct
net_device
*
dev
,
struct
dev_mc_list
*
mc
)
{
dvb_net_priv_t
*
priv
=
(
dvb_net_priv_t
*
)
dev
->
priv
;
struct
dvb_net_priv
*
priv
=
(
struct
dvb_net_priv
*
)
dev
->
priv
;
int
ret
;
if
(
priv
->
multi_num
==
DVB_NET_MULTICAST_MAX
)
if
(
priv
->
multi_num
>=
DVB_NET_MULTICAST_MAX
)
return
-
ENOMEM
;
printk
(
"%s: set_mc_filter %d: %02x %02x %02x %02x %02x %02x
\n
"
,
dev
->
name
,
priv
->
multi_num
,
mc
->
dmi_addr
[
0
],
mc
->
dmi_addr
[
1
],
mc
->
dmi_addr
[
2
],
mc
->
dmi_addr
[
3
],
mc
->
dmi_addr
[
4
],
mc
->
dmi_addr
[
5
]);
ret
=
memcmp
(
priv
->
multi_macs
[
priv
->
multi_num
],
mc
->
dmi_addr
,
6
);
memcpy
(
priv
->
multi_macs
[
priv
->
multi_num
],
mc
->
dmi_addr
,
6
);
priv
->
multi_num
++
;
return
0
;
return
ret
;
}
static
void
dvb_net_set_multi
(
struct
net_device
*
dev
)
{
dvb_net_priv_t
*
priv
=
(
dvb_net_priv_t
*
)
dev
->
priv
;
printk
(
"%s: set_multi()
\n
"
,
dev
->
name
);
dvb_net_feed_stop
(
dev
);
if
(
dev
->
flags
&
IFF_PROMISC
)
{
/* Enable promiscuous mode */
printk
(
"%s: promiscuous mode
\n
"
,
dev
->
name
);
}
else
if
((
dev
->
flags
&
IFF_ALLMULTI
))
{
/* Disable promiscuous mode, use normal mode. */
printk
(
"%s: normal mode
\n
"
,
dev
->
name
);
}
else
if
(
dev
->
mc_count
)
{
int
mci
;
struct
dev_mc_list
*
mc
;
printk
(
"%s: set_mc_list, %d entries
\n
"
,
dev
->
name
,
dev
->
mc_count
);
priv
->
multi_num
=
0
;
for
(
mci
=
0
,
mc
=
dev
->
mc_list
;
mci
<
dev
->
mc_count
;
mc
=
mc
->
next
,
mci
++
)
{
dvb_set_mc_filter
(
dev
,
mc
);
}
struct
dvb_net_priv
*
priv
=
(
struct
dvb_net_priv
*
)
dev
->
priv
;
struct
dev_mc_list
*
mc
;
int
mci
;
int
update
=
0
;
if
(
dev
->
flags
&
IFF_PROMISC
)
{
// printk("%s: promiscuous mode\n", dev->name);
if
(
priv
->
mode
!=
3
)
update
=
1
;
priv
->
mode
=
3
;
}
else
if
(
dev
->
flags
&
IFF_ALLMULTI
)
{
// printk("%s: allmulti mode\n", dev->name);
if
(
priv
->
mode
!=
2
)
update
=
1
;
priv
->
mode
=
2
;
}
else
if
(
dev
->
mc_count
>
0
)
{
// printk("%s: set_mc_list, %d entries\n",
// dev->name, dev->mc_count);
if
(
priv
->
mode
!=
1
)
update
=
1
;
priv
->
mode
=
1
;
priv
->
multi_num
=
0
;
for
(
mci
=
0
,
mc
=
dev
->
mc_list
;
mci
<
dev
->
mc_count
;
mc
=
mc
->
next
,
mci
++
)
if
(
dvb_add_mc_filter
(
dev
,
mc
)
!=
0
)
update
=
1
;
}
else
{
if
(
priv
->
mode
!=
0
)
update
=
1
;
priv
->
mode
=
0
;
}
if
(
netif_running
(
dev
)
!=
0
&&
update
>
0
)
{
dvb_net_feed_stop
(
dev
);
dvb_net_feed_start
(
dev
);
}
dvb_net_feed_start
(
dev
);
}
static
int
...
...
@@ -308,13 +355,15 @@ static int
dvb_net_set_mac
(
struct
net_device
*
dev
,
void
*
p
)
{
struct
sockaddr
*
addr
=
p
;
int
update
;
update
=
memcmp
(
dev
->
dev_addr
,
addr
->
sa_data
,
dev
->
addr_len
);
memcpy
(
dev
->
dev_addr
,
addr
->
sa_data
,
dev
->
addr_len
);
if
(
netif_running
(
dev
))
{
dvb_net_feed_stop
(
dev
);
if
(
netif_running
(
dev
)
!=
0
&&
update
>
0
)
{
dvb_net_feed_stop
(
dev
);
dvb_net_feed_start
(
dev
);
}
return
0
;
return
0
;
}
...
...
@@ -335,15 +384,13 @@ dvb_net_stop(struct net_device *dev)
static
struct
net_device_stats
*
dvb_net_get_stats
(
struct
net_device
*
dev
)
{
return
&
((
dvb_net_priv_t
*
)
dev
->
priv
)
->
stats
;
return
&
((
struct
dvb_net_priv
*
)
dev
->
priv
)
->
stats
;
}
static
int
dvb_net_init_dev
(
struct
net_device
*
dev
)
{
printk
(
"dvb_net: dvb_net_init_dev()
\n
"
);
ether_setup
(
dev
);
dev
->
open
=
dvb_net_open
;
...
...
@@ -354,6 +401,7 @@ dvb_net_init_dev(struct net_device *dev)
dev
->
set_config
=
dvb_net_set_config
;
dev
->
set_mac_address
=
dvb_net_set_mac
;
dev
->
mtu
=
4096
;
dev
->
mc_count
=
0
;
dev
->
flags
|=
IFF_NOARP
;
dev
->
hard_header_cache
=
NULL
;
...
...
@@ -364,7 +412,7 @@ dvb_net_init_dev(struct net_device *dev)
}
static
int
get_if
(
dvb_net_
t
*
dvbnet
)
get_if
(
struct
dvb_ne
t
*
dvbnet
)
{
int
i
;
...
...
@@ -379,10 +427,11 @@ get_if(dvb_net_t *dvbnet)
int
dvb_net_add_if
(
dvb_net_
t
*
dvbnet
,
u16
pid
)
dvb_net_add_if
(
struct
dvb_ne
t
*
dvbnet
,
u16
pid
)
{
struct
net_device
*
net
;
dmx_demux_t
*
demux
;
struct
dvb_net_priv
*
priv
;
int
result
;
int
if_num
;
...
...
@@ -402,25 +451,29 @@ dvb_net_add_if(dvb_net_t *dvbnet, u16 pid)
net
->
name
[
5
]
=
if_num
+
0x30
;
net
->
next
=
NULL
;
net
->
init
=
dvb_net_init_dev
;
net
->
priv
=
kmalloc
(
sizeof
(
dvb_net_priv_t
),
GFP_KERNEL
);
net
->
priv
=
kmalloc
(
sizeof
(
struct
dvb_net_priv
),
GFP_KERNEL
);
if
(
net
->
priv
==
NULL
)
return
-
ENOMEM
;
memset
(
net
->
priv
,
0
,
sizeof
(
dvb_net_priv_t
));
((
dvb_net_priv_t
*
)
net
->
priv
)
->
demux
=
demux
;
((
dvb_net_priv_t
*
)
net
->
priv
)
->
pid
=
pid
;
priv
=
net
->
priv
;
memset
(
priv
,
0
,
sizeof
(
struct
dvb_net_priv
));
priv
->
demux
=
demux
;
priv
->
pid
=
pid
;
priv
->
mode
=
0
;
net
->
base_addr
=
pid
;
net
->
base_addr
=
pid
;
if
((
result
=
register_netdev
(
net
))
<
0
)
{
return
result
;
}
MOD_INC_USE_COUNT
;
/* fixme: is this correct? */
try_module_get
(
THIS_MODULE
);
return
if_num
;
}
int
dvb_net_remove_if
(
dvb_net_
t
*
dvbnet
,
int
num
)
dvb_net_remove_if
(
struct
dvb_ne
t
*
dvbnet
,
int
num
)
{
if
(
!
dvbnet
->
state
[
num
])
return
-
EINVAL
;
...
...
@@ -428,15 +481,17 @@ dvb_net_remove_if(dvb_net_t *dvbnet, int num)
kfree
(
dvbnet
->
device
[
num
].
priv
);
unregister_netdev
(
&
dvbnet
->
device
[
num
]);
dvbnet
->
state
[
num
]
=
0
;
MOD_DEC_USE_COUNT
;
/* fixme: is this correct? */
module_put
(
THIS_MODULE
);
return
0
;
}
int
dvb_net_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
int
dvb_net_
do_
ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
void
*
parg
)
{
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
dvb_net_t
*
dvbnet
=
(
dvb_net_
t
*
)
dvbdev
->
priv
;
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
struct
dvb_net
*
dvbnet
=
(
struct
dvb_ne
t
*
)
dvbdev
->
priv
;
if
(((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDONLY
))
return
-
EPERM
;
...
...
@@ -453,6 +508,21 @@ int dvb_net_ioctl(struct inode *inode, struct file *file,
dvbnetif
->
if_num
=
result
;
break
;
}
case
NET_GET_IF
:
{
struct
net_device
*
netdev
;
struct
dvb_net_priv
*
priv_data
;
struct
dvb_net_if
*
dvbnetif
=
(
struct
dvb_net_if
*
)
parg
;
if
(
dvbnetif
->
if_num
>=
dvbnet
->
dev_num
||
!
dvbnet
->
state
[
dvbnetif
->
if_num
])
return
-
EFAULT
;
netdev
=
(
struct
net_device
*
)
&
dvbnet
->
device
[
dvbnetif
->
if_num
];
priv_data
=
(
struct
dvb_net_priv
*
)
netdev
->
priv
;
dvbnetif
->
pid
=
priv_data
->
pid
;
break
;
}
case
NET_REMOVE_IF
:
return
dvb_net_remove_if
(
dvbnet
,
(
int
)
parg
);
default:
...
...
@@ -461,23 +531,32 @@ int dvb_net_ioctl(struct inode *inode, struct file *file,
return
0
;
}
static
int
dvb_net_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
return
dvb_usercopy
(
inode
,
file
,
cmd
,
arg
,
dvb_net_do_ioctl
);
}
static
struct
file_operations
dvb_net_fops
=
{
.
owner
=
THIS_MODULE
,
.
ioctl
=
dvb_generic_ioctl
,
.
open
=
dvb_generic_open
,
.
release
=
dvb_generic_release
,
.
owner
=
THIS_MODULE
,
.
read
=
0
,
.
write
=
0
,
.
ioctl
=
dvb_net_ioctl
,
.
open
=
dvb_generic_open
,
.
release
=
dvb_generic_release
,
.
poll
=
0
,
};
static
struct
dvb_device
dvbdev_net
=
{
.
priv
=
0
,
.
users
=
1
,
.
writers
=
1
,
.
fops
=
&
dvb_net_fops
,
.
kernel_ioctl
=
dvb_net_ioctl
,
.
priv
=
0
,
.
users
=
1
,
.
writers
=
1
,
.
fops
=
&
dvb_net_fops
,
};
void
dvb_net_release
(
dvb_net_
t
*
dvbnet
)
dvb_net_release
(
struct
dvb_ne
t
*
dvbnet
)
{
int
i
;
...
...
@@ -490,15 +569,19 @@ dvb_net_release(dvb_net_t *dvbnet)
}
int
dvb_net_init
(
struct
dvb_adapter
*
adap
,
dvb_net_t
*
dvbnet
,
dmx_demux_t
*
demu
x
)
dvb_net_init
(
struct
dvb_adapter
*
adap
,
struct
dvb_net
*
dvbnet
,
dmx_demux_t
*
dm
x
)
{
int
i
;
dvbnet
->
demux
=
demux
;
dvbnet
->
dev_num
=
DVB_NET_DEVICES_MAX
;
dvbnet
->
demux
=
dmx
;
dvbnet
->
dev_num
=
DVB_NET_DEVICES_MAX
;
for
(
i
=
0
;
i
<
dvbnet
->
dev_num
;
i
++
)
dvbnet
->
state
[
i
]
=
0
;
dvb_register_device
(
adap
,
&
dvbnet
->
dvbdev
,
&
dvbdev_net
,
dvbnet
,
DVB_DEVICE_NET
);
dvbnet
->
state
[
i
]
=
0
;
dvb_register_device
(
adap
,
&
dvbnet
->
dvbdev
,
&
dvbdev_net
,
dvbnet
,
DVB_DEVICE_NET
);
return
0
;
}
drivers/media/dvb/dvb-core/dvb_net.h
View file @
28003225
...
...
@@ -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
{
struct
dvb_device
*
dvbdev
;
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_ne
t
*
);
int
dvb_net_init
(
struct
dvb_adapter
*
,
struct
dvb_ne
t
*
,
dmx_demux_t
*
);
#endif
drivers/media/dvb/dvb-core/dvb_ringbuffer.c
0 → 100644
View file @
28003225
/*
*
* 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
);
drivers/media/dvb/dvb-core/dvb_ringbuffer.h
0 → 100644
View file @
28003225
/*
*
* 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_ */
drivers/media/dvb/dvb-core/dvbdev.c
View file @
28003225
...
...
@@ -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
,
c
onst
c
har
*
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
;
}
...
...
drivers/media/dvb/dvb-core/dvbdev.h
View file @
28003225
...
...
@@ -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
;
};
...
...
@@ -63,14 +64,14 @@ struct dvb_device {
int
writers
;
/* don't really need those !? -- FIXME: use video_usercopy */
int
(
*
kernel_ioctl
)(
struct
inode
*
inode
,
struct
file
*
file
,
int
(
*
kernel_ioctl
)(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
void
*
arg
);
void
*
priv
;
};
extern
int
dvb_register_adapter
(
struct
dvb_adapter
**
padap
,
char
*
name
);
extern
int
dvb_register_adapter
(
struct
dvb_adapter
**
padap
,
c
onst
c
har
*
name
);
extern
int
dvb_unregister_adapter
(
struct
dvb_adapter
*
adap
);
extern
int
dvb_register_device
(
struct
dvb_adapter
*
adap
,
...
...
@@ -84,7 +85,10 @@ extern void dvb_unregister_device (struct dvb_device *dvbdev);
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
);
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_ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment