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
Kirill Smelkov
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 @@
...
@@ -3,6 +3,6 @@
#
#
dvb-core-objs
=
dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o
\
dvb-core-objs
=
dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o
\
dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o
dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o
dvb_ringbuffer.o
obj-$(CONFIG_DVB_CORE)
+=
dvb-core.o
obj-$(CONFIG_DVB_CORE)
+=
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 {
...
@@ -144,6 +144,14 @@ struct dmx_section_feed_s {
int
is_filtering
;
/* Set to non-zero when filtering in progress */
int
is_filtering
;
/* Set to non-zero when filtering in progress */
struct
dmx_demux_s
*
parent
;
/* Back-pointer */
struct
dmx_demux_s
*
parent
;
/* Back-pointer */
void
*
priv
;
/* Pointer to private data of the API client */
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
,
int
(
*
set
)
(
struct
dmx_section_feed_s
*
feed
,
__u16
pid
,
__u16
pid
,
size_t
circular_buffer_size
,
size_t
circular_buffer_size
,
...
@@ -162,16 +170,16 @@ typedef struct dmx_section_feed_s dmx_section_feed_t;
...
@@ -162,16 +170,16 @@ typedef struct dmx_section_feed_s dmx_section_feed_t;
/* Callback functions */
/* Callback functions */
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
typedef
int
(
*
dmx_ts_cb
)
(
__
u8
*
buffer1
,
typedef
int
(
*
dmx_ts_cb
)
(
const
u8
*
buffer1
,
size_t
buffer1_length
,
size_t
buffer1_length
,
__
u8
*
buffer2
,
const
u8
*
buffer2
,
size_t
buffer2_length
,
size_t
buffer2_length
,
dmx_ts_feed_t
*
source
,
dmx_ts_feed_t
*
source
,
dmx_success_t
success
);
dmx_success_t
success
);
typedef
int
(
*
dmx_section_cb
)
(
__
u8
*
buffer1
,
typedef
int
(
*
dmx_section_cb
)
(
const
u8
*
buffer1
,
size_t
buffer1_len
,
size_t
buffer1_len
,
__
u8
*
buffer2
,
const
u8
*
buffer2
,
size_t
buffer2_len
,
size_t
buffer2_len
,
dmx_section_filter_t
*
source
,
dmx_section_filter_t
*
source
,
dmx_success_t
success
);
dmx_success_t
success
);
...
@@ -278,6 +286,9 @@ struct dmx_demux_s {
...
@@ -278,6 +286,9 @@ struct dmx_demux_s {
int
(
*
disconnect_frontend
)
(
struct
dmx_demux_s
*
demux
);
int
(
*
disconnect_frontend
)
(
struct
dmx_demux_s
*
demux
);
int
(
*
get_pes_pids
)
(
struct
dmx_demux_s
*
demux
,
__u16
*
pids
);
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
;
typedef
struct
dmx_demux_s
dmx_demux_t
;
...
...
drivers/media/dvb/dvb-core/dmxdev.c
View file @
28003225
...
@@ -2,8 +2,8 @@
...
@@ -2,8 +2,8 @@
* dmxdev.c - DVB demultiplexer device
* dmxdev.c - DVB demultiplexer device
*
*
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
*
& Marcus Metzler <marcus@convergence.de>
*
& Marcus Metzler <marcus@convergence.de>
for convergence integrated media GmbH
for convergence integrated media GmbH
*
*
* This program is free software; you can redistribute it and/or
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* modify it under the terms of the GNU Lesser General Public License
...
@@ -24,11 +24,13 @@
...
@@ -24,11 +24,13 @@
#include <linux/vmalloc.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/poll.h>
#include <linux/videodev.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include "dmxdev.h"
#include "dmxdev.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#include "compat.h"
#endif
//MODULE_DESCRIPTION("");
//MODULE_DESCRIPTION("");
//MODULE_AUTHOR("Ralph Metzler, Marcus Metzler");
//MODULE_AUTHOR("Ralph Metzler, Marcus Metzler");
...
@@ -43,133 +45,133 @@ static int debug = 0;
...
@@ -43,133 +45,133 @@ static int debug = 0;
inline
dmxdev_filter_t
*
inline
dmxdev_filter_t
*
dvb_dmxdev_file_to_filter
(
struct
file
*
file
)
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
*
inline
dmxdev_dvr_t
*
dvb_dmxdev_file_to_dvr
(
dmxdev_t
*
dmxdev
,
struct
file
*
file
)
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
static
inline
void
dvb_dmxdev_buffer_init
(
dmxdev_buffer_t
*
buffer
)
dvb_dmxdev_buffer_init
(
dmxdev_buffer_t
*
buffer
)
{
{
buffer
->
data
=
0
;
buffer
->
data
=
0
;
buffer
->
size
=
8192
;
buffer
->
size
=
8192
;
buffer
->
pread
=
0
;
buffer
->
pread
=
0
;
buffer
->
pwrite
=
0
;
buffer
->
pwrite
=
0
;
buffer
->
error
=
0
;
buffer
->
error
=
0
;
init_waitqueue_head
(
&
buffer
->
queue
);
init_waitqueue_head
(
&
buffer
->
queue
);
}
}
static
inline
int
static
inline
dvb_dmxdev_buffer_write
(
dmxdev_buffer_t
*
buf
,
uint8_t
*
src
,
int
len
)
int
dvb_dmxdev_buffer_write
(
dmxdev_buffer_t
*
buf
,
const
u8
*
src
,
int
len
)
{
{
int
split
;
int
split
;
int
free
;
int
free
;
int
todo
;
int
todo
;
if
(
!
len
)
if
(
!
len
)
return
0
;
return
0
;
if
(
!
buf
->
data
)
if
(
!
buf
->
data
)
return
0
;
return
0
;
free
=
buf
->
pread
-
buf
->
pwrite
;
free
=
buf
->
pread
-
buf
->
pwrite
;
split
=
0
;
split
=
0
;
if
(
free
<=
0
)
{
if
(
free
<=
0
)
{
free
+=
buf
->
size
;
free
+=
buf
->
size
;
split
=
buf
->
size
-
buf
->
pwrite
;
split
=
buf
->
size
-
buf
->
pwrite
;
}
}
if
(
len
>=
free
)
{
if
(
len
>=
free
)
{
dprintk
(
"dmxdev: buffer overflow
\n
"
);
dprintk
(
"dmxdev: buffer overflow
\n
"
);
return
-
1
;
return
-
1
;
}
}
if
(
split
>=
len
)
if
(
split
>=
len
)
split
=
0
;
split
=
0
;
todo
=
len
;
todo
=
len
;
if
(
split
)
{
if
(
split
)
{
memcpy
(
buf
->
data
+
buf
->
pwrite
,
src
,
split
);
memcpy
(
buf
->
data
+
buf
->
pwrite
,
src
,
split
);
todo
-=
split
;
todo
-=
split
;
buf
->
pwrite
=
0
;
buf
->
pwrite
=
0
;
}
}
memcpy
(
buf
->
data
+
buf
->
pwrite
,
src
+
split
,
todo
);
memcpy
(
buf
->
data
+
buf
->
pwrite
,
src
+
split
,
todo
);
buf
->
pwrite
=
(
buf
->
pwrite
+
todo
)
%
buf
->
size
;
buf
->
pwrite
=
(
buf
->
pwrite
+
todo
)
%
buf
->
size
;
return
len
;
return
len
;
}
}
static
ssize_t
static
ssize_t
dvb_dmxdev_buffer_read
(
dmxdev_buffer_t
*
src
,
int
non_blocking
,
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
;
unsigned
long
todo
=
count
;
int
split
,
avail
,
error
;
int
split
,
avail
,
error
;
if
(
!
src
->
data
)
if
(
!
src
->
data
)
return
0
;
return
0
;
if
((
error
=
src
->
error
))
{
if
((
error
=
src
->
error
))
{
src
->
pwrite
=
src
->
pread
;
src
->
pwrite
=
src
->
pread
;
src
->
error
=
0
;
src
->
error
=
0
;
return
error
;
return
error
;
}
}
if
(
non_blocking
&&
(
src
->
pwrite
==
src
->
pread
))
if
(
non_blocking
&&
(
src
->
pwrite
==
src
->
pread
))
return
-
EWOULDBLOCK
;
return
-
EWOULDBLOCK
;
while
(
todo
>
0
)
{
while
(
todo
>
0
)
{
if
(
non_blocking
&&
(
src
->
pwrite
==
src
->
pread
))
if
(
non_blocking
&&
(
src
->
pwrite
==
src
->
pread
))
return
(
count
-
todo
)
?
(
count
-
todo
)
:
-
EWOULDBLOCK
;
return
(
count
-
todo
)
?
(
count
-
todo
)
:
-
EWOULDBLOCK
;
if
(
wait_event_interruptible
(
src
->
queue
,
if
(
wait_event_interruptible
(
src
->
queue
,
(
src
->
pread
!=
src
->
pwrite
)
||
(
src
->
pread
!=
src
->
pwrite
)
||
(
src
->
error
))
<
0
)
(
src
->
error
))
<
0
)
return
count
-
todo
;
return
count
-
todo
;
if
((
error
=
src
->
error
))
{
if
((
error
=
src
->
error
))
{
src
->
pwrite
=
src
->
pread
;
src
->
pwrite
=
src
->
pread
;
src
->
error
=
0
;
src
->
error
=
0
;
return
error
;
return
error
;
}
}
split
=
src
->
size
;
split
=
src
->
size
;
avail
=
src
->
pwrite
-
src
->
pread
;
avail
=
src
->
pwrite
-
src
->
pread
;
if
(
avail
<
0
)
{
if
(
avail
<
0
)
{
avail
+=
src
->
size
;
avail
+=
src
->
size
;
split
=
src
->
size
-
src
->
pread
;
split
=
src
->
size
-
src
->
pread
;
}
}
if
(
avail
>
todo
)
if
(
avail
>
todo
)
avail
=
todo
;
avail
=
todo
;
if
(
split
<
avail
)
{
if
(
split
<
avail
)
{
if
(
copy_to_user
(
buf
,
src
->
data
+
src
->
pread
,
split
))
if
(
copy_to_user
(
buf
,
src
->
data
+
src
->
pread
,
split
))
return
-
EFAULT
;
return
-
EFAULT
;
buf
+=
split
;
buf
+=
split
;
src
->
pread
=
0
;
src
->
pread
=
0
;
todo
-=
split
;
todo
-=
split
;
avail
-=
split
;
avail
-=
split
;
}
}
if
(
avail
)
{
if
(
avail
)
{
if
(
copy_to_user
(
buf
,
src
->
data
+
src
->
pread
,
avail
))
if
(
copy_to_user
(
buf
,
src
->
data
+
src
->
pread
,
avail
))
return
-
EFAULT
;
return
-
EFAULT
;
src
->
pread
=
(
src
->
pread
+
avail
)
%
src
->
size
;
src
->
pread
=
(
src
->
pread
+
avail
)
%
src
->
size
;
todo
-=
avail
;
todo
-=
avail
;
buf
+=
avail
;
buf
+=
avail
;
}
}
}
}
return
count
;
return
count
;
}
}
static
dmx_frontend_t
*
static
dmx_frontend_t
*
get_fe
(
dmx_demux_t
*
demux
,
int
type
)
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
)
if
(
!
head
)
return
0
;
return
0
;
list_for_each
(
pos
,
head
)
list_for_each
(
pos
,
head
)
if
(
DMX_FE_ENTRY
(
pos
)
->
source
==
type
)
if
(
DMX_FE_ENTRY
(
pos
)
->
source
==
type
)
return
DMX_FE_ENTRY
(
pos
);
return
DMX_FE_ENTRY
(
pos
);
return
0
;
return
0
;
}
}
...
@@ -177,8 +179,8 @@ get_fe(dmx_demux_t *demux, int type)
...
@@ -177,8 +179,8 @@ get_fe(dmx_demux_t *demux, int type)
static
inline
void
static
inline
void
dvb_dmxdev_dvr_state_set
(
dmxdev_dvr_t
*
dmxdevdvr
,
int
state
)
dvb_dmxdev_dvr_state_set
(
dmxdev_dvr_t
*
dmxdevdvr
,
int
state
)
{
{
spin_lock_irq
(
&
dmxdevdvr
->
dev
->
lock
);
spin_lock_irq
(
&
dmxdevdvr
->
dev
->
lock
);
dmxdevdvr
->
state
=
state
;
dmxdevdvr
->
state
=
state
;
spin_unlock_irq
(
&
dmxdevdvr
->
dev
->
lock
);
spin_unlock_irq
(
&
dmxdevdvr
->
dev
->
lock
);
}
}
...
@@ -186,17 +188,17 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
...
@@ -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
;
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
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
;
return
-
ERESTARTSYS
;
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDWR
)
{
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDWR
)
{
if
(
!
(
dmxdev
->
capabilities
&
DMXDEV_CAP_DUPLEX
))
{
if
(
!
(
dmxdev
->
capabilities
&
DMXDEV_CAP_DUPLEX
))
{
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
-
EOPNOTSUPP
;
return
-
EOPNOTSUPP
;
}
}
}
}
...
@@ -206,12 +208,12 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
...
@@ -206,12 +208,12 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
dmxdev
->
dvr_buffer
.
data
=
vmalloc
(
DVR_BUFFER_SIZE
);
dmxdev
->
dvr_buffer
.
data
=
vmalloc
(
DVR_BUFFER_SIZE
);
if
(
!
dmxdev
->
dvr_buffer
.
data
)
{
if
(
!
dmxdev
->
dvr_buffer
.
data
)
{
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
}
}
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_WRONLY
)
{
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
)
{
if
(
!
dmxdev
->
demux
->
write
)
{
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
...
@@ -222,13 +224,13 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
...
@@ -222,13 +224,13 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
if
(
!
front
)
{
if
(
!
front
)
{
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
dmxdev
->
demux
->
disconnect_frontend
(
dmxdev
->
demux
);
dmxdev
->
demux
->
disconnect_frontend
(
dmxdev
->
demux
);
dmxdev
->
demux
->
connect_frontend
(
dmxdev
->
demux
,
front
);
dmxdev
->
demux
->
connect_frontend
(
dmxdev
->
demux
,
front
);
}
}
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
0
;
return
0
;
}
}
static
int
dvb_dvr_release
(
struct
inode
*
inode
,
struct
file
*
file
)
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)
...
@@ -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
;
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_WRONLY
)
{
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
->
demux
->
connect_frontend
(
dmxdev
->
demux
,
dmxdev
->
dvr_orig_fe
);
dmxdev
->
dvr_orig_fe
);
}
}
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDONLY
)
{
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDONLY
)
{
if
(
dmxdev
->
dvr_buffer
.
data
)
{
if
(
dmxdev
->
dvr_buffer
.
data
)
{
void
*
mem
=
dmxdev
->
dvr_buffer
.
data
;
void
*
mem
=
dmxdev
->
dvr_buffer
.
data
;
mb
();
mb
();
spin_lock_irq
(
&
dmxdev
->
lock
);
spin_lock_irq
(
&
dmxdev
->
lock
);
dmxdev
->
dvr_buffer
.
data
=
0
;
dmxdev
->
dvr_buffer
.
data
=
0
;
spin_unlock_irq
(
&
dmxdev
->
lock
);
spin_unlock_irq
(
&
dmxdev
->
lock
);
vfree
(
mem
);
vfree
(
mem
);
}
}
}
}
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
0
;
return
0
;
}
}
...
@@ -265,14 +267,14 @@ dvb_dvr_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
...
@@ -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
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
int
ret
;
int
ret
;
if
(
!
dmxdev
->
demux
->
write
)
if
(
!
dmxdev
->
demux
->
write
)
return
-
EOPNOTSUPP
;
return
-
EOPNOTSUPP
;
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_WRONLY
)
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_WRONLY
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
ret
=
dmxdev
->
demux
->
write
(
dmxdev
->
demux
,
buf
,
count
);
ret
=
dmxdev
->
demux
->
write
(
dmxdev
->
demux
,
buf
,
count
);
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
ret
;
return
ret
;
}
}
...
@@ -283,19 +285,19 @@ dvb_dvr_read(struct file *file, char *buf, size_t count, loff_t *ppos)
...
@@ -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
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
int
ret
;
int
ret
;
//down(&dmxdev->mutex);
//down(&dmxdev->mutex);
ret
=
dvb_dmxdev_buffer_read
(
&
dmxdev
->
dvr_buffer
,
ret
=
dvb_dmxdev_buffer_read
(
&
dmxdev
->
dvr_buffer
,
file
->
f_flags
&
O_NONBLOCK
,
file
->
f_flags
&
O_NONBLOCK
,
buf
,
count
,
ppos
);
buf
,
count
,
ppos
);
//up(&dmxdev->mutex);
//up(&dmxdev->mutex);
return
ret
;
return
ret
;
}
}
static
inline
void
static
inline
void
dvb_dmxdev_filter_state_set
(
dmxdev_filter_t
*
dmxdevfilter
,
int
state
)
dvb_dmxdev_filter_state_set
(
dmxdev_filter_t
*
dmxdevfilter
,
int
state
)
{
{
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
dmxdevfilter
->
state
=
state
;
dmxdevfilter
->
state
=
state
;
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
}
}
...
@@ -306,25 +308,25 @@ dvb_dmxdev_set_buffer_size(dmxdev_filter_t *dmxdevfilter, unsigned long size)
...
@@ -306,25 +308,25 @@ dvb_dmxdev_set_buffer_size(dmxdev_filter_t *dmxdevfilter, unsigned long size)
void
*
mem
;
void
*
mem
;
if
(
buf
->
size
==
size
)
if
(
buf
->
size
==
size
)
return
0
;
return
0
;
if
(
dmxdevfilter
->
state
>=
DMXDEV_STATE_GO
)
if
(
dmxdevfilter
->
state
>=
DMXDEV_STATE_GO
)
return
-
EBUSY
;
return
-
EBUSY
;
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
mem
=
buf
->
data
;
mem
=
buf
->
data
;
buf
->
data
=
0
;
buf
->
data
=
0
;
buf
->
size
=
size
;
buf
->
size
=
size
;
buf
->
pwrite
=
buf
->
pread
=
0
;
buf
->
pwrite
=
buf
->
pread
=
0
;
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
if
(
mem
)
if
(
mem
)
vfree
(
mem
);
vfree
(
mem
);
if
(
buf
->
size
)
{
if
(
buf
->
size
)
{
mem
=
vmalloc
(
dmxdevfilter
->
buffer
.
size
);
mem
=
vmalloc
(
dmxdevfilter
->
buffer
.
size
);
if
(
!
mem
)
if
(
!
mem
)
return
-
ENOMEM
;
return
-
ENOMEM
;
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
buf
->
data
=
mem
;
buf
->
data
=
mem
;
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
}
}
return
0
;
return
0
;
}
}
...
@@ -332,23 +334,23 @@ dvb_dmxdev_set_buffer_size(dmxdev_filter_t *dmxdevfilter, unsigned long size)
...
@@ -332,23 +334,23 @@ dvb_dmxdev_set_buffer_size(dmxdev_filter_t *dmxdevfilter, unsigned long size)
static
void
static
void
dvb_dmxdev_filter_timeout
(
unsigned
long
data
)
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
;
dmxdevfilter
->
buffer
.
error
=-
ETIMEDOUT
;
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
spin_lock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
dmxdevfilter
->
state
=
DMXDEV_STATE_TIMEDOUT
;
dmxdevfilter
->
state
=
DMXDEV_STATE_TIMEDOUT
;
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
spin_unlock_irq
(
&
dmxdevfilter
->
dev
->
lock
);
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
}
}
static
void
static
void
dvb_dmxdev_filter_timer
(
dmxdev_filter_t
*
dmxdevfilter
)
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
);
del_timer
(
&
dmxdevfilter
->
timer
);
if
(
para
->
timeout
)
{
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
.
data
=
(
unsigned
long
)
dmxdevfilter
;
dmxdevfilter
->
timer
.
expires
=
jiffies
+
1
+
(
HZ
/
2
+
HZ
*
para
->
timeout
)
/
1000
;
dmxdevfilter
->
timer
.
expires
=
jiffies
+
1
+
(
HZ
/
2
+
HZ
*
para
->
timeout
)
/
1000
;
add_timer
(
&
dmxdevfilter
->
timer
);
add_timer
(
&
dmxdevfilter
->
timer
);
...
@@ -356,53 +358,51 @@ dvb_dmxdev_filter_timer(dmxdev_filter_t *dmxdevfilter)
...
@@ -356,53 +358,51 @@ dvb_dmxdev_filter_timer(dmxdev_filter_t *dmxdevfilter)
}
}
static
int
static
int
dvb_dmxdev_section_callback
(
u8
*
buffer1
,
size_t
buffer1_len
,
dvb_dmxdev_section_callback
(
const
u8
*
buffer1
,
size_t
buffer1_len
,
u8
*
buffer2
,
size_t
buffer2_len
,
const
u8
*
buffer2
,
size_t
buffer2_len
,
dmx_section_filter_t
*
filter
,
dmx_section_filter_t
*
filter
,
dmx_success_t
success
)
dmx_success_t
success
)
{
{
dmxdev_filter_t
*
dmxdevfilter
=
(
dmxdev_filter_t
*
)
filter
->
priv
;
dmxdev_filter_t
*
dmxdevfilter
=
(
dmxdev_filter_t
*
)
filter
->
priv
;
int
ret
;
int
ret
;
if
(
dmxdevfilter
->
buffer
.
error
)
{
if
(
dmxdevfilter
->
buffer
.
error
)
{
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
return
0
;
return
0
;
}
}
spin_lock
(
&
dmxdevfilter
->
dev
->
lock
);
spin_lock
(
&
dmxdevfilter
->
dev
->
lock
);
if
(
dmxdevfilter
->
state
!=
DMXDEV_STATE_GO
)
{
if
(
dmxdevfilter
->
state
!=
DMXDEV_STATE_GO
)
{
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
return
0
;
return
0
;
}
}
del_timer
(
&
dmxdevfilter
->
timer
);
del_timer
(
&
dmxdevfilter
->
timer
);
dprintk
(
"dmxdev: section callback %02x %02x %02x %02x %02x %02x
\n
"
,
dprintk
(
"dmxdev: section callback %02x %02x %02x %02x %02x %02x
\n
"
,
buffer1
[
0
],
buffer1
[
1
],
buffer1
[
0
],
buffer1
[
1
],
buffer1
[
2
],
buffer1
[
3
],
buffer1
[
2
],
buffer1
[
3
],
buffer1
[
4
],
buffer1
[
5
]);
buffer1
[
4
],
buffer1
[
5
]);
ret
=
dvb_dmxdev_buffer_write
(
&
dmxdevfilter
->
buffer
,
buffer1
,
buffer1_len
);
ret
=
dvb_dmxdev_buffer_write
(
&
dmxdevfilter
->
buffer
,
buffer1
,
buffer1_len
);
if
(
ret
==
buffer1_len
)
{
if
(
ret
==
buffer1_len
)
{
ret
=
dvb_dmxdev_buffer_write
(
&
dmxdevfilter
->
buffer
,
buffer2
,
buffer2_len
);
ret
=
dvb_dmxdev_buffer_write
(
&
dmxdevfilter
->
buffer
,
buffer2
,
buffer2_len
);
}
}
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
dmxdevfilter
->
buffer
.
pwrite
=
dmxdevfilter
->
buffer
.
pread
;
dmxdevfilter
->
buffer
.
pwrite
=
dmxdevfilter
->
buffer
.
pread
;
dmxdevfilter
->
buffer
.
error
=-
EOVERFLOW
;
dmxdevfilter
->
buffer
.
error
=-
EOVERFLOW
;
}
}
if
(
dmxdevfilter
->
params
.
sec
.
flags
&
DMX_ONESHOT
)
if
(
dmxdevfilter
->
params
.
sec
.
flags
&
DMX_ONESHOT
)
dmxdevfilter
->
state
=
DMXDEV_STATE_DONE
;
dmxdevfilter
->
state
=
DMXDEV_STATE_DONE
;
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
return
0
;
return
0
;
}
}
static
int
static
int
dvb_dmxdev_ts_callback
(
u8
*
buffer1
,
size_t
buffer1_len
,
dvb_dmxdev_ts_callback
(
const
u8
*
buffer1
,
size_t
buffer1_len
,
u8
*
buffer2
,
size_t
buffer2_len
,
const
u8
*
buffer2
,
size_t
buffer2_len
,
dmx_ts_feed_t
*
feed
,
dmx_ts_feed_t
*
feed
,
dmx_success_t
success
)
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
;
dmxdev_buffer_t
*
buffer
;
int
ret
;
int
ret
;
spin_lock
(
&
dmxdevfilter
->
dev
->
lock
);
spin_lock
(
&
dmxdevfilter
->
dev
->
lock
);
if
(
dmxdevfilter
->
params
.
pes
.
output
==
DMX_OUT_DECODER
)
{
if
(
dmxdevfilter
->
params
.
pes
.
output
==
DMX_OUT_DECODER
)
{
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
...
@@ -410,20 +410,20 @@ dvb_dmxdev_ts_callback(u8 *buffer1, size_t buffer1_len,
...
@@ -410,20 +410,20 @@ dvb_dmxdev_ts_callback(u8 *buffer1, size_t buffer1_len,
}
}
if
(
dmxdevfilter
->
params
.
pes
.
output
==
DMX_OUT_TAP
)
if
(
dmxdevfilter
->
params
.
pes
.
output
==
DMX_OUT_TAP
)
buffer
=&
dmxdevfilter
->
buffer
;
buffer
=&
dmxdevfilter
->
buffer
;
else
else
buffer
=&
dmxdevfilter
->
dev
->
dvr_buffer
;
buffer
=&
dmxdevfilter
->
dev
->
dvr_buffer
;
if
(
buffer
->
error
)
{
if
(
buffer
->
error
)
{
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
wake_up
(
&
buffer
->
queue
);
wake_up
(
&
buffer
->
queue
);
return
0
;
return
0
;
}
}
ret
=
dvb_dmxdev_buffer_write
(
buffer
,
buffer1
,
buffer1_len
);
ret
=
dvb_dmxdev_buffer_write
(
buffer
,
buffer1
,
buffer1_len
);
if
(
ret
==
buffer1_len
)
if
(
ret
==
buffer1_len
)
ret
=
dvb_dmxdev_buffer_write
(
buffer
,
buffer2
,
buffer2_len
);
ret
=
dvb_dmxdev_buffer_write
(
buffer
,
buffer2
,
buffer2_len
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
buffer
->
pwrite
=
buffer
->
pread
;
buffer
->
pwrite
=
buffer
->
pread
;
buffer
->
error
=-
EOVERFLOW
;
buffer
->
error
=-
EOVERFLOW
;
}
}
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
spin_unlock
(
&
dmxdevfilter
->
dev
->
lock
);
wake_up
(
&
buffer
->
queue
);
wake_up
(
&
buffer
->
queue
);
...
@@ -440,49 +440,50 @@ dvb_dmxdev_feed_stop(dmxdev_filter_t *dmxdevfilter)
...
@@ -440,49 +440,50 @@ dvb_dmxdev_feed_stop(dmxdev_filter_t *dmxdevfilter)
switch
(
dmxdevfilter
->
type
)
{
switch
(
dmxdevfilter
->
type
)
{
case
DMXDEV_TYPE_SEC
:
case
DMXDEV_TYPE_SEC
:
del_timer
(
&
dmxdevfilter
->
timer
);
del_timer
(
&
dmxdevfilter
->
timer
);
dmxdevfilter
->
feed
.
sec
->
stop_filtering
(
dmxdevfilter
->
feed
.
sec
);
dmxdevfilter
->
feed
.
sec
->
stop_filtering
(
dmxdevfilter
->
feed
.
sec
);
break
;
break
;
case
DMXDEV_TYPE_PES
:
case
DMXDEV_TYPE_PES
:
dmxdevfilter
->
feed
.
ts
->
stop_filtering
(
dmxdevfilter
->
feed
.
ts
);
dmxdevfilter
->
feed
.
ts
->
stop_filtering
(
dmxdevfilter
->
feed
.
ts
);
break
;
break
;
default:
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
}
return
0
;
return
0
;
}
}
/* start feed associated with the specified filter */
/* start feed associated with the specified filter */
static
int
static
dvb_dmxdev_feed_start
(
dmxdev_filter_t
*
dmxdev
filter
)
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
:
case
DMXDEV_TYPE_SEC
:
dmxdevfilter
->
feed
.
sec
->
start_filtering
(
dmxdev
filter
->
feed
.
sec
);
return
filter
->
feed
.
sec
->
start_filtering
(
filter
->
feed
.
sec
);
break
;
break
;
case
DMXDEV_TYPE_PES
:
case
DMXDEV_TYPE_PES
:
dmxdevfilter
->
feed
.
ts
->
start_filtering
(
dmxdev
filter
->
feed
.
ts
);
return
filter
->
feed
.
ts
->
start_filtering
(
filter
->
feed
.
ts
);
break
;
break
;
default:
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
}
return
0
;
return
0
;
}
}
/* restart section feed if it has filters left associated with it,
/* restart section feed if it has filters left associated with it,
otherwise release the feed */
otherwise release the feed */
static
int
static
dvb_dmxdev_feed_restart
(
dmxdev_filter_t
*
dmxdev
filter
)
int
dvb_dmxdev_feed_restart
(
dmxdev_filter_t
*
filter
)
{
{
int
i
;
int
i
;
dmxdev_t
*
dmxdev
=
dmxdev
filter
->
dev
;
dmxdev_t
*
dmxdev
=
filter
->
dev
;
uint16_t
pid
=
dmxdev
filter
->
params
.
sec
.
pid
;
uint16_t
pid
=
filter
->
params
.
sec
.
pid
;
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
if
(
dmxdev
->
filter
[
i
].
state
>=
DMXDEV_STATE_GO
&&
if
(
dmxdev
->
filter
[
i
].
state
>=
DMXDEV_STATE_GO
&&
...
@@ -492,36 +493,34 @@ dvb_dmxdev_feed_restart(dmxdev_filter_t *dmxdevfilter)
...
@@ -492,36 +493,34 @@ dvb_dmxdev_feed_restart(dmxdev_filter_t *dmxdevfilter)
return
0
;
return
0
;
}
}
dmxdevfilter
->
dev
->
demux
->
filter
->
dev
->
demux
->
release_section_feed
(
dmxdev
->
demux
,
filter
->
feed
.
sec
);
release_section_feed
(
dmxdev
->
demux
,
dmxdevfilter
->
feed
.
sec
);
return
0
;
return
0
;
}
}
static
int
static
int
dvb_dmxdev_filter_stop
(
dmxdev_filter_t
*
dmxdevfilter
)
dvb_dmxdev_filter_stop
(
dmxdev_filter_t
*
dmxdevfilter
)
{
{
if
(
dmxdevfilter
->
state
<
DMXDEV_STATE_GO
)
if
(
dmxdevfilter
->
state
<
DMXDEV_STATE_GO
)
return
0
;
return
0
;
switch
(
dmxdevfilter
->
type
)
{
switch
(
dmxdevfilter
->
type
)
{
case
DMXDEV_TYPE_SEC
:
case
DMXDEV_TYPE_SEC
:
if
(
!
dmxdevfilter
->
feed
.
sec
)
if
(
!
dmxdevfilter
->
feed
.
sec
)
break
;
break
;
dvb_dmxdev_feed_stop
(
dmxdevfilter
);
dvb_dmxdev_feed_stop
(
dmxdevfilter
);
if
(
dmxdevfilter
->
filter
.
sec
)
if
(
dmxdevfilter
->
filter
.
sec
)
dmxdevfilter
->
feed
.
sec
->
dmxdevfilter
->
feed
.
sec
->
release_filter
(
dmxdevfilter
->
feed
.
sec
,
release_filter
(
dmxdevfilter
->
feed
.
sec
,
dmxdevfilter
->
filter
.
sec
);
dmxdevfilter
->
filter
.
sec
);
dvb_dmxdev_feed_restart
(
dmxdevfilter
);
dvb_dmxdev_feed_restart
(
dmxdevfilter
);
dmxdevfilter
->
feed
.
sec
=
0
;
dmxdevfilter
->
feed
.
sec
=
0
;
break
;
break
;
case
DMXDEV_TYPE_PES
:
case
DMXDEV_TYPE_PES
:
if
(
!
dmxdevfilter
->
feed
.
ts
)
if
(
!
dmxdevfilter
->
feed
.
ts
)
break
;
break
;
dvb_dmxdev_feed_stop
(
dmxdevfilter
);
dvb_dmxdev_feed_stop
(
dmxdevfilter
);
dmxdevfilter
->
dev
->
demux
->
dmxdevfilter
->
dev
->
demux
->
release_ts_feed
(
dmxdevfilter
->
dev
->
demux
,
release_ts_feed
(
dmxdevfilter
->
dev
->
demux
,
dmxdevfilter
->
feed
.
ts
);
dmxdevfilter
->
feed
.
ts
);
dmxdevfilter
->
feed
.
ts
=
0
;
dmxdevfilter
->
feed
.
ts
=
0
;
...
@@ -529,10 +528,10 @@ dvb_dmxdev_filter_stop(dmxdev_filter_t *dmxdevfilter)
...
@@ -529,10 +528,10 @@ dvb_dmxdev_filter_stop(dmxdev_filter_t *dmxdevfilter)
default:
default:
if
(
dmxdevfilter
->
state
==
DMXDEV_STATE_ALLOCATED
)
if
(
dmxdevfilter
->
state
==
DMXDEV_STATE_ALLOCATED
)
return
0
;
return
0
;
return
-
EINVAL
;
return
-
EINVAL
;
}
}
dmxdevfilter
->
buffer
.
pwrite
=
dmxdevfilter
->
buffer
.
pread
=
0
;
dmxdevfilter
->
buffer
.
pwrite
=
dmxdevfilter
->
buffer
.
pread
=
0
;
return
0
;
return
0
;
}
}
static
inline
int
static
inline
int
...
@@ -544,58 +543,58 @@ dvb_dmxdev_filter_reset(dmxdev_filter_t *dmxdevfilter)
...
@@ -544,58 +543,58 @@ dvb_dmxdev_filter_reset(dmxdev_filter_t *dmxdevfilter)
dmxdevfilter
->
type
=
DMXDEV_TYPE_NONE
;
dmxdevfilter
->
type
=
DMXDEV_TYPE_NONE
;
dmxdevfilter
->
pid
=
0xffff
;
dmxdevfilter
->
pid
=
0xffff
;
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_ALLOCATED
);
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_ALLOCATED
);
return
0
;
return
0
;
}
}
static
int
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
;
void
*
mem
;
int
ret
,
i
;
int
ret
,
i
;
if
(
dmxdevfilter
->
state
<
DMXDEV_STATE_SET
)
if
(
filter
->
state
<
DMXDEV_STATE_SET
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
dmxdevfilter
->
state
>=
DMXDEV_STATE_GO
)
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
if
(
filter
->
state
>=
DMXDEV_STATE_GO
)
dvb_dmxdev_filter_stop
(
filter
);
mem
=
dmxdevfilter
->
buffer
.
data
;
if
(
!
mem
)
{
if
(
!
(
mem
=
filter
->
buffer
.
data
)
)
{
mem
=
vmalloc
(
dmxdev
filter
->
buffer
.
size
);
mem
=
vmalloc
(
filter
->
buffer
.
size
);
spin_lock_irq
(
&
dmxdev
filter
->
dev
->
lock
);
spin_lock_irq
(
&
filter
->
dev
->
lock
);
dmxdev
filter
->
buffer
.
data
=
mem
;
filter
->
buffer
.
data
=
mem
;
spin_unlock_irq
(
&
dmxdev
filter
->
dev
->
lock
);
spin_unlock_irq
(
&
filter
->
dev
->
lock
);
if
(
!
dmxdev
filter
->
buffer
.
data
)
if
(
!
filter
->
buffer
.
data
)
return
-
ENOMEM
;
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
:
case
DMXDEV_TYPE_SEC
:
{
{
struct
dmx_sct_filter_params
*
para
=&
dmxdev
filter
->
params
.
sec
;
struct
dmx_sct_filter_params
*
para
=&
filter
->
params
.
sec
;
dmx_section_filter_t
**
secfilter
=&
dmxdev
filter
->
filter
.
sec
;
dmx_section_filter_t
**
secfilter
=&
filter
->
filter
.
sec
;
dmx_section_feed_t
**
secfeed
=&
dmxdev
filter
->
feed
.
sec
;
dmx_section_feed_t
**
secfeed
=&
filter
->
feed
.
sec
;
*
secfilter
=
0
;
*
secfilter
=
0
;
*
secfeed
=
0
;
*
secfeed
=
0
;
/* find active filter/feed with same PID */
/* find active filter/feed with same PID */
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
{
if
(
dmxdev
->
filter
[
i
].
state
>=
DMXDEV_STATE_GO
&&
if
(
dmxdev
->
filter
[
i
].
state
>=
DMXDEV_STATE_GO
&&
dmxdev
->
filter
[
i
].
pid
==
para
->
pid
)
{
dmxdev
->
filter
[
i
].
pid
==
para
->
pid
&&
if
(
dmxdev
->
filter
[
i
].
type
!=
DMXDEV_TYPE_SEC
)
dmxdev
->
filter
[
i
].
type
==
DMXDEV_TYPE_SEC
)
{
return
-
EBUSY
;
*
secfeed
=
dmxdev
->
filter
[
i
].
feed
.
sec
;
*
secfeed
=
dmxdev
->
filter
[
i
].
feed
.
sec
;
break
;
break
;
}
}
}
/* if no feed found, try to allocate new one */
/* if no feed found, try to allocate new one */
if
(
!*
secfeed
)
{
if
(
!*
secfeed
)
{
ret
=
dmxdev
->
demux
->
allocate_section_feed
(
dmxdev
->
demux
,
ret
=
dmxdev
->
demux
->
allocate_section_feed
(
dmxdev
->
demux
,
secfeed
,
secfeed
,
dvb_dmxdev_section_callback
);
dvb_dmxdev_section_callback
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
printk
(
"DVB (%s): could not alloc feed
\n
"
,
printk
(
"DVB (%s): could not alloc feed
\n
"
,
__FUNCTION__
);
__FUNCTION__
);
...
@@ -608,22 +607,23 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
...
@@ -608,22 +607,23 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
printk
(
"DVB (%s): could not set feed
\n
"
,
printk
(
"DVB (%s): could not set feed
\n
"
,
__FUNCTION__
);
__FUNCTION__
);
dvb_dmxdev_feed_restart
(
dmxdev
filter
);
dvb_dmxdev_feed_restart
(
filter
);
return
ret
;
return
ret
;
}
}
}
else
{
dvb_dmxdev_feed_stop
(
filter
);
}
}
else
dvb_dmxdev_feed_stop
(
dmxdevfilter
);
ret
=
(
*
secfeed
)
->
allocate_filter
(
*
secfeed
,
secfilter
);
ret
=
(
*
secfeed
)
->
allocate_filter
(
*
secfeed
,
secfilter
);
if
(
ret
<
0
)
{
dvb_dmxdev_feed_restart
(
dmxdevfilter
);
if
(
ret
<
0
)
{
dmxdevfilter
->
feed
.
sec
->
start_filtering
(
*
secfeed
);
dvb_dmxdev_feed_restart
(
filter
);
filter
->
feed
.
sec
->
start_filtering
(
*
secfeed
);
dprintk
(
"could not get filter
\n
"
);
dprintk
(
"could not get filter
\n
"
);
return
ret
;
return
ret
;
}
}
(
*
secfilter
)
->
priv
=
(
void
*
)
dmxdev
filter
;
(
*
secfilter
)
->
priv
=
filter
;
memcpy
(
&
((
*
secfilter
)
->
filter_value
[
3
]),
memcpy
(
&
((
*
secfilter
)
->
filter_value
[
3
]),
&
(
para
->
filter
.
filter
[
1
]),
DMX_FILTER_SIZE
-
1
);
&
(
para
->
filter
.
filter
[
1
]),
DMX_FILTER_SIZE
-
1
);
...
@@ -638,23 +638,28 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
...
@@ -638,23 +638,28 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
(
*
secfilter
)
->
filter_mask
[
1
]
=
0
;
(
*
secfilter
)
->
filter_mask
[
1
]
=
0
;
(
*
secfilter
)
->
filter_mask
[
2
]
=
0
;
(
*
secfilter
)
->
filter_mask
[
2
]
=
0
;
dmxdevfilter
->
todo
=
0
;
filter
->
todo
=
0
;
dmxdevfilter
->
feed
.
sec
->
start_filtering
(
dmxdevfilter
->
feed
.
sec
);
dvb_dmxdev_filter_timer
(
dmxdevfilter
);
ret
=
filter
->
feed
.
sec
->
start_filtering
(
filter
->
feed
.
sec
);
if
(
ret
<
0
)
return
ret
;
dvb_dmxdev_filter_timer
(
filter
);
break
;
break
;
}
}
case
DMXDEV_TYPE_PES
:
case
DMXDEV_TYPE_PES
:
{
{
struct
timespec
timeout
=
{
0
};
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
;
dmx_output_t
otype
;
int
ret
;
int
ret
;
int
ts_type
;
int
ts_type
;
dmx_ts_pes_t
ts_pes
;
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
;
otype
=
para
->
output
;
ts_pes
=
(
dmx_ts_pes_t
)
para
->
pes_type
;
ts_pes
=
(
dmx_ts_pes_t
)
para
->
pes_type
;
...
@@ -664,11 +669,11 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
...
@@ -664,11 +669,11 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
else
else
ts_type
=
0
;
ts_type
=
0
;
if
(
otype
==
DMX_OUT_TS_TAP
)
if
(
otype
==
DMX_OUT_TS_TAP
)
ts_type
|=
TS_PACKET
;
ts_type
|=
TS_PACKET
;
if
(
otype
==
DMX_OUT_TAP
)
if
(
otype
==
DMX_OUT_TAP
)
ts_type
|=
TS_PAYLOAD_ONLY
|
TS_PACKET
;
ts_type
|=
TS_PAYLOAD_ONLY
|
TS_PACKET
;
ret
=
dmxdev
->
demux
->
allocate_ts_feed
(
dmxdev
->
demux
,
ret
=
dmxdev
->
demux
->
allocate_ts_feed
(
dmxdev
->
demux
,
tsfeed
,
tsfeed
,
...
@@ -676,75 +681,97 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
...
@@ -676,75 +681,97 @@ dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
(
*
tsfeed
)
->
priv
=
(
void
*
)
dmxdevfilter
;
(
*
tsfeed
)
->
priv
=
(
void
*
)
filter
;
ret
=
(
*
tsfeed
)
->
set
(
*
tsfeed
,
para
->
pid
,
ts_type
,
ts_pes
,
188
,
32768
,
0
,
timeout
);
if
(
ret
<
0
)
{
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
);
dmxdev
->
demux
->
release_ts_feed
(
dmxdev
->
demux
,
*
tsfeed
);
return
ret
;
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
;
break
;
}
}
default:
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
)
static
int
dvb_demux_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
{
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
int
i
;
int
i
;
dmxdev_filter_t
*
dmxdevfilter
;
dmxdev_filter_t
*
dmxdevfilter
;
if
(
!
dmxdev
->
filter
)
if
(
!
dmxdev
->
filter
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
if
(
dmxdev
->
filter
[
i
].
state
==
DMXDEV_STATE_FREE
)
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
break
;
if
(
dmxdev
->
filter
[
i
].
state
==
DMXDEV_STATE_FREE
)
if
(
i
==
dmxdev
->
filternum
)
{
break
;
up
(
&
dmxdev
->
mutex
);
return
-
EMFILE
;
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
;
file
->
private_data
=
dmxdevfilter
;
dvb_dmxdev_buffer_init
(
&
dmxdevfilter
->
buffer
);
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
);
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_ALLOCATED
);
dmxdevfilter
->
feed
.
ts
=
0
;
dmxdevfilter
->
feed
.
ts
=
0
;
init_timer
(
&
dmxdevfilter
->
timer
);
init_timer
(
&
dmxdevfilter
->
timer
);
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
0
;
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
;
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
);
dvb_dmxdev_filter_reset
(
dmxdevfilter
);
if
(
dmxdevfilter
->
buffer
.
data
)
{
if
(
dmxdevfilter
->
buffer
.
data
)
{
void
*
mem
=
dmxdevfilter
->
buffer
.
data
;
void
*
mem
=
dmxdevfilter
->
buffer
.
data
;
spin_lock_irq
(
&
dmxdev
->
lock
);
spin_lock_irq
(
&
dmxdev
->
lock
);
dmxdevfilter
->
buffer
.
data
=
0
;
dmxdevfilter
->
buffer
.
data
=
0
;
spin_unlock_irq
(
&
dmxdev
->
lock
);
spin_unlock_irq
(
&
dmxdev
->
lock
);
vfree
(
mem
);
vfree
(
mem
);
}
}
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_FREE
);
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_FREE
);
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
wake_up
(
&
dmxdevfilter
->
buffer
.
queue
);
up
(
&
dmxdevfilter
->
mutex
);
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
0
;
return
0
;
}
}
static
inline
void
static
inline
void
...
@@ -759,83 +786,83 @@ invert_mode(dmx_filter_t *filter)
...
@@ -759,83 +786,83 @@ invert_mode(dmx_filter_t *filter)
static
int
static
int
dvb_dmxdev_filter_set
(
dmxdev_t
*
dmxdev
,
dvb_dmxdev_filter_set
(
dmxdev_t
*
dmxdev
,
dmxdev_filter_t
*
dmxdevfilter
,
dmxdev_filter_t
*
dmxdevfilter
,
struct
dmx_sct_filter_params
*
params
)
struct
dmx_sct_filter_params
*
params
)
{
{
dprintk
(
"function : %s
\n
"
,
__FUNCTION__
);
dprintk
(
"function : %s
\n
"
,
__FUNCTION__
);
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
dmxdevfilter
->
type
=
DMXDEV_TYPE_SEC
;
dmxdevfilter
->
type
=
DMXDEV_TYPE_SEC
;
dmxdevfilter
->
pid
=
params
->
pid
;
dmxdevfilter
->
pid
=
params
->
pid
;
memcpy
(
&
dmxdevfilter
->
params
.
sec
,
memcpy
(
&
dmxdevfilter
->
params
.
sec
,
params
,
sizeof
(
struct
dmx_sct_filter_params
));
params
,
sizeof
(
struct
dmx_sct_filter_params
));
invert_mode
(
&
dmxdevfilter
->
params
.
sec
.
filter
);
invert_mode
(
&
dmxdevfilter
->
params
.
sec
.
filter
);
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_SET
);
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_SET
);
if
(
params
->
flags
&
DMX_IMMEDIATE_START
)
if
(
params
->
flags
&
DMX_IMMEDIATE_START
)
return
dvb_dmxdev_filter_start
(
dmxdevfilter
);
return
dvb_dmxdev_filter_start
(
dmxdevfilter
);
return
0
;
return
0
;
}
}
static
int
static
int
dvb_dmxdev_pes_filter_set
(
dmxdev_t
*
dmxdev
,
dvb_dmxdev_pes_filter_set
(
dmxdev_t
*
dmxdev
,
dmxdev_filter_t
*
dmxdevfilter
,
dmxdev_filter_t
*
dmxdevfilter
,
struct
dmx_pes_filter_params
*
params
)
struct
dmx_pes_filter_params
*
params
)
{
{
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
if
(
params
->
pes_type
>
DMX_PES_OTHER
||
params
->
pes_type
<
0
)
if
(
params
->
pes_type
>
DMX_PES_OTHER
||
params
->
pes_type
<
0
)
return
-
EINVAL
;
return
-
EINVAL
;
dmxdevfilter
->
type
=
DMXDEV_TYPE_PES
;
dmxdevfilter
->
type
=
DMXDEV_TYPE_PES
;
dmxdevfilter
->
pid
=
params
->
pid
;
dmxdevfilter
->
pid
=
params
->
pid
;
memcpy
(
&
dmxdevfilter
->
params
,
params
,
sizeof
(
struct
dmx_pes_filter_params
));
memcpy
(
&
dmxdevfilter
->
params
,
params
,
sizeof
(
struct
dmx_pes_filter_params
));
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_SET
);
dvb_dmxdev_filter_state_set
(
dmxdevfilter
,
DMXDEV_STATE_SET
);
if
(
params
->
flags
&
DMX_IMMEDIATE_START
)
if
(
params
->
flags
&
DMX_IMMEDIATE_START
)
return
dvb_dmxdev_filter_start
(
dmxdevfilter
);
return
dvb_dmxdev_filter_start
(
dmxdevfilter
);
return
0
;
return
0
;
}
}
static
ssize_t
static
ssize_t
dvb_dmxdev_read_sec
(
dmxdev_filter_t
*
dfil
,
struct
file
*
file
,
dvb_dmxdev_read_sec
(
dmxdev_filter_t
*
dfil
,
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
{
int
result
,
hcount
;
int
result
,
hcount
;
int
done
=
0
;
int
done
=
0
;
if
(
dfil
->
todo
<=
0
)
{
if
(
dfil
->
todo
<=
0
)
{
hcount
=
3
+
dfil
->
todo
;
hcount
=
3
+
dfil
->
todo
;
if
(
hcount
>
count
)
if
(
hcount
>
count
)
hcount
=
count
;
hcount
=
count
;
result
=
dvb_dmxdev_buffer_read
(
&
dfil
->
buffer
,
file
->
f_flags
&
O_NONBLOCK
,
result
=
dvb_dmxdev_buffer_read
(
&
dfil
->
buffer
,
file
->
f_flags
&
O_NONBLOCK
,
buf
,
hcount
,
ppos
);
buf
,
hcount
,
ppos
);
if
(
result
<
0
)
{
if
(
result
<
0
)
{
dfil
->
todo
=
0
;
dfil
->
todo
=
0
;
return
result
;
return
result
;
}
}
if
(
copy_from_user
(
dfil
->
secheader
-
dfil
->
todo
,
buf
,
result
))
if
(
copy_from_user
(
dfil
->
secheader
-
dfil
->
todo
,
buf
,
result
))
return
-
EFAULT
;
return
-
EFAULT
;
buf
+=
result
;
buf
+=
result
;
done
=
result
;
done
=
result
;
count
-=
result
;
count
-=
result
;
dfil
->
todo
-=
result
;
dfil
->
todo
-=
result
;
if
(
dfil
->
todo
>-
3
)
if
(
dfil
->
todo
>-
3
)
return
done
;
return
done
;
dfil
->
todo
=
((
dfil
->
secheader
[
1
]
<<
8
)
|
dfil
->
secheader
[
2
])
&
0xfff
;
dfil
->
todo
=
((
dfil
->
secheader
[
1
]
<<
8
)
|
dfil
->
secheader
[
2
])
&
0xfff
;
if
(
!
count
)
if
(
!
count
)
return
done
;
return
done
;
}
}
if
(
count
>
dfil
->
todo
)
if
(
count
>
dfil
->
todo
)
count
=
dfil
->
todo
;
count
=
dfil
->
todo
;
result
=
dvb_dmxdev_buffer_read
(
&
dfil
->
buffer
,
file
->
f_flags
&
O_NONBLOCK
,
result
=
dvb_dmxdev_buffer_read
(
&
dfil
->
buffer
,
file
->
f_flags
&
O_NONBLOCK
,
buf
,
count
,
ppos
);
buf
,
count
,
ppos
);
if
(
result
<
0
)
if
(
result
<
0
)
return
result
;
return
result
;
dfil
->
todo
-=
result
;
dfil
->
todo
-=
result
;
return
(
result
+
done
);
return
(
result
+
done
);
}
}
...
@@ -844,19 +871,20 @@ dvb_dmxdev_read_sec(dmxdev_filter_t *dfil, struct file *file,
...
@@ -844,19 +871,20 @@ dvb_dmxdev_read_sec(dmxdev_filter_t *dfil, struct file *file,
ssize_t
ssize_t
dvb_demux_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
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_filter_t
*
dmxdevfilter
=
dvb_dmxdev_file_to_filter
(
file
);
//dmxdev_t *dmxdev=dmxdevfilter->dev;
int
ret
=
0
;
int
ret
=
0
;
// semaphore should not be necessary (I hope ...)
if
(
down_interruptible
(
&
dmxdevfilter
->
mutex
))
//down(&dmxdev->mutex);
return
-
ERESTARTSYS
;
if
(
dmxdevfilter
->
type
==
DMXDEV_TYPE_SEC
)
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
else
ret
=
dvb_dmxdev_buffer_read
(
&
dmxdevfilter
->
buffer
,
ret
=
dvb_dmxdev_buffer_read
(
&
dmxdevfilter
->
buffer
,
file
->
f_flags
&
O_NONBLOCK
,
file
->
f_flags
&
O_NONBLOCK
,
buf
,
count
,
ppos
);
buf
,
count
,
ppos
);
//up(&dmxdev->mutex);
up
(
&
dmxdevfilter
->
mutex
);
return
ret
;
return
ret
;
}
}
...
@@ -864,102 +892,131 @@ dvb_demux_read(struct file *file, char *buf, size_t count, loff_t *ppos)
...
@@ -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
,
static
int
dvb_demux_do_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
void
*
parg
)
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
;
dmxdev_t
*
dmxdev
=
dmxdevfilter
->
dev
;
unsigned
long
arg
=
(
unsigned
long
)
parg
;
unsigned
long
arg
=
(
unsigned
long
)
parg
;
int
ret
=
0
;
int
ret
=
0
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
DMX_START
:
case
DMX_START
:
if
(
dmxdevfilter
->
state
<
DMXDEV_STATE_SET
)
if
(
down_interruptible
(
&
dmxdevfilter
->
mutex
))
{
ret
=-
EINVAL
;
up
(
&
dmxdev
->
mutex
);
return
-
ERESTARTSYS
;
}
if
(
dmxdevfilter
->
state
<
DMXDEV_STATE_SET
)
ret
=
-
EINVAL
;
else
else
ret
=
dvb_dmxdev_filter_start
(
dmxdevfilter
);
ret
=
dvb_dmxdev_filter_start
(
dmxdevfilter
);
up
(
&
dmxdevfilter
->
mutex
);
break
;
break
;
case
DMX_STOP
:
case
DMX_STOP
:
if
(
down_interruptible
(
&
dmxdevfilter
->
mutex
))
{
up
(
&
dmxdev
->
mutex
);
return
-
ERESTARTSYS
;
}
ret
=
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
ret
=
dvb_dmxdev_filter_stop
(
dmxdevfilter
);
up
(
&
dmxdevfilter
->
mutex
);
break
;
break
;
case
DMX_SET_FILTER
:
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
);
(
struct
dmx_sct_filter_params
*
)
parg
);
up
(
&
dmxdevfilter
->
mutex
);
break
;
break
;
case
DMX_SET_PES_FILTER
:
case
DMX_SET_PES_FILTER
:
if
(
down_interruptible
(
&
dmxdevfilter
->
mutex
))
{
up
(
&
dmxdev
->
mutex
);
return
-
ERESTARTSYS
;
}
ret
=
dvb_dmxdev_pes_filter_set
(
dmxdev
,
dmxdevfilter
,
ret
=
dvb_dmxdev_pes_filter_set
(
dmxdev
,
dmxdevfilter
,
(
struct
dmx_pes_filter_params
*
)
parg
);
(
struct
dmx_pes_filter_params
*
)
parg
);
up
(
&
dmxdevfilter
->
mutex
);
break
;
break
;
case
DMX_SET_BUFFER_SIZE
:
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
;
break
;
case
DMX_GET_EVENT
:
break
;
case
DMX_GET_PES_PIDS
:
case
DMX_GET_PES_PIDS
:
if
(
!
dmxdev
->
demux
->
get_pes_pids
)
{
if
(
!
dmxdev
->
demux
->
get_pes_pids
)
{
ret
=-
EINVAL
;
ret
=-
EINVAL
;
break
;
break
;
}
}
dmxdev
->
demux
->
get_pes_pids
(
dmxdev
->
demux
,
(
uint16_t
*
)
parg
);
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:
default:
ret
=-
EINVAL
;
ret
=-
EINVAL
;
}
}
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
ret
;
return
ret
;
}
}
static
int
dvb_demux_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
static
int
dvb_demux_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
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
)
if
(
!
dmxdevfilter
)
return
-
EINVAL
;
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
;
poll_wait
(
file
,
&
dmxdevfilter
->
buffer
.
queue
,
wait
);
poll_wait
(
file
,
&
dmxdevfilter
->
buffer
.
queue
,
wait
);
if
(
dmxdevfilter
->
state
==
DMXDEV_STATE_FREE
)
if
(
dmxdevfilter
->
state
!=
DMXDEV_STATE_GO
&&
return
0
;
dmxdevfilter
->
state
!=
DMXDEV_STATE_DONE
)
return
0
;
if
(
dmxdevfilter
->
buffer
.
error
)
if
(
dmxdevfilter
->
buffer
.
error
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
|
POLLERR
);
mask
|=
(
POLLIN
|
POLLRDNORM
|
POLLPRI
|
POLLERR
);
if
(
dmxdevfilter
->
buffer
.
pread
!=
dmxdevfilter
->
buffer
.
pwrite
)
if
(
dmxdevfilter
->
buffer
.
pread
!=
dmxdevfilter
->
buffer
.
pwrite
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
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_filter_t
*
dmxdevfilter
=
dvb_dmxdev_file_to_filter
(
file
);
dmxdev_t
*
dmxdev
=
dmxdevfilter
->
dev
;
dmxdev_t
*
dmxdev
=
dmxdevfilter
->
dev
;
return
dvb_dmxdev_filter_free
(
dmxdev
,
dmxdevfilter
);
return
dvb_dmxdev_filter_free
(
dmxdev
,
dmxdevfilter
);
}
}
...
@@ -988,64 +1045,62 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
...
@@ -988,64 +1045,62 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
int
ret
=
0
;
int
ret
=
0
;
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
if
(
down_interruptible
(
&
dmxdev
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
DMX_SET_BUFFER_SIZE
:
case
DMX_SET_BUFFER_SIZE
:
// FIXME: implement
// FIXME: implement
ret
=
0
;
ret
=
0
;
break
;
break
;
default:
default:
ret
=-
EINVAL
;
ret
=-
EINVAL
;
}
}
up
(
&
dmxdev
->
mutex
);
up
(
&
dmxdev
->
mutex
);
return
ret
;
return
ret
;
}
}
static
int
dvb_dvr_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
static
int
dvb_dvr_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
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
;
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
dmxdev_t
*
dmxdev
=
(
dmxdev_t
*
)
dvbdev
->
priv
;
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
)
{
poll_wait
(
file
,
&
dmxdev
->
dvr_buffer
.
queue
,
wait
);
if
(
dmxdev
->
dvr_buffer
.
error
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
|
POLLERR
);
if
(
dmxdev
->
dvr_buffer
.
pread
!=
dmxdev
->
dvr_buffer
.
pwrite
)
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDONLY
)
{
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
poll_wait
(
file
,
&
dmxdev
->
dvr_buffer
.
queue
,
wait
);
if
(
dmxdev
->
dvr_buffer
.
error
)
if
(
dmxdev
->
dvr_buffer
.
error
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
|
POLLERR
);
mask
|=
(
POLLIN
|
POLLRDNORM
|
POLLPRI
|
POLLERR
);
if
(
dmxdev
->
dvr_buffer
.
pread
!=
dmxdev
->
dvr_buffer
.
pwrite
)
if
(
dmxdev
->
dvr_buffer
.
pread
!=
dmxdev
->
dvr_buffer
.
pwrite
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
mask
|=
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
return
0
;
}
else
}
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
,
.
owner
=
THIS_MODULE
,
.
read
=
dvb_dvr_read
,
.
read
=
dvb_dvr_read
,
.
write
=
dvb_dvr_write
,
.
write
=
dvb_dvr_write
,
.
ioctl
=
dvb_dvr_ioctl
,
.
ioctl
=
dvb_dvr_ioctl
,
.
open
=
dvb_dvr_open
,
.
open
=
dvb_dvr_open
,
.
release
=
dvb_dvr_release
,
.
release
=
dvb_dvr_release
,
.
poll
=
dvb_dvr_poll
,
.
poll
=
dvb_dvr_poll
,
};
};
static
struct
dvb_device
dvbdev_dvr
=
{
static
struct
dvb_device
dvbdev_dvr
=
{
...
@@ -1058,37 +1113,38 @@ static struct dvb_device dvbdev_dvr = {
...
@@ -1058,37 +1113,38 @@ static struct dvb_device dvbdev_dvr = {
int
int
dvb_dmxdev_init
(
dmxdev_t
*
dmxdev
,
struct
dvb_adapter
*
dvb_adapter
)
dvb_dmxdev_init
(
dmxdev_t
*
dmxdev
,
struct
dvb_adapter
*
dvb_adapter
)
{
{
int
i
;
int
i
;
if
(
dmxdev
->
demux
->
open
(
dmxdev
->
demux
)
<
0
)
if
(
dmxdev
->
demux
->
open
(
dmxdev
->
demux
)
<
0
)
return
-
EUSERS
;
return
-
EUSERS
;
dmxdev
->
filter
=
vmalloc
(
dmxdev
->
filternum
*
sizeof
(
dmxdev_filter_t
));
dmxdev
->
filter
=
vmalloc
(
dmxdev
->
filternum
*
sizeof
(
dmxdev_filter_t
));
if
(
!
dmxdev
->
filter
)
if
(
!
dmxdev
->
filter
)
return
-
ENOMEM
;
return
-
ENOMEM
;
dmxdev
->
dvr
=
vmalloc
(
dmxdev
->
filternum
*
sizeof
(
dmxdev_dvr_t
));
dmxdev
->
dvr
=
vmalloc
(
dmxdev
->
filternum
*
sizeof
(
dmxdev_dvr_t
));
if
(
!
dmxdev
->
dvr
)
{
if
(
!
dmxdev
->
dvr
)
{
vfree
(
dmxdev
->
filter
);
vfree
(
dmxdev
->
filter
);
dmxdev
->
filter
=
0
;
dmxdev
->
filter
=
0
;
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
sema_init
(
&
dmxdev
->
mutex
,
1
);
sema_init
(
&
dmxdev
->
mutex
,
1
);
spin_lock_init
(
&
dmxdev
->
lock
);
spin_lock_init
(
&
dmxdev
->
lock
);
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
{
for
(
i
=
0
;
i
<
dmxdev
->
filternum
;
i
++
)
{
dmxdev
->
filter
[
i
].
dev
=
dmxdev
;
dmxdev
->
filter
[
i
].
dev
=
dmxdev
;
dmxdev
->
filter
[
i
].
buffer
.
data
=
0
;
dmxdev
->
filter
[
i
].
buffer
.
data
=
0
;
dvb_dmxdev_filter_state_set
(
&
dmxdev
->
filter
[
i
],
DMXDEV_STATE_FREE
);
dvb_dmxdev_filter_state_set
(
&
dmxdev
->
filter
[
i
],
DMXDEV_STATE_FREE
);
dmxdev
->
dvr
[
i
].
dev
=
dmxdev
;
dmxdev
->
dvr
[
i
].
dev
=
dmxdev
;
dmxdev
->
dvr
[
i
].
buffer
.
data
=
0
;
dmxdev
->
dvr
[
i
].
buffer
.
data
=
0
;
dvb_dmxdev_filter_state_set
(
&
dmxdev
->
filter
[
i
],
DMXDEV_STATE_FREE
);
dvb_dmxdev_filter_state_set
(
&
dmxdev
->
filter
[
i
],
DMXDEV_STATE_FREE
);
dvb_dmxdev_dvr_state_set
(
&
dmxdev
->
dvr
[
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
->
dvbdev
,
&
dvbdev_demux
,
dmxdev
,
DVB_DEVICE_DEMUX
);
dvb_register_device
(
dvb_adapter
,
&
dmxdev
->
dvr_dvbdev
,
&
dvbdev_dvr
,
dmxdev
,
DVB_DEVICE_DVR
);
dvb_register_device
(
dvb_adapter
,
&
dmxdev
->
dvr_dvbdev
,
&
dvbdev_dvr
,
dmxdev
,
DVB_DEVICE_DVR
);
dvb_dmxdev_buffer_init
(
&
dmxdev
->
dvr_buffer
);
dvb_dmxdev_buffer_init
(
&
dmxdev
->
dvr_buffer
);
MOD_INC_USE_COUNT
;
/* fixme: is this correct? */
try_module_get
(
THIS_MODULE
);
return
0
;
return
0
;
}
}
...
@@ -1098,15 +1154,16 @@ dvb_dmxdev_release(dmxdev_t *dmxdev)
...
@@ -1098,15 +1154,16 @@ dvb_dmxdev_release(dmxdev_t *dmxdev)
dvb_unregister_device
(
dmxdev
->
dvbdev
);
dvb_unregister_device
(
dmxdev
->
dvbdev
);
dvb_unregister_device
(
dmxdev
->
dvr_dvbdev
);
dvb_unregister_device
(
dmxdev
->
dvr_dvbdev
);
if
(
dmxdev
->
filter
)
{
if
(
dmxdev
->
filter
)
{
vfree
(
dmxdev
->
filter
);
vfree
(
dmxdev
->
filter
);
dmxdev
->
filter
=
0
;
dmxdev
->
filter
=
0
;
}
}
if
(
dmxdev
->
dvr
)
{
if
(
dmxdev
->
dvr
)
{
vfree
(
dmxdev
->
dvr
);
vfree
(
dmxdev
->
dvr
);
dmxdev
->
dvr
=
0
;
dmxdev
->
dvr
=
0
;
}
}
dmxdev
->
demux
->
close
(
dmxdev
->
demux
);
dmxdev
->
demux
->
close
(
dmxdev
->
demux
);
MOD_DEC_USE_COUNT
;
/* 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 {
...
@@ -85,6 +85,8 @@ typedef struct dmxdev_filter_s {
struct
dmxdev_s
*
dev
;
struct
dmxdev_s
*
dev
;
dmxdev_buffer_t
buffer
;
dmxdev_buffer_t
buffer
;
struct
semaphore
mutex
;
// only for sections
// only for sections
struct
timer_list
timer
;
struct
timer_list
timer
;
int
todo
;
int
todo
;
...
...
drivers/media/dvb/dvb-core/dvb_demux.c
View file @
28003225
...
@@ -2,8 +2,8 @@
...
@@ -2,8 +2,8 @@
* dvb_demux.c - DVB kernel demux API
* dvb_demux.c - DVB kernel demux API
*
*
* Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
* Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
*
& Marcus Metzler <marcus@convergence.de>
*
& Marcus Metzler <marcus@convergence.de>
*
for convergence integrated media GmbH
*
for convergence integrated media GmbH
*
*
* This program is free software; you can redistribute it and/or
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* modify it under the terms of the GNU Lesser General Public License
...
@@ -27,27 +27,36 @@
...
@@ -27,27 +27,36 @@
#include <linux/version.h>
#include <linux/version.h>
#include <asm/uaccess.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"
#include "dvb_demux.h"
#define NOBUFS
#define NOBUFS
LIST_HEAD
(
dmx_muxs
);
LIST_HEAD
(
dmx_muxs
);
int
dmx_register_demux
(
dmx_demux_t
*
demux
)
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
))
if
(
!
(
demux
->
id
&&
demux
->
vendor
&&
demux
->
model
))
return
-
EINVAL
;
return
-
EINVAL
;
list_for_each
(
pos
,
head
)
{
list_for_each
(
pos
,
&
dmx_muxs
)
{
if
(
!
strcmp
(
DMX_DIR_ENTRY
(
pos
)
->
id
,
demux
->
id
))
if
(
!
strcmp
(
DMX_DIR_ENTRY
(
pos
)
->
id
,
demux
->
id
))
return
-
EEXIST
;
return
-
EEXIST
;
}
}
demux
->
users
=
0
;
list_add
(
&
(
demux
->
reg_list
),
head
);
demux
->
users
=
0
;
MOD_INC_USE_COUNT
;
list_add
(
&
demux
->
reg_list
,
&
dmx_muxs
);
/* fixme: is this correct? */
try_module_get
(
THIS_MODULE
);
return
0
;
return
0
;
}
}
...
@@ -55,25 +64,25 @@ int dmx_unregister_demux(dmx_demux_t* demux)
...
@@ -55,25 +64,25 @@ int dmx_unregister_demux(dmx_demux_t* demux)
{
{
struct
list_head
*
pos
,
*
n
,
*
head
=&
dmx_muxs
;
struct
list_head
*
pos
,
*
n
,
*
head
=&
dmx_muxs
;
list_for_each_safe
(
pos
,
n
,
head
)
list_for_each_safe
(
pos
,
n
,
head
)
{
{
if
(
DMX_DIR_ENTRY
(
pos
)
==
demux
)
{
if
(
DMX_DIR_ENTRY
(
pos
)
==
demux
)
if
(
demux
->
users
>
0
)
{
return
-
EINVAL
;
if
(
demux
->
users
>
0
)
list_del
(
pos
);
return
-
EINVAL
;
/* fixme: is this correct? */
list_del
(
pos
);
module_put
(
THIS_MODULE
);
MOD_DEC_USE_COUNT
;
return
0
;
return
0
;
}
}
}
}
return
-
ENODEV
;
return
-
ENODEV
;
}
}
struct
list_head
*
dmx_get_demuxes
(
void
)
struct
list_head
*
dmx_get_demuxes
(
void
)
{
{
if
(
list_empty
(
&
dmx_muxs
))
if
(
list_empty
(
&
dmx_muxs
))
return
NULL
;
return
NULL
;
return
&
dmx_muxs
;
return
&
dmx_muxs
;
}
}
...
@@ -82,628 +91,661 @@ struct list_head *dmx_get_demuxes(void)
...
@@ -82,628 +91,661 @@ struct list_head *dmx_get_demuxes(void)
* static inlined helper functions
* 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?
if
(
!
(
tsp
[
3
]
&
0x10
))
// no payload?
return
0
;
return
0
;
if
(
tsp
[
3
]
&
0x20
)
{
// adaptation field?
if
(
tsp
[
3
]
&
0x20
)
{
// adaptation field?
if
(
tsp
[
4
]
>
183
)
// corrupted data?
if
(
tsp
[
4
]
>
183
)
// corrupted data?
return
0
;
return
0
;
else
else
return
184
-
1
-
tsp
[
4
];
return
184
-
1
-
tsp
[
4
];
}
}
return
184
;
return
184
;
}
}
static
u32
void
dvb_set_crc32
(
u8
*
data
,
int
length
)
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
)
{
{
int
i
;
u32
crc
;
u32
crc
=
0xffffffff
;
crc
=
crc32_le
(
~
0
,
data
,
length
);
for
(
i
=
0
;
i
<
len
;
i
++
)
data
[
length
]
=
(
crc
>>
24
)
&
0xff
;
crc
=
(
crc
<<
8
)
^
dvb_crc_table
[((
crc
>>
24
)
^
*
data
++
)
&
0xff
];
data
[
length
+
1
]
=
(
crc
>>
16
)
&
0xff
;
return
crc
;
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
;
static
data
[
length
+
1
]
=
(
crc
>>
16
)
&
0xff
;
void
dvb_dmx_memcopy
(
struct
dvb_demux_feed
*
f
,
u8
*
d
,
const
u8
*
s
,
size_t
len
)
data
[
length
+
2
]
=
(
crc
>>
8
)
&
0xff
;
{
data
[
length
+
3
]
=
(
crc
)
&
0xff
;
memcpy
(
d
,
s
,
len
)
;
}
}
/******************************************************************************
/******************************************************************************
* Software filter functions
* Software filter functions
******************************************************************************/
******************************************************************************/
static
inline
int
static
inline
dvb_dmx_swfilter_payload
(
struct
dvb_demux_feed
*
dvbdmx
feed
,
const
u8
*
buf
)
int
dvb_dmx_swfilter_payload
(
struct
dvb_demux_feed
*
feed
,
const
u8
*
buf
)
{
{
int
p
,
count
;
int
count
=
payload
(
buf
);
int
p
;
//int ccok;
//int ccok;
//u8 cc;
//u8 cc;
if
(
!
(
count
=
payload
(
buf
)))
if
(
count
==
0
)
return
-
1
;
return
-
1
;
p
=
188
-
count
;
/*
p
=
188
-
count
;
/*
cc=buf[3]&0x0f;
cc=buf[3]&0x0f;
ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0;
ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0;
dvbdmxfeed->cc=cc;
dvbdmxfeed->cc=cc;
if (!ccok)
if (!ccok)
printk("missed packet!\n");
printk("missed packet!\n");
*/
*/
if
(
buf
[
1
]
&
0x40
)
// PUSI ?
dvbdmxfeed
->
peslen
=
0xfffa
;
if
(
buf
[
1
]
&
0x40
)
// PUSI ?
dvbdmxfeed
->
peslen
+=
count
;
feed
->
peslen
=
0xfffa
;
return
dvbdmxfeed
->
cb
.
ts
((
u8
*
)
&
buf
[
p
],
count
,
0
,
0
,
feed
->
peslen
+=
count
;
&
dvbdmxfeed
->
feed
.
ts
,
DMX_OK
);
return
feed
->
cb
.
ts
(
&
buf
[
p
],
count
,
0
,
0
,
&
feed
->
feed
.
ts
,
DMX_OK
);
}
}
static
int
static
dvb_dmx_swfilter_sectionfilter
(
struct
dvb_demux_feed
*
dvbdmx
feed
,
int
dvb_dmx_swfilter_sectionfilter
(
struct
dvb_demux_feed
*
feed
,
struct
dvb_demux_filter
*
f
)
struct
dvb_demux_filter
*
f
)
{
{
dmx_section_filter_t
*
filter
=&
f
->
filter
;
u8
neq
=
0
;
int
i
;
int
i
;
u8
xor
,
neq
=
0
;
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
++
)
{
if
(
f
->
maskandmode
[
i
]
&
xor
)
xor
=
filter
->
filter_value
[
i
]
^
dvbdmxfeed
->
secbuf
[
i
];
if
(
f
->
maskandmode
[
i
]
&
xor
)
return
0
;
return
0
;
neq
|=
f
->
maskandnotmode
[
i
]
&
xor
;
neq
|=
f
->
maskandnotmode
[
i
]
&
xor
;
}
}
if
(
f
->
doneq
&&
!
neq
)
if
(
f
->
doneq
&
!
neq
)
return
0
;
return
0
;
return
dvbdmxfeed
->
cb
.
sec
(
dvbdmxfeed
->
secbuf
,
dvbdmxfeed
->
seclen
,
return
feed
->
cb
.
sec
(
feed
->
feed
.
sec
.
secbuf
,
feed
->
feed
.
sec
.
seclen
,
0
,
0
,
filter
,
DMX_OK
);
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
*
demux
=
feed
->
demux
;
struct
dvb_demux_filter
*
f
;
struct
dvb_demux_filter
*
f
=
feed
->
filter
;
dmx_section_feed_t
*
sec
=
&
feed
->
feed
.
sec
;
if
(
dvbdmxfeed
->
secbufp
!=
dvbdmxfeed
->
seclen
)
u8
*
buf
=
sec
->
secbuf
;
return
-
1
;
if
(
!
dvbdmxfeed
->
feed
.
sec
.
is_filtering
)
if
(
sec
->
secbufp
!=
sec
->
seclen
)
return
0
;
return
-
1
;
if
(
!
(
f
=
dvbdmxfeed
->
filter
))
return
0
;
if
(
!
sec
->
is_filtering
)
do
return
0
;
if
(
dvb_dmx_swfilter_sectionfilter
(
dvbdmxfeed
,
f
)
<
0
)
return
-
1
;
if
(
!
f
)
while
((
f
=
f
->
next
)
&&
dvbdmxfeed
->
feed
.
sec
.
is_filtering
);
return
0
;
dvbdmxfeed
->
secbufp
=
dvbdmxfeed
->
seclen
=
0
;
if
(
sec
->
check_crc
&&
demux
->
check_crc32
(
feed
,
sec
->
secbuf
,
sec
->
seclen
))
memset
(
buf
,
0
,
DVB_DEMUX_MASK_MAX
);
return
-
1
;
return
0
;
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
;
struct
dvb_demux
*
demux
=
feed
->
demux
;
int
ccok
,
rest
;
dmx_section_feed_t
*
sec
=
&
feed
->
feed
.
sec
;
int
p
,
count
;
int
ccok
,
rest
;
u8
cc
;
u8
cc
;
if
(
!
(
count
=
payload
(
buf
)))
if
(
!
(
count
=
payload
(
buf
)))
return
-
1
;
return
-
1
;
p
=
188
-
count
;
cc
=
buf
[
3
]
&
0x0f
;
p
=
188
-
count
;
ccok
=
((
dvbdmxfeed
->
cc
+
1
)
&
0x0f
)
==
cc
?
1
:
0
;
dvbdmxfeed
->
cc
=
cc
;
if
(
buf
[
1
]
&
0x40
)
{
// PUSI set
cc
=
buf
[
3
]
&
0x0f
;
// offset to start of first section is in buf[p]
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
if
(
p
+
buf
[
p
]
>
187
)
// trash if it points beyond packet
return
-
1
;
return
-
1
;
if
(
buf
[
p
]
&&
ccok
)
{
// rest of previous section?
// did we have enough data in last packet to calc length?
if
(
buf
[
p
]
&&
ccok
)
{
// rest of previous section?
int
tmp
=
3
-
dvbdmxfeed
->
secbufp
;
// did we have enough data in last packet to calc length?
if
(
tmp
>
0
&&
tmp
!=
3
)
{
int
tmp
=
3
-
sec
->
secbufp
;
if
(
p
+
tmp
>=
187
)
if
(
tmp
>
0
&&
tmp
!=
3
)
{
if
(
p
+
tmp
>=
187
)
return
-
1
;
return
-
1
;
memcpy
(
dvbdmxfeed
->
secbuf
+
dvbdmxfeed
->
secbufp
,
buf
+
p
+
1
,
tmp
);
demux
->
memcopy
(
feed
,
sec
->
secbuf
+
sec
->
secbufp
,
dvbdmxfeed
->
seclen
=
section_length
(
dvbdmxfeed
->
secbuf
);
buf
+
p
+
1
,
tmp
);
if
(
dvbdmxfeed
->
seclen
>
4096
)
sec
->
seclen
=
section_length
(
sec
->
secbuf
);
if
(
sec
->
seclen
>
4096
)
return
-
1
;
return
-
1
;
}
}
rest
=
dvbdmxfeed
->
seclen
-
dvbdmxfeed
->
secbufp
;
if
(
rest
==
buf
[
p
]
&&
dvbdmxfeed
->
seclen
)
{
rest
=
sec
->
seclen
-
sec
->
secbufp
;
memcpy
(
dvbdmxfeed
->
secbuf
+
dvbdmxfeed
->
secbufp
,
buf
+
p
+
1
,
buf
[
p
]);
if
(
rest
==
buf
[
p
]
&&
sec
->
seclen
)
{
dvbdmxfeed
->
secbufp
+=
buf
[
p
];
demux
->
memcopy
(
feed
,
sec
->
secbuf
+
sec
->
secbufp
,
dvb_dmx_swfilter_section_feed
(
dvbdmxfeed
);
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
>
0
)
{
if
((
count
>
2
)
&&
// enough data to determine sec length?
p
+=
buf
[
p
]
+
1
;
// skip rest of last section
((
dvbdmxfeed
->
seclen
=
section_length
(
buf
+
p
))
<=
count
))
{
count
=
188
-
p
;
if
(
dvbdmxfeed
->
seclen
>
4096
)
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
;
return
-
1
;
memcpy
(
dvbdmxfeed
->
secbuf
,
buf
+
p
,
dvbdmxfeed
->
seclen
);
demux
->
memcopy
(
feed
,
sec
->
secbuf
,
buf
+
p
,
dvbdmxfeed
->
secbufp
=
dvbdmxfeed
->
seclen
;
sec
->
seclen
);
p
+=
dvbdmxfeed
->
seclen
;
count
=
188
-
p
;
sec
->
secbufp
=
sec
->
seclen
;
dvb_dmx_swfilter_section_feed
(
dvbdmxfeed
);
p
+=
sec
->
seclen
;
count
=
188
-
p
;
// filling bytes until packet end?
if
(
count
&&
buf
[
p
]
==
0xff
)
dvb_dmx_swfilter_section_feed
(
feed
);
count
=
0
;
}
else
{
// section continues to following TS packet
// filling bytes until packet end?
memcpy
(
dvbdmxfeed
->
secbuf
,
buf
+
p
,
count
);
if
(
count
&&
buf
[
p
]
==
0xff
)
dvbdmxfeed
->
secbufp
+=
count
;
count
=
0
;
count
=
0
;
}
}
else
{
// section continues to following TS packet
}
demux
->
memcopy
(
feed
,
sec
->
secbuf
,
buf
+
p
,
count
);
sec
->
secbufp
+=
count
;
count
=
0
;
}
}
return
0
;
return
0
;
}
}
// section continued below
// section continued below
if
(
!
ccok
)
if
(
!
ccok
)
return
-
1
;
return
-
1
;
if
(
!
dvbdmxfeed
->
secbufp
)
// any data in last ts packet?
if
(
!
sec
->
secbufp
)
// any data in last ts packet?
return
-
1
;
return
-
1
;
// did we have enough data in last packet to calc section length?
// did we have enough data in last packet to calc section length?
if
(
dvbdmxfeed
->
secbufp
<
3
)
{
if
(
sec
->
secbufp
<
3
)
{
int
tmp
=
3
-
dvbdmxfeed
->
secbufp
;
int
tmp
=
3
-
sec
->
secbufp
;
if
(
tmp
>
count
)
if
(
tmp
>
count
)
return
-
1
;
return
-
1
;
memcpy
(
dvbdmxfeed
->
secbuf
+
dvbdmxfeed
->
secbufp
,
buf
+
p
,
tmp
);
dvbdmxfeed
->
seclen
=
section_length
(
dvbdmxfeed
->
secbuf
);
sec
->
crc_val
=
~
0
;
if
(
dvbdmxfeed
->
seclen
>
4096
)
demux
->
memcopy
(
feed
,
sec
->
secbuf
+
sec
->
secbufp
,
buf
+
p
,
tmp
);
sec
->
seclen
=
section_length
(
sec
->
secbuf
);
if
(
sec
->
seclen
>
4096
)
return
-
1
;
return
-
1
;
}
}
rest
=
dvbdmxfeed
->
seclen
-
dvbdmxfeed
->
secbufp
;
if
(
rest
<
0
)
rest
=
sec
->
seclen
-
sec
->
secbufp
;
if
(
rest
<
0
)
return
-
1
;
return
-
1
;
if
(
rest
<=
count
)
{
// section completed in this TS packet
memcpy
(
dvbdmxfeed
->
secbuf
+
dvbdmxfeed
->
secbufp
,
buf
+
p
,
rest
);
if
(
rest
<=
count
)
{
// section completed in this TS packet
dvbdmxfeed
->
secbufp
+=
rest
;
demux
->
memcopy
(
feed
,
sec
->
secbuf
+
sec
->
secbufp
,
buf
+
p
,
rest
);
dvb_dmx_swfilter_section_feed
(
dvbdmxfeed
);
sec
->
secbufp
+=
rest
;
dvb_dmx_swfilter_section_feed
(
feed
);
}
else
{
// section continues in following ts packet
}
else
{
// section continues in following ts packet
memcpy
(
dvbdmxfeed
->
secbuf
+
dvbdmxfeed
->
secbufp
,
buf
+
p
,
count
);
demux
->
memcopy
(
feed
,
sec
->
secbuf
+
sec
->
secbufp
,
buf
+
p
,
count
);
dvbdmxfeed
->
secbufp
+=
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
)
{
switch
(
feed
->
type
)
{
case
DMX_TYPE_TS
:
case
DMX_TYPE_TS
:
if
(
!
dvbdmxfeed
->
feed
.
ts
.
is_filtering
)
if
(
!
feed
->
feed
.
ts
.
is_filtering
)
break
;
break
;
if
(
dvbdmxfeed
->
ts_type
&
TS_PACKET
)
{
if
(
feed
->
ts_type
&
TS_PACKET
)
{
if
(
dvbdmxfeed
->
ts_type
&
TS_PAYLOAD_ONLY
)
if
(
feed
->
ts_type
&
TS_PAYLOAD_ONLY
)
dvb_dmx_swfilter_payload
(
dvbdmxfeed
,
buf
);
dvb_dmx_swfilter_payload
(
feed
,
buf
);
else
else
dvbdmxfeed
->
cb
.
ts
((
u8
*
)
buf
,
188
,
0
,
0
,
feed
->
cb
.
ts
(
buf
,
188
,
0
,
0
,
&
feed
->
feed
.
ts
,
DMX_OK
);
&
dvbdmxfeed
->
feed
.
ts
,
DMX_OK
);
}
}
if
(
feed
->
ts_type
&
TS_DECODER
)
if
(
dvbdmxfeed
->
ts_type
&
TS_DECODER
)
if
(
feed
->
demux
->
write_to_decoder
)
if
(
dvbdmxfeed
->
demux
->
write_to_decoder
)
feed
->
demux
->
write_to_decoder
(
feed
,
buf
,
188
);
dvbdmxfeed
->
demux
->
break
;
write_to_decoder
(
dvbdmxfeed
,
(
u8
*
)
buf
,
188
);
break
;
case
DMX_TYPE_SEC
:
if
(
!
feed
->
feed
.
sec
.
is_filtering
)
case
DMX_TYPE_SEC
:
break
;
if
(
!
dvbdmxfeed
->
feed
.
sec
.
is_filtering
)
if
(
dvb_dmx_swfilter_section_packet
(
feed
,
buf
)
<
0
)
break
;
feed
->
feed
.
sec
.
seclen
=
feed
->
feed
.
sec
.
secbufp
=
0
;
if
(
dvb_dmx_swfilter_section_packet
(
dvbdmxfeed
,
buf
)
<
0
)
break
;
dvbdmxfeed
->
seclen
=
dvbdmxfeed
->
secbufp
=
0
;
break
;
default:
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
)]))
void
dvb_dmx_swfilter_packet
(
struct
dvb_demux
*
demux
,
const
u8
*
buf
)
return
;
{
dvb_dmx_swfilter_packet_type
(
dvbdmxfeed
,
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
(
&
demux
->
lock
);
spin_lock
(
&
dvbdmx
->
lock
);
while
(
count
--
)
{
if
((
dvbdmxfeed
=
dvbdmx
->
pid2feed
[
0x2000
]))
dvb_dmx_swfilter_packet
(
demux
,
buf
);
dvbdmxfeed
->
cb
.
ts
((
u8
*
)
buf
,
count
*
188
,
0
,
0
,
buf
+=
188
;
&
dvbdmxfeed
->
feed
.
ts
,
DMX_OK
);
while
(
count
)
{
dvb_dmx_swfilter_packet
(
dvbdmx
,
buf
);
count
--
;
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
;
int
p
=
0
,
i
,
j
;
if
((
i
=
dvbdm
x
->
tsbufp
))
{
if
((
i
=
demu
x
->
tsbufp
))
{
if
(
count
<
(
j
=
188
-
i
))
{
if
(
count
<
(
j
=
188
-
i
))
{
memcpy
(
&
dvbdm
x
->
tsbuf
[
i
],
buf
,
count
);
memcpy
(
&
demu
x
->
tsbuf
[
i
],
buf
,
count
);
dvbdmx
->
tsbufp
+=
count
;
demux
->
tsbufp
+=
count
;
return
;
return
;
}
}
memcpy
(
&
dvbdm
x
->
tsbuf
[
i
],
buf
,
j
);
memcpy
(
&
demu
x
->
tsbuf
[
i
],
buf
,
j
);
dvb_dmx_swfilter_packet
(
dvbdmx
,
dvbdm
x
->
tsbuf
);
dvb_dmx_swfilter_packet
(
demux
,
demu
x
->
tsbuf
);
dvbdmx
->
tsbufp
=
0
;
demux
->
tsbufp
=
0
;
p
+=
j
;
p
+=
j
;
}
}
while
(
p
<
count
)
{
while
(
p
<
count
)
{
if
(
buf
[
p
]
==
0x47
)
{
if
(
buf
[
p
]
==
0x47
)
{
if
(
count
-
p
>=
188
)
{
if
(
count
-
p
>=
188
)
{
dvb_dmx_swfilter_packet
(
dvbdm
x
,
buf
+
p
);
dvb_dmx_swfilter_packet
(
demu
x
,
buf
+
p
);
p
+=
188
;
p
+=
188
;
}
else
{
}
else
{
i
=
count
-
p
;
i
=
count
-
p
;
memcpy
(
dvbdm
x
->
tsbuf
,
buf
+
p
,
i
);
memcpy
(
demu
x
->
tsbuf
,
buf
+
p
,
i
);
dvbdm
x
->
tsbufp
=
i
;
demu
x
->
tsbufp
=
i
;
return
;
return
;
}
}
}
else
}
else
p
++
;
p
++
;
}
}
}
}
/******************************************************************************
static
******************************************************************************
struct
dvb_demux_filter
*
dvb_dmx_filter_alloc
(
struct
dvb_demux
*
demux
)
* DVB DEMUX API LEVEL FUNCTIONS
******************************************************************************
******************************************************************************/
static
struct
dvb_demux_filter
*
dvb_dmx_filter_alloc
(
struct
dvb_demux
*
dvbdmx
)
{
{
int
i
;
int
i
;
for
(
i
=
0
;
i
<
dvbdmx
->
filternum
;
i
++
)
for
(
i
=
0
;
i
<
demux
->
filternum
;
i
++
)
if
(
dvbdmx
->
filter
[
i
].
state
==
DMX_STATE_FREE
)
if
(
demux
->
filter
[
i
].
state
==
DMX_STATE_FREE
)
break
;
break
;
if
(
i
==
dvbdmx
->
filternum
)
return
0
;
if
(
i
==
demux
->
filternum
)
dvbdmx
->
filter
[
i
].
state
=
DMX_STATE_ALLOCATED
;
return
NULL
;
return
&
dvbdmx
->
filter
[
i
];
demux
->
filter
[
i
].
state
=
DMX_STATE_ALLOCATED
;
return
&
demux
->
filter
[
i
];
}
}
static
struct
dvb_demux_feed
*
static
dvb_dmx_feed_alloc
(
struct
dvb_demux
*
dvbdm
x
)
struct
dvb_demux_feed
*
dvb_dmx_feed_alloc
(
struct
dvb_demux
*
demu
x
)
{
{
int
i
;
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
];
}
for
(
i
=
0
;
i
<
demux
->
feednum
;
i
++
)
if
(
demux
->
feed
[
i
].
state
==
DMX_STATE_FREE
)
break
;
/******************************************************************************
if
(
i
==
demux
->
feednum
)
* dmx_ts_feed API calls
return
NULL
;
******************************************************************************/
static
int
demux
->
feed
[
i
].
state
=
DMX_STATE_ALLOCATED
;
dmx_pid_set
(
u16
pid
,
struct
dvb_demux_feed
*
dvbdmxfeed
)
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
*
demux
=
feed
->
demux
;
struct
dvb_demux_feed
**
pid2feed
=
dvbdmx
->
pid2feed
;
struct
list_head
*
pos
,
*
n
,
*
head
=&
demux
->
feed_list
;
if
(
pid
>
DMX_MAX_PID
)
if
(
pid
>
DMX_MAX_PID
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
dvbdmxfeed
->
pid
!=
0xffff
)
{
if
(
dvbdmxfeed
->
pid
<=
DMX_MAX_PID
)
if
(
pid
==
feed
->
pid
)
pid2feed
[
dvbdmxfeed
->
pid
]
=
0
;
return
0
;
dvbdmxfeed
->
pid
=
0xffff
;
}
if
(
feed
->
pid
<=
DMX_MAX_PID
)
if
(
pid2feed
[
pid
])
{
list_for_each_safe
(
pos
,
n
,
head
)
return
-
EBUSY
;
if
(
DMX_FEED_ENTRY
(
pos
)
->
pid
==
feed
->
pid
)
{
}
list_del
(
pos
);
pid2feed
[
pid
]
=
dvbdmxfeed
;
break
;
dvbdmxfeed
->
pid
=
pid
;
}
list_add
(
&
feed
->
list_head
,
head
);
feed
->
pid
=
pid
;
return
0
;
return
0
;
}
}
static
int
static
dmx_ts_feed_set
(
struct
dmx_ts_feed_s
*
feed
,
int
dmx_ts_feed_set
(
struct
dmx_ts_feed_s
*
ts_feed
,
u16
pid
,
int
ts_type
,
u16
pid
,
dmx_ts_pes_t
pes_type
,
size_t
callback_length
,
int
ts_type
,
size_t
circular_buffer_size
,
int
descramble
,
dmx_ts_pes_t
pes_type
,
struct
timespec
timeout
)
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_feed
*
feed
=
(
struct
dvb_demux_feed
*
)
ts_
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmx
feed
->
demux
;
struct
dvb_demux
*
demux
=
feed
->
demux
;
int
ret
;
int
ret
;
if
(
down_interruptible
(
&
dvbdm
x
->
mutex
))
if
(
down_interruptible
(
&
demu
x
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
if
(
ts_type
&
TS_DECODER
)
{
if
(
ts_type
&
TS_DECODER
)
{
if
(
pes_type
>=
DMX_TS_PES_OTHER
)
{
if
(
pes_type
>=
DMX_TS_PES_OTHER
)
{
up
(
&
d
vbdm
x
->
mutex
);
up
(
&
d
emu
x
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
dvbdmx
->
pesfilter
[
pes_type
]
&&
(
dvbdmx
->
pesfilter
[
pes_type
]
!=
dvbdmxfeed
))
{
if
(
demux
->
pesfilter
[
pes_type
]
&&
up
(
&
dvbdmx
->
mutex
);
demux
->
pesfilter
[
pes_type
]
!=
feed
)
{
return
-
EINVAL
;
up
(
&
demux
->
mutex
);
return
-
EINVAL
;
}
}
if
((
pes_type
!=
DMX_TS_PES_PCR0
)
&&
if
((
pes_type
!=
DMX_TS_PES_PCR0
)
&&
(
pes_type
!=
DMX_TS_PES_PCR1
)
&&
(
pes_type
!=
DMX_TS_PES_PCR1
)
&&
(
pes_type
!=
DMX_TS_PES_PCR2
)
&&
(
pes_type
!=
DMX_TS_PES_PCR2
)
&&
(
pes_type
!=
DMX_TS_PES_PCR3
))
{
(
pes_type
!=
DMX_TS_PES_PCR3
))
{
if
((
ret
=
dmx_pid_set
(
pid
,
dvbdmx
feed
))
<
0
)
{
if
((
ret
=
dmx_pid_set
(
pid
,
feed
))
<
0
)
{
up
(
&
d
vbdm
x
->
mutex
);
up
(
&
d
emu
x
->
mutex
);
return
ret
;
return
ret
;
}
else
}
dvbdmxfeed
->
pid
=
pid
;
}
else
}
feed
->
pid
=
pid
;
dvbdmx
->
pesfilter
[
pes_type
]
=
dvbdmxfeed
;
dvbdmx
->
pids
[
pes_type
]
=
dvbdmxfeed
->
pid
;
demux
->
pesfilter
[
pes_type
]
=
feed
;
}
else
demux
->
pids
[
pes_type
]
=
feed
->
pid
;
if
((
ret
=
dmx_pid_set
(
pid
,
dvbdmxfeed
))
<
0
)
{
}
else
{
up
(
&
dvbdmx
->
mutex
);
if
((
ret
=
dmx_pid_set
(
pid
,
feed
))
<
0
)
{
up
(
&
demux
->
mutex
);
return
ret
;
return
ret
;
}
}
}
dvbdmxfeed
->
buffer_size
=
circular_buffer_size
;
feed
->
buffer_size
=
circular_buffer_size
;
dvbdmxfeed
->
descramble
=
descramble
;
feed
->
descramble
=
descramble
;
dvbdmxfeed
->
timeout
=
timeout
;
feed
->
timeout
=
timeout
;
dvbdmxfeed
->
cb_length
=
callback_length
;
feed
->
cb_length
=
callback_length
;
dvbdmxfeed
->
ts_type
=
ts_type
;
feed
->
ts_type
=
ts_type
;
dvbdmxfeed
->
pes_type
=
pes_type
;
feed
->
pes_type
=
pes_type
;
if
(
dvbdmx
feed
->
descramble
)
{
if
(
feed
->
descramble
)
{
up
(
&
d
vbdm
x
->
mutex
);
up
(
&
d
emu
x
->
mutex
);
return
-
ENOSYS
;
return
-
ENOSYS
;
}
}
if
(
dvbdmx
feed
->
buffer_size
)
{
if
(
feed
->
buffer_size
)
{
#ifdef NOBUFS
#ifdef NOBUFS
dvbdmx
feed
->
buffer
=
0
;
feed
->
buffer
=
0
;
#else
#else
dvbdmxfeed
->
buffer
=
vmalloc
(
dvbdmx
feed
->
buffer_size
);
feed
->
buffer
=
vmalloc
(
feed
->
buffer_size
);
if
(
!
dvbdmx
feed
->
buffer
)
{
if
(
!
feed
->
buffer
)
{
up
(
&
d
vbdm
x
->
mutex
);
up
(
&
d
emu
x
->
mutex
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
#endif
#endif
}
}
dvbdmxfeed
->
state
=
DMX_STATE_READY
;
up
(
&
dvbdmx
->
mutex
);
feed
->
state
=
DMX_STATE_READY
;
return
0
;
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_feed
*
feed
=
(
struct
dvb_demux_feed
*
)
ts_
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmx
feed
->
demux
;
struct
dvb_demux
*
demux
=
feed
->
demux
;
int
ret
;
int
ret
;
if
(
down_interruptible
(
&
dvbdm
x
->
mutex
))
if
(
down_interruptible
(
&
demu
x
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
if
(
dvbdmxfeed
->
state
!=
DMX_STATE_READY
||
if
(
feed
->
state
!=
DMX_STATE_READY
||
feed
->
type
!=
DMX_TYPE_TS
)
{
dvbdmxfeed
->
type
!=
DMX_TYPE_TS
)
{
up
(
&
demux
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
!
dvbdmx
->
start_feed
)
{
up
(
&
dvbdmx
->
mutex
);
if
(
!
demux
->
start_feed
)
{
return
-
1
;
up
(
&
demux
->
mutex
);
return
-
ENODEV
;
}
}
ret
=
dvbdmx
->
start_feed
(
dvbdmxfeed
);
if
(
ret
<
0
)
{
if
((
ret
=
demux
->
start_feed
(
feed
))
<
0
)
{
up
(
&
d
vbdm
x
->
mutex
);
up
(
&
d
emu
x
->
mutex
);
return
ret
;
return
ret
;
}
}
spin_lock_irq
(
&
dvbdmx
->
lock
);
feed
->
is_filtering
=
1
;
spin_lock_irq
(
&
demux
->
lock
);
dvbdmxfeed
->
state
=
DMX_STATE_GO
;
ts_feed
->
is_filtering
=
1
;
spin_unlock_irq
(
&
dvbdmx
->
lock
);
feed
->
state
=
DMX_STATE_GO
;
up
(
&
dvbdmx
->
mutex
);
spin_unlock_irq
(
&
demux
->
lock
);
up
(
&
demux
->
mutex
);
return
0
;
return
0
;
}
}
static
int
static
dmx_ts_feed_stop_filtering
(
struct
dmx_ts_feed_s
*
feed
)
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_feed
*
feed
=
(
struct
dvb_demux_feed
*
)
ts_
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmx
feed
->
demux
;
struct
dvb_demux
*
demux
=
feed
->
demux
;
int
ret
;
int
ret
;
if
(
down_interruptible
(
&
dvbdm
x
->
mutex
))
if
(
down_interruptible
(
&
demu
x
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
if
(
dvbdmx
feed
->
state
<
DMX_STATE_GO
)
{
if
(
feed
->
state
<
DMX_STATE_GO
)
{
up
(
&
d
vbdm
x
->
mutex
);
up
(
&
d
emu
x
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
!
dvbdmx
->
stop_feed
)
{
up
(
&
dvbdmx
->
mutex
);
if
(
!
demux
->
stop_feed
)
{
return
-
1
;
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
);
ret
=
demux
->
stop_feed
(
feed
);
up
(
&
dvbdmx
->
mutex
);
return
ret
;
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
,
static
dmx_ts_feed_t
**
feed
,
int
dvbdmx_allocate_ts_feed
(
dmx_demux_t
*
dmx
,
dmx_ts_feed_t
**
ts_
feed
,
dmx_ts_cb
callback
)
dmx_ts_cb
callback
)
{
{
struct
dvb_demux
*
dvbdmx
=
(
struct
dvb_demux
*
)
demu
x
;
struct
dvb_demux
*
demux
=
(
struct
dvb_demux
*
)
dm
x
;
struct
dvb_demux_feed
*
dvbdmx
feed
;
struct
dvb_demux_feed
*
feed
;
if
(
down_interruptible
(
&
dvbdm
x
->
mutex
))
if
(
down_interruptible
(
&
demu
x
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
if
(
!
(
dvbdmxfeed
=
dvb_dmx_feed_alloc
(
dvbdm
x
)))
{
if
(
!
(
feed
=
dvb_dmx_feed_alloc
(
demu
x
)))
{
up
(
&
d
vbdm
x
->
mutex
);
up
(
&
d
emu
x
->
mutex
);
return
-
EBUSY
;
return
-
EBUSY
;
}
}
dvbdmxfeed
->
type
=
DMX_TYPE_TS
;
dvbdmxfeed
->
cb
.
ts
=
callback
;
feed
->
type
=
DMX_TYPE_TS
;
dvbdmxfeed
->
demux
=
dvbdmx
;
feed
->
cb
.
ts
=
callback
;
dvbdmxfeed
->
pid
=
0xffff
;
feed
->
demux
=
demux
;
dvbdmxfeed
->
peslen
=
0xfffa
;
feed
->
pid
=
0xffff
;
dvbdmxfeed
->
buffer
=
0
;
feed
->
peslen
=
0xfffa
;
feed
->
buffer
=
0
;
(
*
feed
)
=&
dvbdmxfeed
->
feed
.
ts
;
(
*
feed
)
->
is_filtering
=
0
;
(
*
ts_feed
)
=
&
feed
->
feed
.
ts
;
(
*
feed
)
->
parent
=
demux
;
(
*
ts_feed
)
->
is_filtering
=
0
;
(
*
feed
)
->
priv
=
0
;
(
*
ts_feed
)
->
parent
=
dmx
;
(
*
feed
)
->
set
=
dmx_ts_feed_set
;
(
*
ts_feed
)
->
priv
=
0
;
(
*
feed
)
->
start_filtering
=
dmx_ts_feed_start_filtering
;
(
*
ts_feed
)
->
set
=
dmx_ts_feed_set
;
(
*
feed
)
->
stop_filtering
=
dmx_ts_feed_stop_filtering
;
(
*
ts_feed
)
->
start_filtering
=
dmx_ts_feed_start_filtering
;
(
*
ts_feed
)
->
stop_filtering
=
dmx_ts_feed_stop_filtering
;
if
(
!
(
dvbdmxfeed
->
filter
=
dvb_dmx_filter_alloc
(
dvbdmx
)))
{
dvbdmxfeed
->
state
=
DMX_STATE_FREE
;
if
(
!
(
feed
->
filter
=
dvb_dmx_filter_alloc
(
demux
)))
{
up
(
&
dvbdmx
->
mutex
);
feed
->
state
=
DMX_STATE_FREE
;
return
-
EBUSY
;
up
(
&
demux
->
mutex
);
}
return
-
EBUSY
;
}
dvbdmxfeed
->
filter
->
type
=
DMX_TYPE_TS
;
dvbdmxfeed
->
filter
->
feed
=
dvbdmxfeed
;
feed
->
filter
->
type
=
DMX_TYPE_TS
;
dvbdmxfeed
->
filter
->
state
=
DMX_STATE_READY
;
feed
->
filter
->
feed
=
feed
;
feed
->
filter
->
state
=
DMX_STATE_READY
;
up
(
&
dvbdmx
->
mutex
);
return
0
;
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
*
demux
=
(
struct
dvb_demux
*
)
dmx
;
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
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
;
return
-
ERESTARTSYS
;
if
(
dvbdmxfeed
->
state
==
DMX_STATE_FREE
)
{
if
(
feed
->
state
==
DMX_STATE_FREE
)
{
up
(
&
d
vbdm
x
->
mutex
);
up
(
&
d
emu
x
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
#ifndef NOBUFS
#ifndef NOBUFS
if
(
dvbdmx
feed
->
buffer
)
{
if
(
feed
->
buffer
)
{
vfree
(
dvbdmx
feed
->
buffer
);
vfree
(
feed
->
buffer
);
dvbdmx
feed
->
buffer
=
0
;
feed
->
buffer
=
0
;
}
}
#endif
#endif
dvbdmxfeed
->
state
=
DMX_STATE_FREE
;
dvbdmxfeed
->
filter
->
state
=
DMX_STATE_FREE
;
feed
->
state
=
DMX_STATE_FREE
;
if
(
dvbdmxfeed
->
pid
<=
DMX_MAX_PID
)
{
feed
->
filter
->
state
=
DMX_STATE_FREE
;
dvbdmxfeed
->
demux
->
pid2feed
[
dvbdmxfeed
->
pid
]
=
0
;
dvbdmxfeed
->
pid
=
0xffff
;
if
(
feed
->
pid
<=
DMX_MAX_PID
)
{
}
list_for_each_safe
(
pos
,
n
,
head
)
if
(
DMX_FEED_ENTRY
(
pos
)
->
pid
==
feed
->
pid
)
{
up
(
&
dvbdmx
->
mutex
);
list_del
(
pos
);
return
0
;
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)
...
@@ -713,92 +755,92 @@ static int dvbdmx_release_ts_feed(dmx_demux_t *demux, dmx_ts_feed_t *feed)
static
int
static
int
dmx_section_feed_allocate_filter
(
struct
dmx_section_feed_s
*
feed
,
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_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdemux
=
dvbdmxfeed
->
demux
;
struct
dvb_demux
*
dvbdemux
=
dvbdmxfeed
->
demux
;
struct
dvb_demux_filter
*
dvbdmxfilter
;
struct
dvb_demux_filter
*
dvbdmxfilter
;
if
(
down_interruptible
(
&
dvbdemux
->
mutex
))
if
(
down_interruptible
(
&
dvbdemux
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
dvbdmxfilter
=
dvb_dmx_filter_alloc
(
dvbdemux
);
dvbdmxfilter
=
dvb_dmx_filter_alloc
(
dvbdemux
);
if
(
!
dvbdmxfilter
)
{
if
(
!
dvbdmxfilter
)
{
up
(
&
dvbdemux
->
mutex
);
up
(
&
dvbdemux
->
mutex
);
return
-
ENOSPC
;
return
-
ENOSPC
;
}
}
spin_lock_irq
(
&
dvbdemux
->
lock
);
spin_lock_irq
(
&
dvbdemux
->
lock
);
*
filter
=&
dvbdmxfilter
->
filter
;
*
filter
=&
dvbdmxfilter
->
filter
;
(
*
filter
)
->
parent
=
feed
;
(
*
filter
)
->
parent
=
feed
;
(
*
filter
)
->
priv
=
0
;
(
*
filter
)
->
priv
=
0
;
dvbdmxfilter
->
feed
=
dvbdmxfeed
;
dvbdmxfilter
->
feed
=
dvbdmxfeed
;
dvbdmxfilter
->
type
=
DMX_TYPE_SEC
;
dvbdmxfilter
->
type
=
DMX_TYPE_SEC
;
dvbdmxfilter
->
state
=
DMX_STATE_READY
;
dvbdmxfilter
->
state
=
DMX_STATE_READY
;
dvbdmxfilter
->
next
=
dvbdmxfeed
->
filter
;
dvbdmxfilter
->
next
=
dvbdmxfeed
->
filter
;
dvbdmxfeed
->
filter
=
dvbdmxfilter
;
dvbdmxfeed
->
filter
=
dvbdmxfilter
;
spin_unlock_irq
(
&
dvbdemux
->
lock
);
spin_unlock_irq
(
&
dvbdemux
->
lock
);
up
(
&
dvbdemux
->
mutex
);
up
(
&
dvbdemux
->
mutex
);
return
0
;
return
0
;
}
}
static
int
static
int
dmx_section_feed_set
(
struct
dmx_section_feed_s
*
feed
,
dmx_section_feed_set
(
struct
dmx_section_feed_s
*
feed
,
u16
pid
,
size_t
circular_buffer_size
,
u16
pid
,
size_t
circular_buffer_size
,
int
descramble
,
int
check_crc
)
int
descramble
,
int
check_crc
)
{
{
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmxfeed
->
demux
;
struct
dvb_demux
*
dvbdmx
=
dvbdmxfeed
->
demux
;
struct
list_head
*
pos
,
*
n
,
*
head
=&
dvbdmx
->
feed_list
;
if
(
pid
>
0x1fff
)
if
(
pid
>
0x1fff
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
if
(
dvbdmxfeed
->
pid
!=
0xffff
)
{
if
(
dvbdmxfeed
->
pid
<=
DMX_MAX_PID
)
dvbdmx
->
pid2feed
[
dvbdmxfeed
->
pid
]
=
0
;
list_for_each_safe
(
pos
,
n
,
head
)
dvbdmxfeed
->
pid
=
0xffff
;
if
(
DMX_FEED_ENTRY
(
pos
)
->
pid
==
dvbdmxfeed
->
pid
)
{
}
list_del
(
pos
);
if
(
dvbdmx
->
pid2feed
[
pid
])
{
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
);
up
(
&
dvbdmx
->
mutex
);
return
-
E
BUSY
;
return
-
E
NOSYS
;
}
}
dvbdmx
->
pid2feed
[
pid
]
=
dvbdmxfeed
;
dvbdmxfeed
->
pid
=
pid
;
dvbdmxfeed
->
buffer_size
=
circular_buffer_size
;
dvbdmxfeed
->
feed
.
sec
.
check_crc
=
check_crc
;
dvbdmxfeed
->
descramble
=
descramble
;
if
(
dvbdmxfeed
->
descramble
)
{
up
(
&
dvbdmx
->
mutex
);
return
-
ENOSYS
;
}
dvbdmxfeed
->
check_crc
=
check_crc
;
#ifdef NOBUFS
#ifdef NOBUFS
dvbdmxfeed
->
buffer
=
0
;
dvbdmxfeed
->
buffer
=
0
;
#else
#else
dvbdmxfeed
->
buffer
=
vmalloc
(
dvbdmxfeed
->
buffer_size
);
dvbdmxfeed
->
buffer
=
vmalloc
(
dvbdmxfeed
->
buffer_size
);
if
(
!
dvbdmxfeed
->
buffer
)
{
if
(
!
dvbdmxfeed
->
buffer
)
{
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
#endif
#endif
dvbdmxfeed
->
state
=
DMX_STATE_READY
;
dvbdmxfeed
->
state
=
DMX_STATE_READY
;
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
0
;
return
0
;
}
}
static
void
prepare_secfilters
(
struct
dvb_demux_feed
*
dvbdmxfeed
)
static
void
prepare_secfilters
(
struct
dvb_demux_feed
*
dvbdmxfeed
)
{
{
int
i
;
int
i
;
dmx_section_filter_t
*
sf
;
dmx_section_filter_t
*
sf
;
struct
dvb_demux_filter
*
f
;
struct
dvb_demux_filter
*
f
;
u8
mask
,
mode
,
doneq
;
u8
mask
,
mode
,
doneq
;
if
(
!
(
f
=
dvbdmxfeed
->
filter
))
if
(
!
(
f
=
dvbdmxfeed
->
filter
))
return
;
return
;
do
{
do
{
sf
=&
f
->
filter
;
sf
=&
f
->
filter
;
doneq
=
0
;
doneq
=
0
;
for
(
i
=
0
;
i
<
DVB_DEMUX_MASK_MAX
;
i
++
)
{
for
(
i
=
0
;
i
<
DVB_DEMUX_MASK_MAX
;
i
++
)
{
...
@@ -815,159 +857,169 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
...
@@ -815,159 +857,169 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
static
int
static
int
dmx_section_feed_start_filtering
(
dmx_section_feed_t
*
feed
)
dmx_section_feed_start_filtering
(
dmx_section_feed_t
*
feed
)
{
{
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmxfeed
->
demux
;
struct
dvb_demux
*
dvbdmx
=
dvbdmxfeed
->
demux
;
int
ret
;
int
ret
;
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
if
(
feed
->
is_filtering
)
{
if
(
feed
->
is_filtering
)
{
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
-
EBUSY
;
return
-
EBUSY
;
}
}
if
(
!
dvbdmxfeed
->
filter
)
{
if
(
!
dvbdmxfeed
->
filter
)
{
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
dvbdmxfeed
->
secbufp
=
0
;
dvbdmxfeed
->
feed
.
sec
.
secbufp
=
0
;
dvbdmxfeed
->
seclen
=
0
;
dvbdmxfeed
->
feed
.
sec
.
seclen
=
0
;
if
(
!
dvbdmx
->
start_feed
)
{
if
(
!
dvbdmx
->
start_feed
)
{
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
-
1
;
return
-
ENODEV
;
}
}
prepare_secfilters
(
dvbdmxfeed
);
prepare_secfilters
(
dvbdmxfeed
);
ret
=
dvbdmx
->
start_feed
(
dvbdmxfeed
);
if
(
ret
<
0
)
{
if
(
(
ret
=
dvbdmx
->
start_feed
(
dvbdmxfeed
))
<
0
)
{
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
ret
;
return
ret
;
}
}
spin_lock_irq
(
&
dvbdmx
->
lock
);
spin_lock_irq
(
&
dvbdmx
->
lock
);
feed
->
is_filtering
=
1
;
feed
->
is_filtering
=
1
;
dvbdmxfeed
->
state
=
DMX_STATE_GO
;
dvbdmxfeed
->
state
=
DMX_STATE_GO
;
spin_unlock_irq
(
&
dvbdmx
->
lock
);
spin_unlock_irq
(
&
dvbdmx
->
lock
);
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
0
;
return
0
;
}
}
static
int
static
int
dmx_section_feed_stop_filtering
(
struct
dmx_section_feed_s
*
feed
)
dmx_section_feed_stop_filtering
(
struct
dmx_section_feed_s
*
feed
)
{
{
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmxfeed
->
demux
;
struct
dvb_demux
*
dvbdmx
=
dvbdmxfeed
->
demux
;
int
ret
;
int
ret
;
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
if
(
!
dvbdmx
->
stop_feed
)
{
if
(
!
dvbdmx
->
stop_feed
)
{
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
-
1
;
return
-
ENODEV
;
}
}
ret
=
dvbdmx
->
stop_feed
(
dvbdmxfeed
);
ret
=
dvbdmx
->
stop_feed
(
dvbdmxfeed
);
spin_lock_irq
(
&
dvbdmx
->
lock
);
spin_lock_irq
(
&
dvbdmx
->
lock
);
dvbdmxfeed
->
state
=
DMX_STATE_READY
;
dvbdmxfeed
->
state
=
DMX_STATE_READY
;
feed
->
is_filtering
=
0
;
feed
->
is_filtering
=
0
;
spin_unlock_irq
(
&
dvbdmx
->
lock
);
spin_unlock_irq
(
&
dvbdmx
->
lock
);
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
ret
;
return
ret
;
}
}
static
int
static
int
dmx_section_feed_release_filter
(
dmx_section_feed_t
*
feed
,
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_filter
*
dvbdmxfilter
=
(
struct
dvb_demux_filter
*
)
filter
,
*
f
;
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdmx
=
dvbdmxfeed
->
demux
;
struct
dvb_demux
*
dvbdmx
=
dvbdmxfeed
->
demux
;
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
if
(
dvbdmxfilter
->
feed
!=
dvbdmxfeed
)
{
if
(
dvbdmxfilter
->
feed
!=
dvbdmxfeed
)
{
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
feed
->
is_filtering
)
if
(
feed
->
is_filtering
)
feed
->
stop_filtering
(
feed
);
feed
->
stop_filtering
(
feed
);
spin_lock_irq
(
&
dvbdmx
->
lock
);
spin_lock_irq
(
&
dvbdmx
->
lock
);
f
=
dvbdmxfeed
->
filter
;
f
=
dvbdmxfeed
->
filter
;
if
(
f
==
dvbdmxfilter
)
if
(
f
==
dvbdmxfilter
)
dvbdmxfeed
->
filter
=
dvbdmxfilter
->
next
;
dvbdmxfeed
->
filter
=
dvbdmxfilter
->
next
;
else
{
else
{
while
(
f
->
next
!=
dvbdmxfilter
)
while
(
f
->
next
!=
dvbdmxfilter
)
f
=
f
->
next
;
f
=
f
->
next
;
f
->
next
=
f
->
next
->
next
;
f
->
next
=
f
->
next
->
next
;
}
}
dvbdmxfilter
->
state
=
DMX_STATE_FREE
;
dvbdmxfilter
->
state
=
DMX_STATE_FREE
;
spin_unlock_irq
(
&
dvbdmx
->
lock
);
spin_unlock_irq
(
&
dvbdmx
->
lock
);
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
0
;
return
0
;
}
}
static
int
dvbdmx_allocate_section_feed
(
dmx_demux_t
*
demux
,
static
int
dvbdmx_allocate_section_feed
(
dmx_demux_t
*
demux
,
dmx_section_feed_t
**
feed
,
dmx_section_feed_t
**
feed
,
dmx_section_cb
callback
)
dmx_section_cb
callback
)
{
{
struct
dvb_demux
*
dvbdmx
=
(
struct
dvb_demux
*
)
demux
;
struct
dvb_demux
*
dvbdmx
=
(
struct
dvb_demux
*
)
demux
;
struct
dvb_demux_feed
*
dvbdmxfeed
;
struct
dvb_demux_feed
*
dvbdmxfeed
;
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
if
(
down_interruptible
(
&
dvbdmx
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
if
(
!
(
dvbdmxfeed
=
dvb_dmx_feed_alloc
(
dvbdmx
)))
{
if
(
!
(
dvbdmxfeed
=
dvb_dmx_feed_alloc
(
dvbdmx
)))
{
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
-
EBUSY
;
return
-
EBUSY
;
}
}
dvbdmxfeed
->
type
=
DMX_TYPE_SEC
;
dvbdmxfeed
->
type
=
DMX_TYPE_SEC
;
dvbdmxfeed
->
cb
.
sec
=
callback
;
dvbdmxfeed
->
cb
.
sec
=
callback
;
dvbdmxfeed
->
demux
=
dvbdmx
;
dvbdmxfeed
->
demux
=
dvbdmx
;
dvbdmxfeed
->
pid
=
0xffff
;
dvbdmxfeed
->
pid
=
0xffff
;
dvbdmxfeed
->
secbufp
=
0
;
dvbdmxfeed
->
feed
.
sec
.
secbufp
=
0
;
dvbdmxfeed
->
filter
=
0
;
dvbdmxfeed
->
filter
=
0
;
dvbdmxfeed
->
buffer
=
0
;
dvbdmxfeed
->
buffer
=
0
;
(
*
feed
)
=&
dvbdmxfeed
->
feed
.
sec
;
(
*
feed
)
=&
dvbdmxfeed
->
feed
.
sec
;
(
*
feed
)
->
is_filtering
=
0
;
(
*
feed
)
->
is_filtering
=
0
;
(
*
feed
)
->
parent
=
demux
;
(
*
feed
)
->
parent
=
demux
;
(
*
feed
)
->
priv
=
0
;
(
*
feed
)
->
priv
=
0
;
(
*
feed
)
->
set
=
dmx_section_feed_set
;
(
*
feed
)
->
set
=
dmx_section_feed_set
;
(
*
feed
)
->
allocate_filter
=
dmx_section_feed_allocate_filter
;
(
*
feed
)
->
allocate_filter
=
dmx_section_feed_allocate_filter
;
(
*
feed
)
->
release_filter
=
dmx_section_feed_release_filter
;
(
*
feed
)
->
release_filter
=
dmx_section_feed_release_filter
;
(
*
feed
)
->
start_filtering
=
dmx_section_feed_start_filtering
;
(
*
feed
)
->
start_filtering
=
dmx_section_feed_start_filtering
;
(
*
feed
)
->
stop_filtering
=
dmx_section_feed_stop_filtering
;
(
*
feed
)
->
stop_filtering
=
dmx_section_feed_stop_filtering
;
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
0
;
return
0
;
}
}
static
int
dvbdmx_release_section_feed
(
dmx_demux_t
*
demux
,
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_feed
*
dvbdmxfeed
=
(
struct
dvb_demux_feed
*
)
feed
;
struct
dvb_demux
*
dvbdmx
=
(
struct
dvb_demux
*
)
demux
;
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
;
return
-
ERESTARTSYS
;
if
(
dvbdmxfeed
->
state
==
DMX_STATE_FREE
)
{
if
(
dvbdmxfeed
->
state
==
DMX_STATE_FREE
)
{
up
(
&
dvbdmx
->
mutex
);
up
(
&
dvbdmx
->
mutex
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
#ifndef NOBUFS
#ifndef NOBUFS
if
(
dvbdmxfeed
->
buffer
)
{
if
(
dvbdmxfeed
->
buffer
)
{
vfree
(
dvbdmxfeed
->
buffer
);
vfree
(
dvbdmxfeed
->
buffer
);
dvbdmxfeed
->
buffer
=
0
;
dvbdmxfeed
->
buffer
=
0
;
}
}
#endif
#endif
dvbdmxfeed
->
state
=
DMX_STATE_FREE
;
dvbdmxfeed
->
state
=
DMX_STATE_FREE
;
dvbdmxfeed
->
demux
->
pid2feed
[
dvbdmxfeed
->
pid
]
=
0
;
if
(
dvbdmxfeed
->
pid
!=
0xffff
)
if
(
dvbdmxfeed
->
pid
<=
DMX_MAX_PID
)
{
dvbdmxfeed
->
demux
->
pid2feed
[
dvbdmxfeed
->
pid
]
=
0
;
list_for_each_safe
(
pos
,
n
,
head
)
up
(
&
dvbdmx
->
mutex
);
if
(
DMX_FEED_ENTRY
(
pos
)
->
pid
==
dvbdmxfeed
->
pid
)
{
return
0
;
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,
...
@@ -977,72 +1029,72 @@ static int dvbdmx_release_section_feed(dmx_demux_t *demux,
static
int
dvbdmx_open
(
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
)
if
(
dvbdemux
->
users
>=
MAX_DVB_DEMUX_USERS
)
return
-
EUSERS
;
return
-
EUSERS
;
dvbdemux
->
users
++
;
dvbdemux
->
users
++
;
return
0
;
return
0
;
}
}
static
int
dvbdmx_close
(
struct
dmx_demux_s
*
demux
)
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
)
if
(
dvbdemux
->
users
==
0
)
return
-
ENODEV
;
return
-
ENODEV
;
dvbdemux
->
users
--
;
dvbdemux
->
users
--
;
//FIXME: release any unneeded resources if users==0
//FIXME: release any unneeded resources if users==0
return
0
;
return
0
;
}
}
static
int
dvbdmx_write
(
dmx_demux_t
*
demux
,
const
char
*
buf
,
size_t
count
)
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
)
||
if
((
!
demux
->
frontend
)
||
(
demux
->
frontend
->
source
!=
DMX_MEMORY_FE
))
(
demux
->
frontend
->
source
!=
DMX_MEMORY_FE
))
return
-
EINVAL
;
return
-
EINVAL
;
if
(
down_interruptible
(
&
dvbdemux
->
mutex
))
if
(
down_interruptible
(
&
dvbdemux
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
dvb_dmx_swfilter
(
dvbdemux
,
buf
,
count
);
dvb_dmx_swfilter
(
dvbdemux
,
buf
,
count
);
up
(
&
dvbdemux
->
mutex
);
up
(
&
dvbdemux
->
mutex
);
return
count
;
return
count
;
}
}
static
int
dvbdmx_add_frontend
(
dmx_demux_t
*
demux
,
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
dvb_demux
*
dvbdemux
=
(
struct
dvb_demux
*
)
demux
;
struct
list_head
*
pos
,
*
head
=&
dvbdemux
->
frontend_list
;
struct
list_head
*
pos
,
*
head
=&
dvbdemux
->
frontend_list
;
if
(
!
(
frontend
->
id
&&
frontend
->
vendor
&&
frontend
->
model
))
if
(
!
(
frontend
->
id
&&
frontend
->
vendor
&&
frontend
->
model
))
return
-
EINVAL
;
return
-
EINVAL
;
list_for_each
(
pos
,
head
)
list_for_each
(
pos
,
head
)
{
{
if
(
!
strcmp
(
DMX_FE_ENTRY
(
pos
)
->
id
,
frontend
->
id
))
if
(
!
strcmp
(
DMX_FE_ENTRY
(
pos
)
->
id
,
frontend
->
id
))
return
-
EEXIST
;
return
-
EEXIST
;
}
}
list_add
(
&
(
frontend
->
connectivity_list
),
head
);
list_add
(
&
(
frontend
->
connectivity_list
),
head
);
return
0
;
return
0
;
}
}
static
int
static
int
dvbdmx_remove_frontend
(
dmx_demux_t
*
demux
,
dvbdmx_remove_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
;
struct
list_head
*
pos
,
*
n
,
*
head
=&
dvbdemux
->
frontend_list
;
struct
list_head
*
pos
,
*
n
,
*
head
=&
dvbdemux
->
frontend_list
;
list_for_each_safe
(
pos
,
n
,
head
)
list_for_each_safe
(
pos
,
n
,
head
)
{
{
if
(
DMX_FE_ENTRY
(
pos
)
==
frontend
)
if
(
DMX_FE_ENTRY
(
pos
)
==
frontend
)
{
{
list_del
(
pos
);
list_del
(
pos
);
return
0
;
return
0
;
}
}
}
}
...
@@ -1052,123 +1104,129 @@ dvbdmx_remove_frontend(dmx_demux_t *demux,
...
@@ -1052,123 +1104,129 @@ dvbdmx_remove_frontend(dmx_demux_t *demux,
static
struct
list_head
*
static
struct
list_head
*
dvbdmx_get_frontends
(
dmx_demux_t
*
demux
)
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
))
if
(
list_empty
(
&
dvbdemux
->
frontend_list
))
return
NULL
;
return
NULL
;
return
&
dvbdemux
->
frontend_list
;
return
&
dvbdemux
->
frontend_list
;
}
}
static
int
dvbdmx_connect_frontend
(
dmx_demux_t
*
demux
,
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
)
if
(
demux
->
frontend
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
down_interruptible
(
&
dvbdemux
->
mutex
))
if
(
down_interruptible
(
&
dvbdemux
->
mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
demux
->
frontend
=
frontend
;
demux
->
frontend
=
frontend
;
up
(
&
dvbdemux
->
mutex
);
up
(
&
dvbdemux
->
mutex
);
return
0
;
return
0
;
}
}
static
int
dvbdmx_disconnect_frontend
(
dmx_demux_t
*
demux
)
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
;
return
-
ERESTARTSYS
;
demux
->
frontend
=
NULL
;
demux
->
frontend
=
NULL
;
up
(
&
dvbdemux
->
mutex
);
up
(
&
dvbdemux
->
mutex
);
return
0
;
return
0
;
}
}
static
int
dvbdmx_get_pes_pids
(
dmx_demux_t
*
demux
,
u16
*
pids
)
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
));
memcpy
(
pids
,
dvbdemux
->
pids
,
5
*
sizeof
(
u16
));
return
0
;
return
0
;
}
}
int
int
dvb_dmx_init
(
struct
dvb_demux
*
dvbdemux
)
dvb_dmx_init
(
struct
dvb_demux
*
dvbdemux
)
{
{
int
i
;
int
i
;
dmx_demux_t
*
dmx
=&
dvbdemux
->
dmx
;
dmx_demux_t
*
dmx
=&
dvbdemux
->
dmx
;
dvbdemux
->
users
=
0
;
dvbdemux
->
users
=
0
;
dvbdemux
->
filter
=
vmalloc
(
dvbdemux
->
filternum
*
sizeof
(
struct
dvb_demux_filter
));
dvbdemux
->
filter
=
vmalloc
(
dvbdemux
->
filternum
*
sizeof
(
struct
dvb_demux_filter
));
if
(
!
dvbdemux
->
filter
)
if
(
!
dvbdemux
->
filter
)
return
-
ENOMEM
;
return
-
ENOMEM
;
dvbdemux
->
feed
=
vmalloc
(
dvbdemux
->
feednum
*
sizeof
(
struct
dvb_demux_feed
));
dvbdemux
->
feed
=
vmalloc
(
dvbdemux
->
feednum
*
sizeof
(
struct
dvb_demux_feed
));
if
(
!
dvbdemux
->
feed
)
{
if
(
!
dvbdemux
->
feed
)
{
vfree
(
dvbdemux
->
filter
);
vfree
(
dvbdemux
->
filter
);
return
-
ENOMEM
;
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
++
)
{
for
(
i
=
0
;
i
<
dvbdemux
->
feednum
;
i
++
)
dvbdemux
->
filter
[
i
].
state
=
DMX_STATE_FREE
;
dvbdemux
->
feed
[
i
].
state
=
DMX_STATE_FREE
;
dvbdemux
->
filter
[
i
].
index
=
i
;
dvbdemux
->
frontend_list
.
next
=
}
dvbdemux
->
frontend_list
.
prev
=
for
(
i
=
0
;
i
<
dvbdemux
->
feednum
;
i
++
)
&
dvbdemux
->
frontend_list
;
dvbdemux
->
feed
[
i
].
state
=
DMX_STATE_FREE
;
for
(
i
=
0
;
i
<
DMX_TS_PES_OTHER
;
i
++
)
{
dvbdemux
->
frontend_list
.
next
=
dvbdemux
->
pesfilter
[
i
]
=
NULL
;
dvbdemux
->
frontend_list
.
prev
=
dvbdemux
->
pids
[
i
]
=
0xffff
;
&
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
;
dvbdemux
->
playing
=
dvbdemux
->
recording
=
0
;
memset
(
dvbdemux
->
pid2feed
,
0
,
(
DMX_MAX_PID
+
1
)
*
sizeof
(
struct
dvb_demux_feed
*
));
INIT_LIST_HEAD
(
&
dvbdemux
->
feed_list
);
dvbdemux
->
tsbufp
=
0
;
dvbdemux
->
tsbufp
=
0
;
dmx
->
frontend
=
0
;
if
(
!
dvbdemux
->
check_crc32
)
dmx
->
reg_list
.
next
=
dmx
->
reg_list
.
prev
=&
dmx
->
reg_list
;
dvbdemux
->
check_crc32
=
dvb_dmx_crc32
;
dmx
->
priv
=
(
void
*
)
dvbdemux
;
//dmx->users=0; // reset in dmx_register_demux()
if
(
!
dvbdemux
->
memcopy
)
dmx
->
open
=
dvbdmx_open
;
dvbdemux
->
memcopy
=
dvb_dmx_memcopy
;
dmx
->
close
=
dvbdmx_close
;
dmx
->
write
=
dvbdmx_write
;
dmx
->
frontend
=
0
;
dmx
->
allocate_ts_feed
=
dvbdmx_allocate_ts_feed
;
dmx
->
reg_list
.
next
=
dmx
->
reg_list
.
prev
=&
dmx
->
reg_list
;
dmx
->
release_ts_feed
=
dvbdmx_release_ts_feed
;
dmx
->
priv
=
(
void
*
)
dvbdemux
;
dmx
->
allocate_section_feed
=
dvbdmx_allocate_section_feed
;
//dmx->users=0; // reset in dmx_register_demux()
dmx
->
release_section_feed
=
dvbdmx_release_section_feed
;
dmx
->
open
=
dvbdmx_open
;
dmx
->
close
=
dvbdmx_close
;
dmx
->
descramble_mac_address
=
NULL
;
dmx
->
write
=
dvbdmx_write
;
dmx
->
descramble_section_payload
=
NULL
;
dmx
->
allocate_ts_feed
=
dvbdmx_allocate_ts_feed
;
dmx
->
release_ts_feed
=
dvbdmx_release_ts_feed
;
dmx
->
add_frontend
=
dvbdmx_add_frontend
;
dmx
->
allocate_section_feed
=
dvbdmx_allocate_section_feed
;
dmx
->
remove_frontend
=
dvbdmx_remove_frontend
;
dmx
->
release_section_feed
=
dvbdmx_release_section_feed
;
dmx
->
get_frontends
=
dvbdmx_get_frontends
;
dmx
->
connect_frontend
=
dvbdmx_connect_frontend
;
dmx
->
descramble_mac_address
=
NULL
;
dmx
->
disconnect_frontend
=
dvbdmx_disconnect_frontend
;
dmx
->
descramble_section_payload
=
NULL
;
dmx
->
get_pes_pids
=
dvbdmx_get_pes_pids
;
sema_init
(
&
dvbdemux
->
mutex
,
1
);
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
);
spin_lock_init
(
&
dvbdemux
->
lock
);
if
(
dmx_register_demux
(
dmx
)
<
0
)
if
(
dmx_register_demux
(
dmx
)
<
0
)
return
-
1
;
return
-
1
;
return
0
;
return
0
;
}
}
int
int
dvb_dmx_release
(
struct
dvb_demux
*
dvbdemux
)
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
)
if
(
dvbdemux
->
filter
)
vfree
(
dvbdemux
->
filter
);
vfree
(
dvbdemux
->
filter
);
if
(
dvbdemux
->
feed
)
if
(
dvbdemux
->
feed
)
vfree
(
dvbdemux
->
feed
);
vfree
(
dvbdemux
->
feed
);
return
0
;
return
0
;
}
}
#if 0
#if 0
...
...
drivers/media/dvb/dvb-core/dvb_demux.h
View file @
28003225
...
@@ -25,6 +25,9 @@
...
@@ -25,6 +25,9 @@
#ifndef _DVB_DEMUX_H_
#ifndef _DVB_DEMUX_H_
#define _DVB_DEMUX_H_
#define _DVB_DEMUX_H_
#include <asm/semaphore.h>
#include <linux/timer.h>
#include "demux.h"
#include "demux.h"
#define DMX_TYPE_TS 0
#define DMX_TYPE_TS 0
...
@@ -59,6 +62,8 @@ struct dvb_demux_filter {
...
@@ -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
{
struct
dvb_demux_feed
{
union
{
union
{
dmx_ts_feed_t
ts
;
dmx_ts_feed_t
ts
;
...
@@ -71,13 +76,13 @@ struct dvb_demux_feed {
...
@@ -71,13 +76,13 @@ struct dvb_demux_feed {
}
cb
;
}
cb
;
struct
dvb_demux
*
demux
;
struct
dvb_demux
*
demux
;
void
*
priv
;
int
type
;
int
type
;
int
state
;
int
state
;
u16
pid
;
u16
pid
;
u8
*
buffer
;
u8
*
buffer
;
int
buffer_size
;
int
buffer_size
;
int
descramble
;
int
descramble
;
int
check_crc
;
struct
timespec
timeout
;
struct
timespec
timeout
;
struct
dvb_demux_filter
*
filter
;
struct
dvb_demux_filter
*
filter
;
...
@@ -86,12 +91,11 @@ struct dvb_demux_feed {
...
@@ -86,12 +91,11 @@ struct dvb_demux_feed {
int
ts_type
;
int
ts_type
;
dmx_ts_pes_t
pes_type
;
dmx_ts_pes_t
pes_type
;
u8
secbuf
[
4096
];
int
secbufp
;
int
seclen
;
int
cc
;
int
cc
;
u16
peslen
;
u16
peslen
;
struct
list_head
list_head
;
};
};
struct
dvb_demux
{
struct
dvb_demux
{
...
@@ -99,10 +103,14 @@ struct dvb_demux {
...
@@ -99,10 +103,14 @@ struct dvb_demux {
void
*
priv
;
void
*
priv
;
int
filternum
;
int
filternum
;
int
feednum
;
int
feednum
;
int
(
*
start_feed
)(
struct
dvb_demux_feed
*
);
int
(
*
start_feed
)
(
struct
dvb_demux_feed
*
feed
);
int
(
*
stop_feed
)(
struct
dvb_demux_feed
*
);
int
(
*
stop_feed
)
(
struct
dvb_demux_feed
*
feed
);
int
(
*
write_to_decoder
)(
struct
dvb_demux_feed
*
,
u8
*
,
size_t
);
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
;
int
users
;
#define MAX_DVB_DEMUX_USERS 10
#define MAX_DVB_DEMUX_USERS 10
...
@@ -117,7 +125,7 @@ struct dvb_demux {
...
@@ -117,7 +125,7 @@ struct dvb_demux {
int
recording
;
int
recording
;
#define DMX_MAX_PID 0x2000
#define DMX_MAX_PID 0x2000
struct
dvb_demux_feed
*
pid2feed
[
DMX_MAX_PID
+
1
]
;
struct
list_head
feed_list
;
u8
tsbuf
[
188
];
u8
tsbuf
[
188
];
int
tsbufp
;
int
tsbufp
;
...
@@ -129,6 +137,7 @@ struct dvb_demux {
...
@@ -129,6 +137,7 @@ struct dvb_demux {
int
dvb_dmx_init
(
struct
dvb_demux
*
dvbdemux
);
int
dvb_dmx_init
(
struct
dvb_demux
*
dvbdemux
);
int
dvb_dmx_release
(
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_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_ */
#endif
/* _DVB_DEMUX_H_ */
drivers/media/dvb/dvb-core/dvb_filter.c
View file @
28003225
#include <linux/module.h>
#include <linux/module.h>
#include <linux/videodev.h>
#include "dvb_filter.h"
#include "dvb_filter.h"
unsigned
int
bitrates
[
3
][
16
]
=
unsigned
int
bitrates
[
3
][
16
]
=
...
@@ -52,10 +51,10 @@ void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
...
@@ -52,10 +51,10 @@ void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
if (buf[1]&PAY_START) {
if (buf[1]&PAY_START) {
if (p->plength == MMAX_PLENGTH-6 && p->found>6){
if (p->plength == MMAX_PLENGTH-6 && p->found>6){
p->plength = p->found-6;
p->plength = p->found-6;
p->found = 0;
p->found = 0;
send_ipack(p);
send_ipack(p);
dvb_filter_ipack_reset(p);
dvb_filter_ipack_reset(p);
}
}
}
}
if (buf[3] & ADAPT_FIELD) { // adaptation field?
if (buf[3] & ADAPT_FIELD) { // adaptation field?
off = buf[4] + 1;
off = buf[4] + 1;
...
@@ -71,12 +70,12 @@ static
...
@@ -71,12 +70,12 @@ static
int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr)
int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr)
{
{
uint8_t pct;
uint8_t pct;
if (pr) printk( "Pic header: ");
if (pr) printk( "Pic header: ");
pic->temporal_reference[field] = (( headr[0] << 2 ) |
pic->temporal_reference[field] = (( headr[0] << 2 ) |
(headr[1] & 0x03) )& 0x03ff;
(headr[1] & 0x03) )& 0x03ff;
if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
pct = ( headr[1] >> 2 ) & 0x07;
pct = ( headr[1] >> 2 ) & 0x07;
pic->picture_coding_type[field] = pct;
pic->picture_coding_type[field] = pct;
if (pr) {
if (pr) {
...
@@ -90,26 +89,26 @@ int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr)
...
@@ -90,26 +89,26 @@ int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr)
case P_FRAME:
case P_FRAME:
printk( " P-FRAME");
printk( " P-FRAME");
break;
break;
}
}
}
}
pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) |
pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) |
( (headr[3] & 0x1F) << 11) ) & 0xffff;
( (headr[3] & 0x1F) << 11) ) & 0xffff;
if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
((headr[4] & 0x80) >> 3);
((headr[4] & 0x80) >> 3);
if ( pct == B_FRAME ){
if ( pct == B_FRAME ){
pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
}
}
if (pr) printk( " pic head param: 0x%x",
if (pr) printk( " pic head param: 0x%x",
pic->picture_header_parameter);
pic->picture_header_parameter);
return pct;
return pct;
}
}
#endif
#endif
#if 0
#if 0
...
@@ -130,14 +129,14 @@ int read_gop_header(uint8_t *headr, mpg_picture *pic, int pr)
...
@@ -130,14 +129,14 @@ int read_gop_header(uint8_t *headr, mpg_picture *pic, int pr)
pic->closed_gop = 1;
pic->closed_gop = 1;
} else {
} else {
pic->closed_gop = 0;
pic->closed_gop = 0;
}
}
if (pr) printk("closed: %d", pic->closed_gop);
if (pr) printk("closed: %d", pic->closed_gop);
if ( ( headr[3] & 0x20 ) != 0 ){
if ( ( headr[3] & 0x20 ) != 0 ){
pic->broken_link = 1;
pic->broken_link = 1;
} else {
} else {
pic->broken_link = 0;
pic->broken_link = 0;
}
}
if (pr) printk(" broken: %d\n", pic->broken_link);
if (pr) printk(" broken: %d\n", pic->broken_link);
return 0;
return 0;
...
@@ -160,37 +159,37 @@ int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr)
...
@@ -160,37 +159,37 @@ int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr)
sw = (int)((headr[3]&0xF0) >> 4) ;
sw = (int)((headr[3]&0xF0) >> 4) ;
switch( sw ){
switch( sw ){
case 1:
case 1:
if (pr)
if (pr)
printk("Videostream: ASPECT: 1:1");
printk("Videostream: ASPECT: 1:1");
vi->aspect_ratio = 100;
vi->aspect_ratio = 100;
break;
break;
case 2:
case 2:
if (pr)
if (pr)
printk("Videostream: ASPECT: 4:3");
printk("Videostream: ASPECT: 4:3");
vi->aspect_ratio = 133;
vi->aspect_ratio = 133;
break;
break;
case 3:
case 3:
if (pr)
if (pr)
printk("Videostream: ASPECT: 16:9");
printk("Videostream: ASPECT: 16:9");
vi->aspect_ratio = 177;
vi->aspect_ratio = 177;
break;
break;
case 4:
case 4:
if (pr)
if (pr)
printk("Videostream: ASPECT: 2.21:1");
printk("Videostream: ASPECT: 2.21:1");
vi->aspect_ratio = 221;
vi->aspect_ratio = 221;
break;
break;
case 5 ... 15:
case 5 ... 15:
if (pr)
if (pr)
printk("Videostream: ASPECT: reserved");
printk("Videostream: ASPECT: reserved");
vi->aspect_ratio = 0;
vi->aspect_ratio = 0;
break;
break;
default:
default:
vi->aspect_ratio = 0;
vi->aspect_ratio = 0;
return -1;
return -1;
}
}
if (pr)
if (pr)
printk(" Size = %dx%d",vi->horizontal_size,vi->vertical_size);
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)
...
@@ -221,29 +220,29 @@ int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr)
printk(" FRate: 29.97 fps");
printk(" FRate: 29.97 fps");
vi->framerate = 29970;
vi->framerate = 29970;
form = VIDEO_MODE_NTSC;
form = VIDEO_MODE_NTSC;
break;
break;
case 5:
case 5:
if (pr)
if (pr)
printk(" FRate: 30 fps");
printk(" FRate: 30 fps");
vi->framerate = 30000;
vi->framerate = 30000;
form = VIDEO_MODE_NTSC;
form = VIDEO_MODE_NTSC;
break;
break;
case 6:
case 6:
if (pr)
if (pr)
printk(" FRate: 50 fps");
printk(" FRate: 50 fps");
vi->framerate = 50000;
vi->framerate = 50000;
form = VIDEO_MODE_PAL;
form = VIDEO_MODE_PAL;
break;
break;
case 7:
case 7:
if (pr)
if (pr)
printk(" FRate: 60 fps");
printk(" FRate: 60 fps");
vi->framerate = 60000;
vi->framerate = 60000;
form = VIDEO_MODE_NTSC;
form = VIDEO_MODE_NTSC;
break;
break;
}
}
vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
vi->vbv_buffer_size
vi->vbv_buffer_size
= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
...
@@ -259,7 +258,7 @@ int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr)
...
@@ -259,7 +258,7 @@ int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr)
}
}
#endif
#endif
#if 0
#if 0
static
static
int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
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)
...
@@ -267,7 +266,7 @@ int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
uint8_t *headr;
uint8_t *headr;
int found = 0;
int found = 0;
int c = 0;
int c = 0;
while (found < 4 && c+4 < count){
while (found < 4 && c+4 < count){
uint8_t *b;
uint8_t *b;
...
@@ -277,7 +276,7 @@ int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
...
@@ -277,7 +276,7 @@ int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
else {
else {
c++;
c++;
}
}
}
}
if (! found) return -1;
if (! found) return -1;
c += 4;
c += 4;
...
@@ -288,7 +287,7 @@ int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
...
@@ -288,7 +287,7 @@ int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
return 0;
return 0;
}
}
#endif
#endif
#if 0
#if 0
static
static
...
@@ -306,9 +305,9 @@ int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
...
@@ -306,9 +305,9 @@ int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
found = 2;
found = 2;
else {
else {
c++;
c++;
}
}
}
}
if (!found) return -1;
if (!found) return -1;
...
@@ -330,7 +329,7 @@ int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
...
@@ -330,7 +329,7 @@ int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
printk(" BRate: reserved");
printk(" BRate: reserved");
else
else
printk(" BRate: %d kb/s", ai->bit_rate/1000);
printk(" BRate: %d kb/s", ai->bit_rate/1000);
}
}
fr = (headr[2] & 0x0c ) >> 2;
fr = (headr[2] & 0x0c ) >> 2;
ai->frequency = freq[fr]*100;
ai->frequency = freq[fr]*100;
...
@@ -340,41 +339,41 @@ int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
...
@@ -340,41 +339,41 @@ int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
else
else
printk(" Freq: %d kHz\n",ai->frequency);
printk(" Freq: %d kHz\n",ai->frequency);
}
}
ai->off = c;
ai->off = c;
return 0;
return 0;
}
}
#endif
#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
;
uint8_t
*
headr
;
int
found
=
0
;
int
found
=
0
;
int
c
=
0
;
int
c
=
0
;
uint8_t
frame
=
0
;
uint8_t
frame
=
0
;
int
fr
=
0
;
int
fr
=
0
;
while
(
!
found
&&
c
<
count
){
while
(
!
found
&&
c
<
count
){
uint8_t
*
b
=
mbuf
+
c
;
uint8_t
*
b
=
mbuf
+
c
;
if
(
b
[
0
]
==
0x0b
&&
b
[
1
]
==
0x77
)
if
(
b
[
0
]
==
0x0b
&&
b
[
1
]
==
0x77
)
found
=
1
;
found
=
1
;
else
{
else
{
c
++
;
c
++
;
}
}
}
}
if
(
!
found
)
return
-
1
;
if
(
!
found
)
return
-
1
;
if
(
pr
)
if
(
pr
)
printk
(
"Audiostream: AC3"
);
printk
(
"Audiostream: AC3"
);
ai
->
off
=
c
;
ai
->
off
=
c
;
if
(
c
+
5
>=
count
)
return
-
1
;
if
(
c
+
5
>=
count
)
return
-
1
;
ai
->
layer
=
0
;
// 0 for AC3
ai
->
layer
=
0
;
// 0 for AC3
headr
=
mbuf
+
c
+
2
;
headr
=
mbuf
+
c
+
2
;
frame
=
(
headr
[
2
]
&
0x3f
);
frame
=
(
headr
[
2
]
&
0x3f
);
ai
->
bit_rate
=
ac3_bitrates
[
frame
>>
1
]
*
1000
;
ai
->
bit_rate
=
ac3_bitrates
[
frame
>>
1
]
*
1000
;
...
@@ -420,8 +419,8 @@ uint8_t *skip_pes_header(uint8_t **bufp)
...
@@ -420,8 +419,8 @@ uint8_t *skip_pes_header(uint8_t **bufp)
} else { /* mpeg1 */
} else { /* mpeg1 */
for (buf = inbuf + 6; *buf == 0xff; buf++)
for (buf = inbuf + 6; *buf == 0xff; buf++)
if (buf == inbuf + 6 + 16) {
if (buf == inbuf + 6 + 16) {
break;
break;
}
}
if ((*buf & 0xc0) == 0x40)
if ((*buf & 0xc0) == 0x40)
buf += 2;
buf += 2;
skip = mpeg1_skip_table [*buf >> 4];
skip = mpeg1_skip_table [*buf >> 4];
...
@@ -433,7 +432,7 @@ uint8_t *skip_pes_header(uint8_t **bufp)
...
@@ -433,7 +432,7 @@ uint8_t *skip_pes_header(uint8_t **bufp)
*bufp = buf;
*bufp = buf;
return pts;
return pts;
}
}
#endif
#endif
#if 0
#if 0
...
@@ -509,7 +508,7 @@ void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic )
...
@@ -509,7 +508,7 @@ void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic )
pic->progressive_frame = 1;
pic->progressive_frame = 1;
pic->picture_coding_parameter = 0x000010;
pic->picture_coding_parameter = 0x000010;
}
}
/* Reset flag */
/* Reset flag */
pic->picture_display_extension_flag[field_type] = 0;
pic->picture_display_extension_flag[field_type] = 0;
...
@@ -527,7 +526,7 @@ void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic )
...
@@ -527,7 +526,7 @@ void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic )
} else {
} else {
pic->frame_centre_horizontal_offset[3] = last_h_offset;
pic->frame_centre_horizontal_offset[3] = last_h_offset;
pic->frame_centre_vertical_offset[3] = last_v_offset;
pic->frame_centre_vertical_offset[3] = last_v_offset;
}
}
}
}
#endif
#endif
...
@@ -566,7 +565,7 @@ void dvb_filter_pes2ts_init(dvb_filter_pes2ts_t *p2ts, unsigned short pid,
...
@@ -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
)
dvb_filter_pes2ts_cb_t
*
cb
,
void
*
priv
)
{
{
unsigned
char
*
buf
=
p2ts
->
buf
;
unsigned
char
*
buf
=
p2ts
->
buf
;
buf
[
0
]
=
0x47
;
buf
[
0
]
=
0x47
;
buf
[
1
]
=
(
pid
>>
8
);
buf
[
1
]
=
(
pid
>>
8
);
buf
[
2
]
=
pid
&
0xff
;
buf
[
2
]
=
pid
&
0xff
;
...
@@ -579,7 +578,7 @@ int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len)
...
@@ -579,7 +578,7 @@ int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len)
{
{
unsigned
char
*
buf
=
p2ts
->
buf
;
unsigned
char
*
buf
=
p2ts
->
buf
;
int
ret
=
0
,
rest
;
int
ret
=
0
,
rest
;
//len=6+((pes[4]<<8)|pes[5]);
//len=6+((pes[4]<<8)|pes[5]);
buf
[
1
]
|=
0x40
;
buf
[
1
]
|=
0x40
;
...
@@ -592,7 +591,7 @@ int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len)
...
@@ -592,7 +591,7 @@ int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len)
buf
[
1
]
&=~
0x40
;
buf
[
1
]
&=~
0x40
;
}
}
if
(
!
len
)
if
(
!
len
)
return
0
;
return
0
;
buf
[
3
]
=
0x30
|
((
p2ts
->
cc
++
)
&
0x0f
);
buf
[
3
]
=
0x30
|
((
p2ts
->
cc
++
)
&
0x0f
);
rest
=
183
-
len
;
rest
=
183
-
len
;
if
(
rest
)
{
if
(
rest
)
{
...
@@ -605,397 +604,3 @@ int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len)
...
@@ -605,397 +604,3 @@ int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len)
return
p2ts
->
cb
(
p2ts
->
priv
,
buf
);
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 {
...
@@ -17,6 +17,7 @@ typedef struct dvb_filter_pes2ts_s {
void
dvb_filter_pes2ts_init
(
dvb_filter_pes2ts_t
*
p2ts
,
unsigned
short
pid
,
void
dvb_filter_pes2ts_init
(
dvb_filter_pes2ts_t
*
p2ts
,
unsigned
short
pid
,
dvb_filter_pes2ts_cb_t
*
cb
,
void
*
priv
);
dvb_filter_pes2ts_cb_t
*
cb
,
void
*
priv
);
int
dvb_filter_pes2ts
(
dvb_filter_pes2ts_t
*
p2ts
,
unsigned
char
*
pes
,
int
len
);
int
dvb_filter_pes2ts
(
dvb_filter_pes2ts_t
*
p2ts
,
unsigned
char
*
pes
,
int
len
);
...
@@ -223,12 +224,7 @@ typedef struct audio_i{
...
@@ -223,12 +224,7 @@ typedef struct audio_i{
uint32_t
off
;
uint32_t
off
;
}
AudioInfo
;
}
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
#endif
drivers/media/dvb/dvb-core/dvb_frontend.c
View file @
28003225
...
@@ -27,16 +27,14 @@
...
@@ -27,16 +27,14 @@
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/compatmac.h>
#include <linux/list.h>
#include <linux/list.h>
#include "compat.h"
#include "dvb_frontend.h"
#include "dvb_frontend.h"
#include "dvbdev.h"
#include "dvbdev.h"
static
int
dvb_frontend_debug
=
0
;
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
#define dprintk if (dvb_frontend_debug) printk
...
@@ -52,18 +50,10 @@ struct dvb_fe_events {
...
@@ -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_data
{
struct
dvb_frontend_info
*
info
;
struct
dvb_frontend_info
*
info
;
struct
dvb_frontend
frontend
;
struct
dvb_frontend
frontend
;
struct
dvb_device
*
dvbdev
;
struct
dvb_device
*
dvbdev
;
struct
list_head
notifier_callbacks
;
struct
dvb_frontend_parameters
parameters
;
struct
dvb_frontend_parameters
parameters
;
struct
dvb_fe_events
events
;
struct
dvb_fe_events
events
;
struct
semaphore
sem
;
struct
semaphore
sem
;
...
@@ -92,8 +82,17 @@ struct dvb_frontend_ioctl_data {
...
@@ -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_list
);
static
LIST_HEAD
(
frontend_ioctl_list
);
static
LIST_HEAD
(
frontend_ioctl_list
);
static
LIST_HEAD
(
frontend_notifier_list
);
static
DECLARE_MUTEX
(
frontend_mutex
);
static
DECLARE_MUTEX
(
frontend_mutex
);
...
@@ -153,6 +152,7 @@ void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive)
...
@@ -153,6 +152,7 @@ void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive)
if
(
!
recursive
)
{
if
(
!
recursive
)
{
if
(
down_interruptible
(
&
frontend_mutex
))
if
(
down_interruptible
(
&
frontend_mutex
))
return
;
return
;
this_fe
->
bending
=
0
;
this_fe
->
bending
=
0
;
}
}
...
@@ -170,7 +170,7 @@ void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive)
...
@@ -170,7 +170,7 @@ void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive)
frequency
+=
this_fe
->
lnb_drift
;
frequency
+=
this_fe
->
lnb_drift
;
frequency
+=
this_fe
->
bending
;
frequency
+=
this_fe
->
bending
;
if
(
this_fe
!=
fe
&&
if
(
this_fe
!=
fe
&&
fe
->
lost_sync_count
!=
-
1
&&
frequency
>
f
-
stepsize
&&
frequency
<
f
+
stepsize
)
frequency
>
f
-
stepsize
&&
frequency
<
f
+
stepsize
)
{
{
if
(
recursive
%
2
)
if
(
recursive
%
2
)
...
@@ -192,9 +192,6 @@ static
...
@@ -192,9 +192,6 @@ static
void
dvb_call_frontend_notifiers
(
struct
dvb_frontend_data
*
fe
,
void
dvb_call_frontend_notifiers
(
struct
dvb_frontend_data
*
fe
,
fe_status_t
s
)
fe_status_t
s
)
{
{
struct
list_head
*
e
;
struct
dvb_fe_notifier_callbacks
*
c
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
((
fe
->
status
&
FE_HAS_LOCK
)
&&
!
(
s
&
FE_HAS_LOCK
))
if
((
fe
->
status
&
FE_HAS_LOCK
)
&&
!
(
s
&
FE_HAS_LOCK
))
...
@@ -211,10 +208,8 @@ void dvb_call_frontend_notifiers (struct dvb_frontend_data *fe,
...
@@ -211,10 +208,8 @@ void dvb_call_frontend_notifiers (struct dvb_frontend_data *fe,
/**
/**
* now tell the Demux about the TS status changes...
* now tell the Demux about the TS status changes...
*/
*/
list_for_each
(
e
,
&
fe
->
notifier_callbacks
)
{
if
(
fe
->
frontend
.
notifier_callback
)
c
=
list_entry
(
e
,
struct
dvb_fe_notifier_callbacks
,
list_head
);
fe
->
frontend
.
notifier_callback
(
fe
->
status
,
fe
->
frontend
.
notifier_data
);
c
->
callback
(
fe
->
status
,
c
->
data
);
}
}
}
...
@@ -296,38 +291,6 @@ int dvb_frontend_get_event (struct dvb_frontend_data *fe,
...
@@ -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
static
int
dvb_frontend_set_parameters
(
struct
dvb_frontend_data
*
fe
,
int
dvb_frontend_set_parameters
(
struct
dvb_frontend_data
*
fe
,
struct
dvb_frontend_parameters
*
param
,
struct
dvb_frontend_parameters
*
param
,
...
@@ -336,8 +299,6 @@ int dvb_frontend_set_parameters (struct dvb_frontend_data *fe,
...
@@ -336,8 +299,6 @@ int dvb_frontend_set_parameters (struct dvb_frontend_data *fe,
struct
dvb_frontend
*
frontend
=
&
fe
->
frontend
;
struct
dvb_frontend
*
frontend
=
&
fe
->
frontend
;
int
err
;
int
err
;
dvb_bend_frequency
(
fe
,
0
);
if
(
first_trial
)
{
if
(
first_trial
)
{
fe
->
timeout_count
=
0
;
fe
->
timeout_count
=
0
;
fe
->
lost_sync_count
=
0
;
fe
->
lost_sync_count
=
0
;
...
@@ -349,6 +310,8 @@ int dvb_frontend_set_parameters (struct dvb_frontend_data *fe,
...
@@ -349,6 +310,8 @@ int dvb_frontend_set_parameters (struct dvb_frontend_data *fe,
sizeof
(
struct
dvb_frontend_parameters
));
sizeof
(
struct
dvb_frontend_parameters
));
}
}
dvb_bend_frequency
(
fe
,
0
);
dprintk
(
"%s: f == %i, drift == %i
\n
"
,
dprintk
(
"%s: f == %i, drift == %i
\n
"
,
__FUNCTION__
,
param
->
frequency
,
fe
->
lnb_drift
);
__FUNCTION__
,
param
->
frequency
,
fe
->
lnb_drift
);
...
@@ -365,23 +328,12 @@ static
...
@@ -365,23 +328,12 @@ static
void
dvb_frontend_init
(
struct
dvb_frontend_data
*
fe
)
void
dvb_frontend_init
(
struct
dvb_frontend_data
*
fe
)
{
{
struct
dvb_frontend
*
frontend
=
&
fe
->
frontend
;
struct
dvb_frontend
*
frontend
=
&
fe
->
frontend
;
struct
dvb_frontend_parameters
*
init_param
;
printk
(
"DVB: initialising frontend %i:%i (%s)...
\n
"
,
dprintk
(
"DVB: initialising frontend %i:%i (%s)...
\n
"
,
frontend
->
i2c
->
adapter
->
num
,
frontend
->
i2c
->
id
,
fe
->
info
->
name
);
frontend
->
i2c
->
adapter
->
num
,
frontend
->
i2c
->
id
,
fe
->
info
->
name
);
dvb_frontend_internal_ioctl
(
frontend
,
FE_INIT
,
NULL
);
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)
...
@@ -464,7 +416,7 @@ int dvb_frontend_is_exiting (struct dvb_frontend_data *fe)
if
(
fe
->
exit
)
if
(
fe
->
exit
)
return
1
;
return
1
;
if
(
fe
->
dvbdev
->
users
==
0
&&
dvb_shutdown_timeout
)
if
(
fe
->
dvbdev
->
writers
==
1
)
if
(
jiffies
-
fe
->
release_jiffies
>
dvb_shutdown_timeout
*
HZ
)
if
(
jiffies
-
fe
->
release_jiffies
>
dvb_shutdown_timeout
*
HZ
)
return
1
;
return
1
;
...
@@ -482,13 +434,27 @@ int dvb_frontend_thread (void *data)
...
@@ -482,13 +434,27 @@ int dvb_frontend_thread (void *data)
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
lock_kernel
();
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
;
fe
->
thread
=
current
;
snprintf
(
current
->
comm
,
sizeof
(
current
->
comm
),
"kdvb-fe-%i:%i"
,
fe
->
frontend
.
i2c
->
adapter
->
num
,
fe
->
frontend
.
i2c
->
id
);
unlock_kernel
();
unlock_kernel
();
dvb_call_frontend_notifiers
(
fe
,
0
);
dvb_call_frontend_notifiers
(
fe
,
0
);
dvb_frontend_init
(
fe
);
dvb_frontend_init
(
fe
);
fe
->
lost_sync_count
=
-
1
;
while
(
!
dvb_frontend_is_exiting
(
fe
))
{
while
(
!
dvb_frontend_is_exiting
(
fe
))
{
up
(
&
fe
->
sem
);
/* is locked when we enter the thread... */
up
(
&
fe
->
sem
);
/* is locked when we enter the thread... */
...
@@ -499,6 +465,9 @@ int dvb_frontend_thread (void *data)
...
@@ -499,6 +465,9 @@ int dvb_frontend_thread (void *data)
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
}
}
if
(
fe
->
lost_sync_count
==
-
1
)
continue
;
if
(
dvb_frontend_is_exiting
(
fe
))
if
(
dvb_frontend_is_exiting
(
fe
))
break
;
break
;
...
@@ -513,10 +482,14 @@ int dvb_frontend_thread (void *data)
...
@@ -513,10 +482,14 @@ int dvb_frontend_thread (void *data)
fe
->
lost_sync_count
=
0
;
fe
->
lost_sync_count
=
0
;
}
else
{
}
else
{
fe
->
lost_sync_count
++
;
fe
->
lost_sync_count
++
;
if
(
fe
->
lost_sync_count
<
10
)
/* XXX FIXME CHECKME! */
if
(
!
(
fe
->
info
->
caps
&
FE_CAN_RECOVER
))
{
continue
;
if
(
!
(
fe
->
info
->
caps
&
FE_CAN_CLEAN_SETUP
))
{
dvb_frontend_recover
(
fe
);
if
(
fe
->
lost_sync_count
<
10
)
delay
=
HZ
/
5
;
continue
;
}
dvb_frontend_recover
(
fe
);
delay
=
HZ
/
5
;
}
if
(
jiffies
-
fe
->
lost_sync_jiffies
>
TIMEOUT
)
{
if
(
jiffies
-
fe
->
lost_sync_jiffies
>
TIMEOUT
)
{
s
|=
FE_TIMEDOUT
;
s
|=
FE_TIMEDOUT
;
if
((
fe
->
status
&
FE_TIMEDOUT
)
==
0
)
if
((
fe
->
status
&
FE_TIMEDOUT
)
==
0
)
...
@@ -528,7 +501,9 @@ int dvb_frontend_thread (void *data)
...
@@ -528,7 +501,9 @@ int dvb_frontend_thread (void *data)
dvb_frontend_add_event
(
fe
,
s
);
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
);
up
(
&
fe
->
sem
);
fe
->
thread
=
NULL
;
fe
->
thread
=
NULL
;
return
0
;
return
0
;
...
@@ -536,30 +511,36 @@ int dvb_frontend_thread (void *data)
...
@@ -536,30 +511,36 @@ int dvb_frontend_thread (void *data)
static
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__
);
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
!
fe
->
exit
&&
!
fe
->
thread
)
{
while
(
fe
->
thread
)
{
if
(
down_interruptible
(
&
fe
->
sem
))
fe
->
exit
=
1
;
return
;
wake_up_interruptible
(
&
fe
->
wait_queue
);
kernel_thread
(
dvb_frontend_thread
,
fe
,
0
);
current
->
state
=
TASK_INTERRUPTIBLE
;
}
schedule_timeout
(
5
);
if
(
signal_pending
(
current
))
break
;
};
}
}
static
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__
);
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
fe
->
exit
=
1
;
if
(
fe
->
thread
)
wake_up_interruptible
(
&
fe
->
wait_queu
e
);
dvb_frontend_stop
(
f
e
);
while
(
fe
->
thread
)
{
if
(
down_interruptible
(
&
fe
->
sem
))
current
->
state
=
TASK_INTERRUPTIBLE
;
return
;
schedule_timeout
(
5
);
};
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
...
@@ -615,9 +596,6 @@ unsigned int dvb_frontend_poll (struct file *file, struct poll_table_struct *wai
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
fe
->
events
.
eventw
!=
fe
->
events
.
eventr
)
return
(
POLLIN
|
POLLRDNORM
|
POLLPRI
);
poll_wait
(
file
,
&
fe
->
events
.
wait_queue
,
wait
);
poll_wait
(
file
,
&
fe
->
events
.
wait_queue
,
wait
);
if
(
fe
->
events
.
eventw
!=
fe
->
events
.
eventr
)
if
(
fe
->
events
.
eventw
!=
fe
->
events
.
eventr
)
...
@@ -639,10 +617,12 @@ int dvb_frontend_open (struct inode *inode, struct file *file)
...
@@ -639,10 +617,12 @@ int dvb_frontend_open (struct inode *inode, struct file *file)
if
((
ret
=
dvb_generic_open
(
inode
,
file
))
<
0
)
if
((
ret
=
dvb_generic_open
(
inode
,
file
))
<
0
)
return
ret
;
return
ret
;
dvb_frontend_start
(
fe
);
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_RDONLY
)
{
dvb_frontend_start
(
fe
);
/* empty event queue */
/* empty event queue */
fe
->
events
.
eventr
=
fe
->
events
.
eventw
;
fe
->
events
.
eventr
=
fe
->
events
.
eventw
;
}
return
ret
;
return
ret
;
}
}
...
@@ -656,7 +636,8 @@ int dvb_frontend_release (struct inode *inode, struct file *file)
...
@@ -656,7 +636,8 @@ int dvb_frontend_release (struct inode *inode, struct file *file)
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
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
);
return
dvb_generic_release
(
inode
,
file
);
}
}
...
@@ -673,7 +654,6 @@ dvb_add_frontend_ioctls (struct dvb_adapter *adapter,
...
@@ -673,7 +654,6 @@ dvb_add_frontend_ioctls (struct dvb_adapter *adapter,
{
{
struct
dvb_frontend_ioctl_data
*
ioctl
;
struct
dvb_frontend_ioctl_data
*
ioctl
;
struct
list_head
*
entry
;
struct
list_head
*
entry
;
int
frontend_count
=
0
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
...
@@ -706,14 +686,12 @@ dvb_add_frontend_ioctls (struct dvb_adapter *adapter,
...
@@ -706,14 +686,12 @@ dvb_add_frontend_ioctls (struct dvb_adapter *adapter,
fe
->
frontend
.
before_ioctl
=
before_ioctl
;
fe
->
frontend
.
before_ioctl
=
before_ioctl
;
fe
->
frontend
.
after_ioctl
=
after_ioctl
;
fe
->
frontend
.
after_ioctl
=
after_ioctl
;
fe
->
frontend
.
before_after_data
=
before_after_data
;
fe
->
frontend
.
before_after_data
=
before_after_data
;
dvb_frontend_start
(
fe
);
frontend_count
++
;
}
}
}
}
up
(
&
frontend_mutex
);
up
(
&
frontend_mutex
);
return
frontend_count
;
return
0
;
}
}
...
@@ -724,12 +702,11 @@ dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
...
@@ -724,12 +702,11 @@ dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
int
(
*
after_ioctl
)
(
struct
dvb_frontend
*
frontend
,
int
(
*
after_ioctl
)
(
struct
dvb_frontend
*
frontend
,
unsigned
int
cmd
,
void
*
arg
))
unsigned
int
cmd
,
void
*
arg
))
{
{
struct
list_head
*
entry
;
struct
list_head
*
entry
,
*
n
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
down_interruptible
(
&
frontend_mutex
))
down
(
&
frontend_mutex
);
return
;
list_for_each
(
entry
,
&
frontend_list
)
{
list_for_each
(
entry
,
&
frontend_list
)
{
struct
dvb_frontend_data
*
fe
;
struct
dvb_frontend_data
*
fe
;
...
@@ -746,6 +723,22 @@ dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
...
@@ -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
);
up
(
&
frontend_mutex
);
}
}
...
@@ -755,41 +748,43 @@ dvb_add_frontend_notifier (struct dvb_adapter *adapter,
...
@@ -755,41 +748,43 @@ dvb_add_frontend_notifier (struct dvb_adapter *adapter,
void
(
*
callback
)
(
fe_status_t
s
,
void
*
data
),
void
(
*
callback
)
(
fe_status_t
s
,
void
*
data
),
void
*
data
)
void
*
data
)
{
{
struct
list_head
*
entry
;
struct
dvb_frontend_notifier_data
*
notifier
;
struct
list_head
*
entry
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
down_interruptible
(
&
frontend_mutex
))
if
(
down_interruptible
(
&
frontend_mutex
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
list_for_each
(
entry
,
&
frontend_list
)
{
notifier
=
kmalloc
(
sizeof
(
struct
dvb_frontend_notifier_data
),
GFP_KERNEL
);
struct
dvb_frontend_data
*
fe
;
fe
=
list_entry
(
entry
,
struct
dvb_frontend_data
,
list_head
);
if
(
!
notifier
)
{
up
(
&
frontend_mutex
);
return
-
ENOMEM
;
}
if
(
fe
->
frontend
.
i2c
->
adapter
==
adapter
)
{
notifier
->
adapter
=
adapter
;
struct
dvb_fe_notifier_callbacks
*
e
;
notifier
->
callback
=
callback
;
notifier
->
data
=
data
;
e
=
kmalloc
(
sizeof
(
struct
dvb_fe_notifier_callbacks
),
list_add_tail
(
&
notifier
->
list_head
,
&
frontend_notifier_list
);
GFP_KERNEL
);
if
(
!
e
)
{
list_for_each
(
entry
,
&
frontend_list
)
{
up
(
&
frontend_mutex
);
struct
dvb_frontend_data
*
fe
;
return
-
ENOMEM
;
}
e
->
callback
=
callback
;
fe
=
list_entry
(
entry
,
struct
dvb_frontend_data
,
list_head
);
e
->
data
=
data
;
list_add_tail
(
&
e
->
list_head
,
&
fe
->
notifier_callbacks
);
up
(
&
frontend_mutex
);
if
(
fe
->
frontend
.
i2c
->
adapter
==
adapter
&&
return
0
;
fe
->
frontend
.
notifier_callback
==
NULL
)
{
fe
->
frontend
.
notifier_callback
=
callback
;
fe
->
frontend
.
notifier_data
=
data
;
}
}
}
}
up
(
&
frontend_mutex
);
up
(
&
frontend_mutex
);
return
-
ENODEV
;
return
0
;
}
}
...
@@ -797,30 +792,37 @@ void
...
@@ -797,30 +792,37 @@ void
dvb_remove_frontend_notifier
(
struct
dvb_adapter
*
adapter
,
dvb_remove_frontend_notifier
(
struct
dvb_adapter
*
adapter
,
void
(
*
callback
)
(
fe_status_t
s
,
void
*
data
))
void
(
*
callback
)
(
fe_status_t
s
,
void
*
data
))
{
{
struct
list_head
*
entry
;
struct
list_head
*
entry
,
*
n
;
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
down_interruptible
(
&
frontend_mutex
))
down
(
&
frontend_mutex
);
return
;
list_for_each
(
entry
,
&
frontend_list
)
{
list_for_each
(
entry
,
&
frontend_list
)
{
struct
dvb_frontend_data
*
fe
;
struct
dvb_frontend_data
*
fe
;
fe
=
list_entry
(
entry
,
struct
dvb_frontend_data
,
list_head
);
fe
=
list_entry
(
entry
,
struct
dvb_frontend_data
,
list_head
);
if
(
fe
->
frontend
.
i2c
->
adapter
==
adapter
)
{
if
(
fe
->
frontend
.
i2c
->
adapter
==
adapter
&&
struct
list_head
*
e0
,
*
n0
;
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
,
list_for_each_safe
(
entry
,
n
,
&
frontend_notifier_list
)
{
struct
dvb_fe_notifier_callbacks
,
struct
dvb_frontend_notifier_data
*
notifier
;
list_head
);
list_del
(
&
e
->
list_head
);
notifier
=
list_entry
(
entry
,
struct
dvb_frontend_notifier_data
,
list_head
);
kfree
(
e
);
}
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,
...
@@ -849,7 +851,7 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
struct
list_head
*
entry
;
struct
list_head
*
entry
;
struct
dvb_frontend_data
*
fe
;
struct
dvb_frontend_data
*
fe
;
static
const
struct
dvb_device
dvbdev_template
=
{
static
const
struct
dvb_device
dvbdev_template
=
{
.
users
=
1
,
.
users
=
~
0
,
.
writers
=
1
,
.
writers
=
1
,
.
fops
=
&
dvb_frontend_fops
,
.
fops
=
&
dvb_frontend_fops
,
.
kernel_ioctl
=
dvb_frontend_ioctl
.
kernel_ioctl
=
dvb_frontend_ioctl
...
@@ -873,7 +875,6 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
...
@@ -873,7 +875,6 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
init_MUTEX
(
&
fe
->
events
.
sem
);
init_MUTEX
(
&
fe
->
events
.
sem
);
fe
->
events
.
eventw
=
fe
->
events
.
eventr
=
0
;
fe
->
events
.
eventw
=
fe
->
events
.
eventr
=
0
;
fe
->
events
.
overflow
=
0
;
fe
->
events
.
overflow
=
0
;
INIT_LIST_HEAD
(
&
fe
->
notifier_callbacks
);
fe
->
frontend
.
ioctl
=
ioctl
;
fe
->
frontend
.
ioctl
=
ioctl
;
fe
->
frontend
.
i2c
=
i2c
;
fe
->
frontend
.
i2c
=
i2c
;
...
@@ -891,13 +892,30 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
...
@@ -891,13 +892,30 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
fe
->
frontend
.
before_ioctl
=
ioctl
->
before_ioctl
;
fe
->
frontend
.
before_ioctl
=
ioctl
->
before_ioctl
;
fe
->
frontend
.
after_ioctl
=
ioctl
->
after_ioctl
;
fe
->
frontend
.
after_ioctl
=
ioctl
->
after_ioctl
;
fe
->
frontend
.
before_after_data
=
ioctl
->
before_after_data
;
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
;
break
;
}
}
}
}
list_add_tail
(
&
fe
->
list_head
,
&
frontend_list
);
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
,
dvb_register_device
(
i2c
->
adapter
,
&
fe
->
dvbdev
,
&
dvbdev_template
,
fe
,
DVB_DEVICE_FRONTEND
);
fe
,
DVB_DEVICE_FRONTEND
);
...
@@ -915,8 +933,7 @@ int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend,
...
@@ -915,8 +933,7 @@ int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend,
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
(
down_interruptible
(
&
frontend_mutex
))
down
(
&
frontend_mutex
);
return
-
ERESTARTSYS
;
list_for_each_safe
(
entry
,
n
,
&
frontend_list
)
{
list_for_each_safe
(
entry
,
n
,
&
frontend_list
)
{
struct
dvb_frontend_data
*
fe
;
struct
dvb_frontend_data
*
fe
;
...
@@ -925,10 +942,8 @@ int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend,
...
@@ -925,10 +942,8 @@ int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend,
if
(
fe
->
frontend
.
ioctl
==
ioctl
&&
fe
->
frontend
.
i2c
==
i2c
)
{
if
(
fe
->
frontend
.
ioctl
==
ioctl
&&
fe
->
frontend
.
i2c
==
i2c
)
{
dvb_unregister_device
(
fe
->
dvbdev
);
dvb_unregister_device
(
fe
->
dvbdev
);
list_del
(
entry
);
list_del
(
entry
);
up
(
&
frontend_mutex
);
up
(
&
frontend_mutex
);
dvb_frontend_stop
(
fe
);
dvb_frontend_stop
(
fe
);
kfree
(
fe
);
kfree
(
fe
);
return
0
;
return
0
;
...
...
drivers/media/dvb/dvb-core/dvb_frontend.h
View file @
28003225
...
@@ -52,8 +52,10 @@ struct dvb_frontend {
...
@@ -52,8 +52,10 @@ struct dvb_frontend {
int
(
*
before_ioctl
)
(
struct
dvb_frontend
*
frontend
,
unsigned
int
cmd
,
void
*
arg
);
int
(
*
before_ioctl
)
(
struct
dvb_frontend
*
frontend
,
unsigned
int
cmd
,
void
*
arg
);
int
(
*
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
);
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
;
struct
dvb_i2c_bus
*
i2c
;
void
*
before_after_data
;
/* can be used by hardware module... */
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... */
void
*
data
;
/* can be used by hardware module... */
};
};
...
...
drivers/media/dvb/dvb-core/dvb_i2c.c
View file @
28003225
...
@@ -22,10 +22,13 @@
...
@@ -22,10 +22,13 @@
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/version.h>
#include "compat.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#include "dvb_i2c.h"
#include "compat.h"
#endif
#include "dvb_i2c.h"
struct
dvb_i2c_device
{
struct
dvb_i2c_device
{
struct
list_head
list_head
;
struct
list_head
list_head
;
...
@@ -34,13 +37,11 @@ struct dvb_i2c_device {
...
@@ -34,13 +37,11 @@ struct dvb_i2c_device {
void
(
*
detach
)
(
struct
dvb_i2c_bus
*
i2c
);
void
(
*
detach
)
(
struct
dvb_i2c_bus
*
i2c
);
};
};
LIST_HEAD
(
dvb_i2c_buslist
);
LIST_HEAD
(
dvb_i2c_buslist
);
LIST_HEAD
(
dvb_i2c_devicelist
);
LIST_HEAD
(
dvb_i2c_devicelist
);
DECLARE_MUTEX
(
dvb_i2c_mutex
);
DECLARE_MUTEX
(
dvb_i2c_mutex
);
static
static
int
register_i2c_client
(
struct
dvb_i2c_bus
*
i2c
,
struct
dvb_i2c_device
*
dev
)
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)
...
@@ -63,11 +64,16 @@ int register_i2c_client (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
static
static
void
try_attach_device
(
struct
dvb_i2c_bus
*
i2c
,
struct
dvb_i2c_device
*
dev
)
void
try_attach_device
(
struct
dvb_i2c_bus
*
i2c
,
struct
dvb_i2c_device
*
dev
)
{
{
if
(
try_module_get
(
dev
->
owner
))
{
if
(
dev
->
owner
)
{
if
(
dev
->
attach
(
i2c
)
==
0
)
if
(
!
try_module_get
(
dev
->
owner
))
register_i2c_client
(
i2c
,
dev
);
return
;
else
}
module_put
(
dev
->
owner
);
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)
...
@@ -75,8 +81,10 @@ void try_attach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
static
static
void
detach_device
(
struct
dvb_i2c_bus
*
i2c
,
struct
dvb_i2c_device
*
dev
)
void
detach_device
(
struct
dvb_i2c_bus
*
i2c
,
struct
dvb_i2c_device
*
dev
)
{
{
dev
->
detach
(
i2c
);
dev
->
detach
(
i2c
);
module_put
(
dev
->
owner
);
if
(
dev
->
owner
)
module_put
(
dev
->
owner
);
}
}
...
@@ -84,15 +92,17 @@ static
...
@@ -84,15 +92,17 @@ static
void
unregister_i2c_client_from_bus
(
struct
dvb_i2c_device
*
dev
,
void
unregister_i2c_client_from_bus
(
struct
dvb_i2c_device
*
dev
,
struct
dvb_i2c_bus
*
i2c
)
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
;
struct
dvb_i2c_device
*
client
;
client
=
list_entry
(
entry
,
struct
dvb_i2c_device
,
list_head
);
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
);
detach_device
(
i2c
,
dev
);
}
}
}
}
}
...
@@ -100,9 +110,9 @@ void unregister_i2c_client_from_bus (struct dvb_i2c_device *dev,
...
@@ -100,9 +110,9 @@ void unregister_i2c_client_from_bus (struct dvb_i2c_device *dev,
static
static
void
unregister_i2c_client_from_all_busses
(
struct
dvb_i2c_device
*
dev
)
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
;
struct
dvb_i2c_bus
*
i2c
;
i2c
=
list_entry
(
entry
,
struct
dvb_i2c_bus
,
list_head
);
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)
...
@@ -118,18 +128,15 @@ void unregister_all_clients_from_bus (struct dvb_i2c_bus *i2c)
struct
list_head
*
entry
,
*
n
;
struct
list_head
*
entry
,
*
n
;
list_for_each_safe
(
entry
,
n
,
&
(
i2c
->
client_list
))
{
list_for_each_safe
(
entry
,
n
,
&
(
i2c
->
client_list
))
{
struct
dvb_i2c_device
*
client
;
struct
dvb_i2c_device
*
dev
;
client
=
list_entry
(
entry
,
struct
dvb_i2c_device
,
list_head
);
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
static
void
probe_device_on_all_busses
(
struct
dvb_i2c_device
*
dev
)
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)
...
@@ -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
*
struct
dvb_i2c_bus
*
dvb_register_i2c_bus
(
int
(
*
xfer
)
(
struct
dvb_i2c_bus
*
i2c
,
dvb_register_i2c_bus
(
int
(
*
xfer
)
(
struct
dvb_i2c_bus
*
i2c
,
struct
i2c_msg
msgs
[],
int
num
),
const
struct
i2c_msg
*
msgs
,
int
num
),
void
*
data
,
void
*
data
,
struct
dvb_adapter
*
adapter
,
int
id
)
struct
dvb_adapter
*
adapter
,
int
id
)
{
{
struct
dvb_i2c_bus
*
i2c
;
struct
dvb_i2c_bus
*
i2c
;
if
(
down_interruptible
(
&
dvb_i2c_mutex
))
return
NULL
;
if
(
!
(
i2c
=
kmalloc
(
sizeof
(
struct
dvb_i2c_bus
),
GFP_KERNEL
)))
if
(
!
(
i2c
=
kmalloc
(
sizeof
(
struct
dvb_i2c_bus
),
GFP_KERNEL
)))
return
NULL
;
return
NULL
;
...
@@ -184,54 +214,27 @@ dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
...
@@ -184,54 +214,27 @@ dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
list_add_tail
(
&
i2c
->
list_head
,
&
dvb_i2c_buslist
);
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
);
up
(
&
dvb_i2c_mutex
);
return
NULL
;
return
i2c
;
}
}
void
dvb_unregister_i2c_bus
(
int
(
*
xfer
)
(
struct
dvb_i2c_bus
*
i2c
,
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
,
struct
dvb_adapter
*
adapter
,
int
id
)
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
);
unregister_all_clients_from_bus
(
i2c
);
list_del
(
&
i2c
->
list_head
);
list_del
(
&
i2c
->
list_head
);
kfree
(
i2c
);
kfree
(
i2c
);
}
}
up
(
&
dvb_i2c_mutex
);
}
}
...
@@ -267,8 +270,7 @@ int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c))
...
@@ -267,8 +270,7 @@ int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c))
{
{
struct
list_head
*
entry
,
*
n
;
struct
list_head
*
entry
,
*
n
;
if
(
down_interruptible
(
&
dvb_i2c_mutex
))
down
(
&
dvb_i2c_mutex
);
return
-
ERESTARTSYS
;
list_for_each_safe
(
entry
,
n
,
&
dvb_i2c_devicelist
)
{
list_for_each_safe
(
entry
,
n
,
&
dvb_i2c_devicelist
)
{
struct
dvb_i2c_device
*
dev
;
struct
dvb_i2c_device
*
dev
;
...
...
drivers/media/dvb/dvb-core/dvb_i2c.h
View file @
28003225
...
@@ -30,7 +30,9 @@
...
@@ -30,7 +30,9 @@
struct
dvb_i2c_bus
{
struct
dvb_i2c_bus
{
struct
list_head
list_head
;
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
;
void
*
data
;
struct
dvb_adapter
*
adapter
;
struct
dvb_adapter
*
adapter
;
int
id
;
int
id
;
...
@@ -38,17 +40,16 @@ struct dvb_i2c_bus {
...
@@ -38,17 +40,16 @@ struct dvb_i2c_bus {
};
};
extern
extern
struct
dvb_i2c_bus
*
struct
dvb_i2c_bus
*
dvb_register_i2c_bus
(
int
(
*
xfer
)
(
struct
dvb_i2c_bus
*
i2c
,
dvb_register_i2c_bus
(
int
(
*
xfer
)
(
struct
dvb_i2c_bus
*
i2c
,
struct
i2c_msg
msgs
[],
const
struct
i2c_msg
*
msgs
,
int
num
),
int
num
),
void
*
data
,
void
*
data
,
struct
dvb_adapter
*
adapter
,
struct
dvb_adapter
*
adapter
,
int
id
);
int
id
);
extern
extern
void
dvb_unregister_i2c_bus
(
int
(
*
xfer
)
(
struct
dvb_i2c_bus
*
i2c
,
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
,
struct
dvb_adapter
*
adapter
,
int
id
);
int
id
);
...
...
drivers/media/dvb/dvb-core/dvb_ksyms.c
View file @
28003225
...
@@ -8,6 +8,69 @@
...
@@ -8,6 +8,69 @@
#include "dvb_demux.h"
#include "dvb_demux.h"
#include "dvb_net.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_init
);
EXPORT_SYMBOL
(
dvb_dmxdev_release
);
EXPORT_SYMBOL
(
dvb_dmxdev_release
);
...
@@ -15,6 +78,7 @@ EXPORT_SYMBOL(dvb_dmx_init);
...
@@ -15,6 +78,7 @@ EXPORT_SYMBOL(dvb_dmx_init);
EXPORT_SYMBOL
(
dvb_dmx_release
);
EXPORT_SYMBOL
(
dvb_dmx_release
);
EXPORT_SYMBOL
(
dvb_dmx_swfilter_packet
);
EXPORT_SYMBOL
(
dvb_dmx_swfilter_packet
);
EXPORT_SYMBOL
(
dvb_dmx_swfilter_packets
);
EXPORT_SYMBOL
(
dvb_dmx_swfilter_packets
);
EXPORT_SYMBOL
(
dvb_dmx_swfilter
);
EXPORT_SYMBOL
(
dvb_register_frontend
);
EXPORT_SYMBOL
(
dvb_register_frontend
);
EXPORT_SYMBOL
(
dvb_unregister_frontend
);
EXPORT_SYMBOL
(
dvb_unregister_frontend
);
...
@@ -39,11 +103,7 @@ EXPORT_SYMBOL(dvb_generic_ioctl);
...
@@ -39,11 +103,7 @@ EXPORT_SYMBOL(dvb_generic_ioctl);
EXPORT_SYMBOL
(
dvb_generic_open
);
EXPORT_SYMBOL
(
dvb_generic_open
);
EXPORT_SYMBOL
(
dvb_generic_release
);
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_init
);
EXPORT_SYMBOL
(
dvb_filter_pes2ts
);
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 @@
...
@@ -3,29 +3,52 @@
*
*
* Copyright (C) 2001 Convergence integrated media GmbH
* Copyright (C) 2001 Convergence integrated media GmbH
* Ralph Metzler <ralph@convergence.de>
* Ralph Metzler <ralph@convergence.de>
* Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
*
*
* This program is free software; you can redistribute it and/or
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU
Lesser
General Public License
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
.1
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* of the License, or (at your option) any later version.
*
*
*
* This program is distributed in the hope that it will be useful,
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* 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
* 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 <asm/uaccess.h>
#include "demux.h"
#include <linux/dvb/net.h>
#include "dvb_demux.h"
#include "dvb_net.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
* 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.
* 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)
...
@@ -73,7 +96,7 @@ unsigned short my_eth_type_trans(struct sk_buff *skb, struct net_device *dev)
}
}
static
void
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
;
u8
*
eth
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
...
@@ -86,7 +109,7 @@ dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
...
@@ -86,7 +109,7 @@ dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
if
(
skb
==
NULL
)
{
if
(
skb
==
NULL
)
{
printk
(
KERN_NOTICE
"%s: Memory squeeze, dropping packet.
\n
"
,
printk
(
KERN_NOTICE
"%s: Memory squeeze, dropping packet.
\n
"
,
dev
->
name
);
dev
->
name
);
((
dvb_net_priv_t
*
)
dev
->
priv
)
->
stats
.
rx_dropped
++
;
((
struct
dvb_net_priv
*
)
dev
->
priv
)
->
stats
.
rx_dropped
++
;
return
;
return
;
}
}
eth
=
(
u8
*
)
skb_put
(
skb
,
pkt_len
+
2
);
eth
=
(
u8
*
)
skb_put
(
skb
,
pkt_len
+
2
);
...
@@ -104,15 +127,14 @@ dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
...
@@ -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
->
protocol
=
my_eth_type_trans
(
skb
,
dev
);
skb
->
dev
=
dev
;
skb
->
dev
=
dev
;
((
dvb_net_priv_t
*
)
dev
->
priv
)
->
stats
.
rx_packets
++
;
((
struct
dvb_net_priv
*
)
dev
->
priv
)
->
stats
.
rx_packets
++
;
((
dvb_net_priv_t
*
)
dev
->
priv
)
->
stats
.
rx_bytes
+=
skb
->
len
;
((
struct
dvb_net_priv
*
)
dev
->
priv
)
->
stats
.
rx_bytes
+=
skb
->
len
;
//sti();
netif_rx
(
skb
);
netif_rx
(
skb
);
}
}
static
int
static
int
dvb_net_callback
(
u8
*
buffer1
,
size_t
buffer1_len
,
dvb_net_callback
(
const
u8
*
buffer1
,
size_t
buffer1_len
,
u8
*
buffer2
,
size_t
buffer2_len
,
const
u8
*
buffer2
,
size_t
buffer2_len
,
dmx_section_filter_t
*
filter
,
dmx_section_filter_t
*
filter
,
dmx_success_t
success
)
dmx_success_t
success
)
{
{
...
@@ -130,18 +152,21 @@ dvb_net_tx(struct sk_buff *skb, struct net_device *dev)
...
@@ -130,18 +152,21 @@ dvb_net_tx(struct sk_buff *skb, struct net_device *dev)
return
0
;
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
static
int
dvb_net_filter_set
(
struct
net_device
*
dev
,
dvb_net_filter_set
(
struct
net_device
*
dev
,
dmx_section_filter_t
**
secfilter
,
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
;
int
ret
;
*
secfilter
=
0
;
*
secfilter
=
0
;
ret
=
priv
->
secfeed
->
allocate_filter
(
priv
->
secfeed
,
secfilter
);
ret
=
priv
->
secfeed
->
allocate_filter
(
priv
->
secfeed
,
secfilter
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
printk
(
"%s: could not get filter
\n
"
,
dev
->
name
);
printk
(
"%s: could not get filter
\n
"
,
dev
->
name
);
return
ret
;
return
ret
;
...
@@ -149,25 +174,26 @@ dvb_net_filter_set(struct net_device *dev,
...
@@ -149,25 +174,26 @@ dvb_net_filter_set(struct net_device *dev,
(
*
secfilter
)
->
priv
=
(
void
*
)
dev
;
(
*
secfilter
)
->
priv
=
(
void
*
)
dev
;
memset
((
*
secfilter
)
->
filter_value
,
0
,
DMX_MAX_FILTER_SIZE
);
memset
((
*
secfilter
)
->
filter_value
,
0x00
,
DMX_MAX_FILTER_SIZE
);
memset
((
*
secfilter
)
->
filter_mask
,
0
,
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_value
[
0
]
=
0x3e
;
(
*
secfilter
)
->
filter_mask
[
0
]
=
MASK
;
(
*
secfilter
)
->
filter_mask
[
0
]
=
0xff
;
(
*
secfilter
)
->
filter_value
[
3
]
=
mac
[
5
];
(
*
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_value
[
4
]
=
mac
[
4
];
(
*
secfilter
)
->
filter_mask
[
4
]
=
MASK
;
(
*
secfilter
)
->
filter_mask
[
4
]
=
mac_mask
[
4
]
;
(
*
secfilter
)
->
filter_value
[
8
]
=
mac
[
3
];
(
*
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_value
[
9
]
=
mac
[
2
];
(
*
secfilter
)
->
filter_mask
[
9
]
=
MASK
;
(
*
secfilter
)
->
filter_mask
[
9
]
=
mac_mask
[
2
]
;
(
*
secfilter
)
->
filter_value
[
10
]
=
mac
[
1
];
(
*
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_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
"
,
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
]);
dev
->
name
,
mac
[
0
],
mac
[
1
],
mac
[
2
],
mac
[
3
],
mac
[
4
],
mac
[
5
]);
...
@@ -178,9 +204,9 @@ static int
...
@@ -178,9 +204,9 @@ static int
dvb_net_feed_start
(
struct
net_device
*
dev
)
dvb_net_feed_start
(
struct
net_device
*
dev
)
{
{
int
ret
,
i
;
int
ret
,
i
;
dvb_net_priv_t
*
priv
=
(
dvb_net_priv_t
*
)
dev
->
priv
;
struct
dvb_net_priv
*
priv
=
(
struct
dvb_net_priv
*
)
dev
->
priv
;
dmx_demux_t
*
demux
=
priv
->
demux
;
dmx_demux_t
*
demux
=
priv
->
demux
;
unsigned
char
*
mac
=
(
unsigned
char
*
)
dev
->
dev_addr
;
unsigned
char
*
mac
=
(
unsigned
char
*
)
dev
->
dev_addr
;
priv
->
secfeed
=
0
;
priv
->
secfeed
=
0
;
priv
->
secfilter
=
0
;
priv
->
secfilter
=
0
;
...
@@ -200,28 +226,41 @@ dvb_net_feed_start(struct net_device *dev)
...
@@ -200,28 +226,41 @@ dvb_net_feed_start(struct net_device *dev)
priv
->
secfeed
=
0
;
priv
->
secfeed
=
0
;
return
ret
;
return
ret
;
}
}
MOD_INC_USE_COUNT
;
/* fixme: is this correct? */
try_module_get
(
THIS_MODULE
);
dvb_net_filter_set
(
dev
,
&
priv
->
secfilter
,
mac
);
if
(
priv
->
mode
<
3
)
for
(
i
=
0
;
i
<
priv
->
multi_num
;
i
++
)
dvb_net_filter_set
(
dev
,
&
priv
->
secfilter
,
mac
,
mask_normal
);
dvb_net_filter_set
(
dev
,
&
priv
->
secfilter
,
priv
->
multi_macs
[
i
]);
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
);
priv
->
secfeed
->
start_filtering
(
priv
->
secfeed
);
printk
(
"%s: feed_started
\n
"
,
dev
->
name
);
return
0
;
return
0
;
}
}
static
void
static
void
dvb_net_feed_stop
(
struct
net_device
*
dev
)
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
;
int
i
;
if
(
priv
->
secfeed
)
{
if
(
priv
->
secfeed
)
{
if
(
priv
->
secfeed
->
is_filtering
)
if
(
priv
->
secfeed
->
is_filtering
)
priv
->
secfeed
->
stop_filtering
(
priv
->
secfeed
);
priv
->
secfeed
->
stop_filtering
(
priv
->
secfeed
);
printk
(
"%s: feed_stopped
\n
"
,
dev
->
name
);
if
(
priv
->
secfilter
)
if
(
priv
->
secfilter
)
priv
->
secfeed
->
priv
->
secfeed
->
release_filter
(
priv
->
secfeed
,
release_filter
(
priv
->
secfeed
,
...
@@ -238,62 +277,70 @@ dvb_net_feed_stop(struct net_device *dev)
...
@@ -238,62 +277,70 @@ dvb_net_feed_stop(struct net_device *dev)
priv
->
demux
->
priv
->
demux
->
release_section_feed
(
priv
->
demux
,
priv
->
secfeed
);
release_section_feed
(
priv
->
demux
,
priv
->
secfeed
);
priv
->
secfeed
=
0
;
priv
->
secfeed
=
0
;
MOD_DEC_USE_COUNT
;
/* fixme: is this correct? */
module_put
(
THIS_MODULE
);
}
else
}
else
printk
(
"%s: no feed to stop
\n
"
,
dev
->
name
);
printk
(
"%s: no feed to stop
\n
"
,
dev
->
name
);
}
}
static
int
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
;
return
-
ENOMEM
;
printk
(
"%s: set_mc_filter %d: %02x %02x %02x %02x %02x %02x
\n
"
,
ret
=
memcmp
(
priv
->
multi_macs
[
priv
->
multi_num
],
mc
->
dmi_addr
,
6
);
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
]);
memcpy
(
priv
->
multi_macs
[
priv
->
multi_num
],
mc
->
dmi_addr
,
6
);
memcpy
(
priv
->
multi_macs
[
priv
->
multi_num
],
mc
->
dmi_addr
,
6
);
priv
->
multi_num
++
;
priv
->
multi_num
++
;
return
0
;
return
ret
;
}
}
static
void
static
void
dvb_net_set_multi
(
struct
net_device
*
dev
)
dvb_net_set_multi
(
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
;
struct
dev_mc_list
*
mc
;
printk
(
"%s: set_multi()
\n
"
,
dev
->
name
);
int
mci
;
dvb_net_feed_stop
(
dev
);
int
update
=
0
;
if
(
dev
->
flags
&
IFF_PROMISC
)
{
if
(
dev
->
flags
&
IFF_PROMISC
)
{
/* Enable promiscuous mode */
// printk("%s: promiscuous mode\n", dev->name);
printk
(
"%s: promiscuous mode
\n
"
,
dev
->
name
);
if
(
priv
->
mode
!=
3
)
}
else
if
((
dev
->
flags
&
IFF_ALLMULTI
))
{
update
=
1
;
/* Disable promiscuous mode, use normal mode. */
priv
->
mode
=
3
;
printk
(
"%s: normal mode
\n
"
,
dev
->
name
);
}
else
if
(
dev
->
flags
&
IFF_ALLMULTI
)
{
}
else
if
(
dev
->
mc_count
)
{
// printk("%s: allmulti mode\n", dev->name);
int
mci
;
if
(
priv
->
mode
!=
2
)
struct
dev_mc_list
*
mc
;
update
=
1
;
priv
->
mode
=
2
;
printk
(
"%s: set_mc_list, %d entries
\n
"
,
}
else
if
(
dev
->
mc_count
>
0
)
{
dev
->
name
,
dev
->
mc_count
);
// printk("%s: set_mc_list, %d entries\n",
priv
->
multi_num
=
0
;
// dev->name, dev->mc_count);
for
(
mci
=
0
,
mc
=
dev
->
mc_list
;
if
(
priv
->
mode
!=
1
)
mci
<
dev
->
mc_count
;
update
=
1
;
mc
=
mc
->
next
,
mci
++
)
{
priv
->
mode
=
1
;
dvb_set_mc_filter
(
dev
,
mc
);
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
static
int
...
@@ -308,13 +355,15 @@ static int
...
@@ -308,13 +355,15 @@ static int
dvb_net_set_mac
(
struct
net_device
*
dev
,
void
*
p
)
dvb_net_set_mac
(
struct
net_device
*
dev
,
void
*
p
)
{
{
struct
sockaddr
*
addr
=
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
);
memcpy
(
dev
->
dev_addr
,
addr
->
sa_data
,
dev
->
addr_len
);
if
(
netif_running
(
dev
))
{
if
(
netif_running
(
dev
)
!=
0
&&
update
>
0
)
{
dvb_net_feed_stop
(
dev
);
dvb_net_feed_stop
(
dev
);
dvb_net_feed_start
(
dev
);
dvb_net_feed_start
(
dev
);
}
}
return
0
;
return
0
;
}
}
...
@@ -335,15 +384,13 @@ dvb_net_stop(struct net_device *dev)
...
@@ -335,15 +384,13 @@ dvb_net_stop(struct net_device *dev)
static
struct
net_device_stats
*
static
struct
net_device_stats
*
dvb_net_get_stats
(
struct
net_device
*
dev
)
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
static
int
dvb_net_init_dev
(
struct
net_device
*
dev
)
dvb_net_init_dev
(
struct
net_device
*
dev
)
{
{
printk
(
"dvb_net: dvb_net_init_dev()
\n
"
);
ether_setup
(
dev
);
ether_setup
(
dev
);
dev
->
open
=
dvb_net_open
;
dev
->
open
=
dvb_net_open
;
...
@@ -354,6 +401,7 @@ dvb_net_init_dev(struct net_device *dev)
...
@@ -354,6 +401,7 @@ dvb_net_init_dev(struct net_device *dev)
dev
->
set_config
=
dvb_net_set_config
;
dev
->
set_config
=
dvb_net_set_config
;
dev
->
set_mac_address
=
dvb_net_set_mac
;
dev
->
set_mac_address
=
dvb_net_set_mac
;
dev
->
mtu
=
4096
;
dev
->
mtu
=
4096
;
dev
->
mc_count
=
0
;
dev
->
flags
|=
IFF_NOARP
;
dev
->
flags
|=
IFF_NOARP
;
dev
->
hard_header_cache
=
NULL
;
dev
->
hard_header_cache
=
NULL
;
...
@@ -364,7 +412,7 @@ dvb_net_init_dev(struct net_device *dev)
...
@@ -364,7 +412,7 @@ dvb_net_init_dev(struct net_device *dev)
}
}
static
int
static
int
get_if
(
dvb_net_
t
*
dvbnet
)
get_if
(
struct
dvb_ne
t
*
dvbnet
)
{
{
int
i
;
int
i
;
...
@@ -379,10 +427,11 @@ get_if(dvb_net_t *dvbnet)
...
@@ -379,10 +427,11 @@ get_if(dvb_net_t *dvbnet)
int
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
;
struct
net_device
*
net
;
dmx_demux_t
*
demux
;
dmx_demux_t
*
demux
;
struct
dvb_net_priv
*
priv
;
int
result
;
int
result
;
int
if_num
;
int
if_num
;
...
@@ -402,25 +451,29 @@ dvb_net_add_if(dvb_net_t *dvbnet, u16 pid)
...
@@ -402,25 +451,29 @@ dvb_net_add_if(dvb_net_t *dvbnet, u16 pid)
net
->
name
[
5
]
=
if_num
+
0x30
;
net
->
name
[
5
]
=
if_num
+
0x30
;
net
->
next
=
NULL
;
net
->
next
=
NULL
;
net
->
init
=
dvb_net_init_dev
;
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
)
if
(
net
->
priv
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
memset
(
net
->
priv
,
0
,
sizeof
(
dvb_net_priv_t
));
((
dvb_net_priv_t
*
)
net
->
priv
)
->
demux
=
demux
;
priv
=
net
->
priv
;
((
dvb_net_priv_t
*
)
net
->
priv
)
->
pid
=
pid
;
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
)
{
if
((
result
=
register_netdev
(
net
))
<
0
)
{
return
result
;
return
result
;
}
}
MOD_INC_USE_COUNT
;
/* fixme: is this correct? */
try_module_get
(
THIS_MODULE
);
return
if_num
;
return
if_num
;
}
}
int
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
])
if
(
!
dvbnet
->
state
[
num
])
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -428,15 +481,17 @@ dvb_net_remove_if(dvb_net_t *dvbnet, int num)
...
@@ -428,15 +481,17 @@ dvb_net_remove_if(dvb_net_t *dvbnet, int num)
kfree
(
dvbnet
->
device
[
num
].
priv
);
kfree
(
dvbnet
->
device
[
num
].
priv
);
unregister_netdev
(
&
dvbnet
->
device
[
num
]);
unregister_netdev
(
&
dvbnet
->
device
[
num
]);
dvbnet
->
state
[
num
]
=
0
;
dvbnet
->
state
[
num
]
=
0
;
MOD_DEC_USE_COUNT
;
/* fixme: is this correct? */
module_put
(
THIS_MODULE
);
return
0
;
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
)
unsigned
int
cmd
,
void
*
parg
)
{
{
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
struct
dvb_device
*
dvbdev
=
(
struct
dvb_device
*
)
file
->
private_data
;
dvb_net_t
*
dvbnet
=
(
dvb_net_
t
*
)
dvbdev
->
priv
;
struct
dvb_net
*
dvbnet
=
(
struct
dvb_ne
t
*
)
dvbdev
->
priv
;
if
(((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDONLY
))
if
(((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDONLY
))
return
-
EPERM
;
return
-
EPERM
;
...
@@ -453,6 +508,21 @@ int dvb_net_ioctl(struct inode *inode, struct file *file,
...
@@ -453,6 +508,21 @@ int dvb_net_ioctl(struct inode *inode, struct file *file,
dvbnetif
->
if_num
=
result
;
dvbnetif
->
if_num
=
result
;
break
;
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
:
case
NET_REMOVE_IF
:
return
dvb_net_remove_if
(
dvbnet
,
(
int
)
parg
);
return
dvb_net_remove_if
(
dvbnet
,
(
int
)
parg
);
default:
default:
...
@@ -461,23 +531,32 @@ int dvb_net_ioctl(struct inode *inode, struct file *file,
...
@@ -461,23 +531,32 @@ int dvb_net_ioctl(struct inode *inode, struct file *file,
return
0
;
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
=
{
static
struct
file_operations
dvb_net_fops
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
ioctl
=
dvb_generic_ioctl
,
.
read
=
0
,
.
open
=
dvb_generic_open
,
.
write
=
0
,
.
release
=
dvb_generic_release
,
.
ioctl
=
dvb_net_ioctl
,
.
open
=
dvb_generic_open
,
.
release
=
dvb_generic_release
,
.
poll
=
0
,
};
};
static
struct
dvb_device
dvbdev_net
=
{
static
struct
dvb_device
dvbdev_net
=
{
.
priv
=
0
,
.
priv
=
0
,
.
users
=
1
,
.
users
=
1
,
.
writers
=
1
,
.
writers
=
1
,
.
fops
=
&
dvb_net_fops
,
.
fops
=
&
dvb_net_fops
,
.
kernel_ioctl
=
dvb_net_ioctl
,
};
};
void
void
dvb_net_release
(
dvb_net_
t
*
dvbnet
)
dvb_net_release
(
struct
dvb_ne
t
*
dvbnet
)
{
{
int
i
;
int
i
;
...
@@ -490,15 +569,19 @@ dvb_net_release(dvb_net_t *dvbnet)
...
@@ -490,15 +569,19 @@ dvb_net_release(dvb_net_t *dvbnet)
}
}
int
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
;
int
i
;
dvbnet
->
demux
=
demux
;
dvbnet
->
demux
=
dmx
;
dvbnet
->
dev_num
=
DVB_NET_DEVICES_MAX
;
dvbnet
->
dev_num
=
DVB_NET_DEVICES_MAX
;
for
(
i
=
0
;
i
<
dvbnet
->
dev_num
;
i
++
)
for
(
i
=
0
;
i
<
dvbnet
->
dev_num
;
i
++
)
dvbnet
->
state
[
i
]
=
0
;
dvbnet
->
state
[
i
]
=
0
;
dvb_register_device
(
adap
,
&
dvbnet
->
dvbdev
,
&
dvbdev_net
,
dvbnet
,
DVB_DEVICE_NET
);
dvb_register_device
(
adap
,
&
dvbnet
->
dvbdev
,
&
dvbdev_net
,
dvbnet
,
DVB_DEVICE_NET
);
return
0
;
return
0
;
}
}
drivers/media/dvb/dvb-core/dvb_net.h
View file @
28003225
...
@@ -32,23 +32,9 @@
...
@@ -32,23 +32,9 @@
#include "dvbdev.h"
#include "dvbdev.h"
#define DVB_NET_DEVICES_MAX 10
#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
card_num
;
int
dev_num
;
int
dev_num
;
struct
net_device
device
[
DVB_NET_DEVICES_MAX
];
struct
net_device
device
[
DVB_NET_DEVICES_MAX
];
...
@@ -57,7 +43,8 @@ typedef struct dvb_net_s {
...
@@ -57,7 +43,8 @@ typedef struct dvb_net_s {
}
dvb_net_t
;
}
dvb_net_t
;
void
dvb_net_release
(
dvb_net_
t
*
);
void
dvb_net_release
(
struct
dvb_ne
t
*
);
int
dvb_net_init
(
struct
dvb_adapter
*
,
dvb_net_
t
*
,
dmx_demux_t
*
);
int
dvb_net_init
(
struct
dvb_adapter
*
,
struct
dvb_ne
t
*
,
dmx_demux_t
*
);
#endif
#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 @@
...
@@ -35,11 +35,13 @@
#include <asm/system.h>
#include <asm/system.h>
#include <linux/kmod.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/videodev.h>
#include "compat.h"
#include "dvbdev.h"
#include "dvbdev.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#include "compat.h"
#endif
static
int
dvbdev_debug
=
0
;
static
int
dvbdev_debug
=
0
;
#define dprintk if (dvbdev_debug) printk
#define dprintk if (dvbdev_debug) printk
...
@@ -57,7 +59,6 @@ static char *dnames[] = {
...
@@ -57,7 +59,6 @@ static char *dnames[] = {
#define DVB_MAX_IDS 4
#define DVB_MAX_IDS 4
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
static
static
struct
dvb_device
*
dvbdev_find_device
(
int
minor
)
struct
dvb_device
*
dvbdev_find_device
(
int
minor
)
{
{
...
@@ -160,7 +161,7 @@ int dvb_generic_ioctl(struct inode *inode, struct file *file,
...
@@ -160,7 +161,7 @@ int dvb_generic_ioctl(struct inode *inode, struct file *file,
if
(
!
dvbdev
->
kernel_ioctl
)
if
(
!
dvbdev
->
kernel_ioctl
)
return
-
EINVAL
;
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)
...
@@ -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
;
struct
dvb_adapter
*
adap
;
int
num
;
int
num
;
...
@@ -288,12 +289,14 @@ int dvb_register_adapter(struct dvb_adapter **padap, char *name)
...
@@ -288,12 +289,14 @@ int dvb_register_adapter(struct dvb_adapter **padap, char *name)
memset
(
adap
,
0
,
sizeof
(
struct
dvb_adapter
));
memset
(
adap
,
0
,
sizeof
(
struct
dvb_adapter
));
INIT_LIST_HEAD
(
&
adap
->
device_list
);
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
);
printk
(
"DVB: registering new adapter (%s).
\n
"
,
name
);
adap
->
devfs_handle
=
devfs_mk_dir
(
"dvb/adapter%d"
,
num
);
adap
->
devfs_handle
=
devfs_mk_dir
(
"dvb/adapter%d"
,
num
);
adap
->
num
=
num
;
adap
->
num
=
num
;
adap
->
name
=
name
;
list_add_tail
(
&
adap
->
list_head
,
&
dvb_adapter_list
);
list_add_tail
(
&
adap
->
list_head
,
&
dvb_adapter_list
);
...
@@ -311,7 +314,8 @@ int dvb_unregister_adapter(struct dvb_adapter *adap)
...
@@ -311,7 +314,8 @@ int dvb_unregister_adapter(struct dvb_adapter *adap)
list_del
(
&
adap
->
list_head
);
list_del
(
&
adap
->
list_head
);
up
(
&
dvbdev_register_lock
);
up
(
&
dvbdev_register_lock
);
kfree
(
adap
);
kfree
(
adap
);
MOD_DEC_USE_COUNT
;
/* fixme: is this correct? */
module_put
(
THIS_MODULE
);
return
0
;
return
0
;
}
}
...
...
drivers/media/dvb/dvb-core/dvbdev.h
View file @
28003225
...
@@ -48,6 +48,7 @@ struct dvb_adapter {
...
@@ -48,6 +48,7 @@ struct dvb_adapter {
devfs_handle_t
devfs_handle
;
devfs_handle_t
devfs_handle
;
struct
list_head
list_head
;
struct
list_head
list_head
;
struct
list_head
device_list
;
struct
list_head
device_list
;
const
char
*
name
;
};
};
...
@@ -63,14 +64,14 @@ struct dvb_device {
...
@@ -63,14 +64,14 @@ struct dvb_device {
int
writers
;
int
writers
;
/* don't really need those !? -- FIXME: use video_usercopy */
/* 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
);
unsigned
int
cmd
,
void
*
arg
);
void
*
priv
;
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_unregister_adapter
(
struct
dvb_adapter
*
adap
);
extern
int
dvb_register_device
(
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);
...
@@ -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_open
(
struct
inode
*
inode
,
struct
file
*
file
);
extern
int
dvb_generic_release
(
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
,
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_ */
#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