diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-06-14 15:35:53 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-13 22:08:14 -0400 |
commit | 3d6c2bc08ac4f75bf3597740357c98f2207ca412 (patch) | |
tree | dfe6d7c9e466cef06224ffadd3310d61f41a4678 /drivers/media/dvb | |
parent | 5bc3cb743bbab408792c1b4ef31adf6268aa4b7e (diff) |
[media] dvb: move the dvb core one level up
just like the V4L2 core, move the DVB core to drivers/media, as the
intention is to get rid of both "video" and "dvb" directories.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
39 files changed, 17 insertions, 12197 deletions
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 3a6ccbc02add..5a2c4bd75480 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig | |||
@@ -2,32 +2,6 @@ | |||
2 | # DVB device configuration | 2 | # DVB device configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | config DVB_MAX_ADAPTERS | ||
6 | int "maximum number of DVB/ATSC adapters" | ||
7 | depends on DVB_CORE | ||
8 | default 8 | ||
9 | range 1 255 | ||
10 | help | ||
11 | Maximum number of DVB/ATSC adapters. Increasing this number | ||
12 | increases the memory consumption of the DVB subsystem even | ||
13 | if a much lower number of DVB/ATSC adapters is present. | ||
14 | Only values in the range 4-32 are tested. | ||
15 | |||
16 | If you are unsure about this, use the default value 8 | ||
17 | |||
18 | config DVB_DYNAMIC_MINORS | ||
19 | bool "Dynamic DVB minor allocation" | ||
20 | depends on DVB_CORE | ||
21 | default n | ||
22 | help | ||
23 | If you say Y here, the DVB subsystem will use dynamic minor | ||
24 | allocation for any device that uses the DVB major number. | ||
25 | This means that you can have more than 4 of a single type | ||
26 | of device (like demuxes and frontends) per adapter, but udev | ||
27 | will be required to manage the device nodes. | ||
28 | |||
29 | If you are unsure about this, say N here. | ||
30 | |||
31 | menuconfig DVB_CAPTURE_DRIVERS | 5 | menuconfig DVB_CAPTURE_DRIVERS |
32 | bool "DVB/ATSC adapters" | 6 | bool "DVB/ATSC adapters" |
33 | depends on DVB_CORE | 7 | depends on DVB_CORE |
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index 8f7e0129d70e..b14aa9dd0156 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile | |||
@@ -2,8 +2,7 @@ | |||
2 | # Makefile for the kernel multimedia device drivers. | 2 | # Makefile for the kernel multimedia device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := dvb-core/ \ | 5 | obj-y := frontends/ \ |
6 | frontends/ \ | ||
7 | ttpci/ \ | 6 | ttpci/ \ |
8 | ttusb-dec/ \ | 7 | ttusb-dec/ \ |
9 | ttusb-budget/ \ | 8 | ttusb-budget/ \ |
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile index 3d04a8dba99e..e4291e4aba23 100644 --- a/drivers/media/dvb/b2c2/Makefile +++ b/drivers/media/dvb/b2c2/Makefile | |||
@@ -12,5 +12,5 @@ obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o | |||
12 | b2c2-flexcop-usb-objs = flexcop-usb.o | 12 | b2c2-flexcop-usb-objs = flexcop-usb.o |
13 | obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o | 13 | obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o |
14 | 14 | ||
15 | ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | 15 | ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb/frontends/ |
16 | ccflags-y += -Idrivers/media/common/tuners/ | 16 | ccflags-y += -Idrivers/media/common/tuners/ |
diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile index 0713b3af2050..7c2dd04d37e4 100644 --- a/drivers/media/dvb/bt8xx/Makefile +++ b/drivers/media/dvb/bt8xx/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o | 1 | obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o |
2 | 2 | ||
3 | ccflags-y += -Idrivers/media/dvb/dvb-core | 3 | ccflags-y += -Idrivers/media/dvb-core |
4 | ccflags-y += -Idrivers/media/dvb/frontends | 4 | ccflags-y += -Idrivers/media/dvb/frontends |
5 | ccflags-y += -Idrivers/media/video/bt8xx | 5 | ccflags-y += -Idrivers/media/video/bt8xx |
6 | ccflags-y += -Idrivers/media/common/tuners | 6 | ccflags-y += -Idrivers/media/common/tuners |
diff --git a/drivers/media/dvb/ddbridge/Makefile b/drivers/media/dvb/ddbridge/Makefile index 38019bafb862..9eca27dd7328 100644 --- a/drivers/media/dvb/ddbridge/Makefile +++ b/drivers/media/dvb/ddbridge/Makefile | |||
@@ -6,7 +6,7 @@ ddbridge-objs := ddbridge-core.o | |||
6 | 6 | ||
7 | obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o | 7 | obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o |
8 | 8 | ||
9 | ccflags-y += -Idrivers/media/dvb/dvb-core/ | 9 | ccflags-y += -Idrivers/media/dvb-core/ |
10 | ccflags-y += -Idrivers/media/dvb/frontends/ | 10 | ccflags-y += -Idrivers/media/dvb/frontends/ |
11 | ccflags-y += -Idrivers/media/common/tuners/ | 11 | ccflags-y += -Idrivers/media/common/tuners/ |
12 | 12 | ||
diff --git a/drivers/media/dvb/dm1105/Makefile b/drivers/media/dvb/dm1105/Makefile index 95a008b71fe5..0dc5963ee807 100644 --- a/drivers/media/dvb/dm1105/Makefile +++ b/drivers/media/dvb/dm1105/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | obj-$(CONFIG_DVB_DM1105) += dm1105.o | 1 | obj-$(CONFIG_DVB_DM1105) += dm1105.o |
2 | 2 | ||
3 | ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends | 3 | ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb/frontends |
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile deleted file mode 100644 index 8f22bcd7c1f9..000000000000 --- a/drivers/media/dvb/dvb-core/Makefile +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for the kernel DVB device drivers. | ||
3 | # | ||
4 | |||
5 | dvb-net-$(CONFIG_DVB_NET) := dvb_net.o | ||
6 | |||
7 | dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ | ||
8 | dvb_ca_en50221.o dvb_frontend.o \ | ||
9 | $(dvb-net-y) dvb_ringbuffer.o dvb_math.o | ||
10 | |||
11 | obj-$(CONFIG_DVB_CORE) += dvb-core.o | ||
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h deleted file mode 100644 index eb91fd808c16..000000000000 --- a/drivers/media/dvb/dvb-core/demux.h +++ /dev/null | |||
@@ -1,280 +0,0 @@ | |||
1 | /* | ||
2 | * demux.h | ||
3 | * | ||
4 | * Copyright (c) 2002 Convergence GmbH | ||
5 | * | ||
6 | * based on code: | ||
7 | * Copyright (c) 2000 Nokia Research Center | ||
8 | * Tampere, FINLAND | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU Lesser General Public License | ||
12 | * as published by the Free Software Foundation; either version 2.1 | ||
13 | * of the License, or (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Lesser General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #ifndef __DEMUX_H | ||
27 | #define __DEMUX_H | ||
28 | |||
29 | #include <linux/types.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/list.h> | ||
32 | #include <linux/time.h> | ||
33 | #include <linux/dvb/dmx.h> | ||
34 | |||
35 | /*--------------------------------------------------------------------------*/ | ||
36 | /* Common definitions */ | ||
37 | /*--------------------------------------------------------------------------*/ | ||
38 | |||
39 | /* | ||
40 | * DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter. | ||
41 | */ | ||
42 | |||
43 | #ifndef DMX_MAX_FILTER_SIZE | ||
44 | #define DMX_MAX_FILTER_SIZE 18 | ||
45 | #endif | ||
46 | |||
47 | /* | ||
48 | * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter. | ||
49 | */ | ||
50 | |||
51 | #ifndef DMX_MAX_SECTION_SIZE | ||
52 | #define DMX_MAX_SECTION_SIZE 4096 | ||
53 | #endif | ||
54 | #ifndef DMX_MAX_SECFEED_SIZE | ||
55 | #define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188) | ||
56 | #endif | ||
57 | |||
58 | |||
59 | /* | ||
60 | * enum dmx_success: Success codes for the Demux Callback API. | ||
61 | */ | ||
62 | |||
63 | enum dmx_success { | ||
64 | DMX_OK = 0, /* Received Ok */ | ||
65 | DMX_LENGTH_ERROR, /* Incorrect length */ | ||
66 | DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */ | ||
67 | DMX_CRC_ERROR, /* Incorrect CRC */ | ||
68 | DMX_FRAME_ERROR, /* Frame alignment error */ | ||
69 | DMX_FIFO_ERROR, /* Receiver FIFO overrun */ | ||
70 | DMX_MISSED_ERROR /* Receiver missed packet */ | ||
71 | } ; | ||
72 | |||
73 | /*--------------------------------------------------------------------------*/ | ||
74 | /* TS packet reception */ | ||
75 | /*--------------------------------------------------------------------------*/ | ||
76 | |||
77 | /* TS filter type for set() */ | ||
78 | |||
79 | #define TS_PACKET 1 /* send TS packets (188 bytes) to callback (default) */ | ||
80 | #define TS_PAYLOAD_ONLY 2 /* in case TS_PACKET is set, only send the TS | ||
81 | payload (<=184 bytes per packet) to callback */ | ||
82 | #define TS_DECODER 4 /* send stream to built-in decoder (if present) */ | ||
83 | #define TS_DEMUX 8 /* in case TS_PACKET is set, send the TS to | ||
84 | the demux device, not to the dvr device */ | ||
85 | |||
86 | /* PES type for filters which write to built-in decoder */ | ||
87 | /* these should be kept identical to the types in dmx.h */ | ||
88 | |||
89 | enum dmx_ts_pes | ||
90 | { /* also send packets to decoder (if it exists) */ | ||
91 | DMX_TS_PES_AUDIO0, | ||
92 | DMX_TS_PES_VIDEO0, | ||
93 | DMX_TS_PES_TELETEXT0, | ||
94 | DMX_TS_PES_SUBTITLE0, | ||
95 | DMX_TS_PES_PCR0, | ||
96 | |||
97 | DMX_TS_PES_AUDIO1, | ||
98 | DMX_TS_PES_VIDEO1, | ||
99 | DMX_TS_PES_TELETEXT1, | ||
100 | DMX_TS_PES_SUBTITLE1, | ||
101 | DMX_TS_PES_PCR1, | ||
102 | |||
103 | DMX_TS_PES_AUDIO2, | ||
104 | DMX_TS_PES_VIDEO2, | ||
105 | DMX_TS_PES_TELETEXT2, | ||
106 | DMX_TS_PES_SUBTITLE2, | ||
107 | DMX_TS_PES_PCR2, | ||
108 | |||
109 | DMX_TS_PES_AUDIO3, | ||
110 | DMX_TS_PES_VIDEO3, | ||
111 | DMX_TS_PES_TELETEXT3, | ||
112 | DMX_TS_PES_SUBTITLE3, | ||
113 | DMX_TS_PES_PCR3, | ||
114 | |||
115 | DMX_TS_PES_OTHER | ||
116 | }; | ||
117 | |||
118 | #define DMX_TS_PES_AUDIO DMX_TS_PES_AUDIO0 | ||
119 | #define DMX_TS_PES_VIDEO DMX_TS_PES_VIDEO0 | ||
120 | #define DMX_TS_PES_TELETEXT DMX_TS_PES_TELETEXT0 | ||
121 | #define DMX_TS_PES_SUBTITLE DMX_TS_PES_SUBTITLE0 | ||
122 | #define DMX_TS_PES_PCR DMX_TS_PES_PCR0 | ||
123 | |||
124 | |||
125 | struct dmx_ts_feed { | ||
126 | int is_filtering; /* Set to non-zero when filtering in progress */ | ||
127 | struct dmx_demux *parent; /* Back-pointer */ | ||
128 | void *priv; /* Pointer to private data of the API client */ | ||
129 | int (*set) (struct dmx_ts_feed *feed, | ||
130 | u16 pid, | ||
131 | int type, | ||
132 | enum dmx_ts_pes pes_type, | ||
133 | size_t circular_buffer_size, | ||
134 | struct timespec timeout); | ||
135 | int (*start_filtering) (struct dmx_ts_feed* feed); | ||
136 | int (*stop_filtering) (struct dmx_ts_feed* feed); | ||
137 | }; | ||
138 | |||
139 | /*--------------------------------------------------------------------------*/ | ||
140 | /* Section reception */ | ||
141 | /*--------------------------------------------------------------------------*/ | ||
142 | |||
143 | struct dmx_section_filter { | ||
144 | u8 filter_value [DMX_MAX_FILTER_SIZE]; | ||
145 | u8 filter_mask [DMX_MAX_FILTER_SIZE]; | ||
146 | u8 filter_mode [DMX_MAX_FILTER_SIZE]; | ||
147 | struct dmx_section_feed* parent; /* Back-pointer */ | ||
148 | void* priv; /* Pointer to private data of the API client */ | ||
149 | }; | ||
150 | |||
151 | struct dmx_section_feed { | ||
152 | int is_filtering; /* Set to non-zero when filtering in progress */ | ||
153 | struct dmx_demux* parent; /* Back-pointer */ | ||
154 | void* priv; /* Pointer to private data of the API client */ | ||
155 | |||
156 | int check_crc; | ||
157 | u32 crc_val; | ||
158 | |||
159 | u8 *secbuf; | ||
160 | u8 secbuf_base[DMX_MAX_SECFEED_SIZE]; | ||
161 | u16 secbufp, seclen, tsfeedp; | ||
162 | |||
163 | int (*set) (struct dmx_section_feed* feed, | ||
164 | u16 pid, | ||
165 | size_t circular_buffer_size, | ||
166 | int check_crc); | ||
167 | int (*allocate_filter) (struct dmx_section_feed* feed, | ||
168 | struct dmx_section_filter** filter); | ||
169 | int (*release_filter) (struct dmx_section_feed* feed, | ||
170 | struct dmx_section_filter* filter); | ||
171 | int (*start_filtering) (struct dmx_section_feed* feed); | ||
172 | int (*stop_filtering) (struct dmx_section_feed* feed); | ||
173 | }; | ||
174 | |||
175 | /*--------------------------------------------------------------------------*/ | ||
176 | /* Callback functions */ | ||
177 | /*--------------------------------------------------------------------------*/ | ||
178 | |||
179 | typedef int (*dmx_ts_cb) ( const u8 * buffer1, | ||
180 | size_t buffer1_length, | ||
181 | const u8 * buffer2, | ||
182 | size_t buffer2_length, | ||
183 | struct dmx_ts_feed* source, | ||
184 | enum dmx_success success); | ||
185 | |||
186 | typedef int (*dmx_section_cb) ( const u8 * buffer1, | ||
187 | size_t buffer1_len, | ||
188 | const u8 * buffer2, | ||
189 | size_t buffer2_len, | ||
190 | struct dmx_section_filter * source, | ||
191 | enum dmx_success success); | ||
192 | |||
193 | /*--------------------------------------------------------------------------*/ | ||
194 | /* DVB Front-End */ | ||
195 | /*--------------------------------------------------------------------------*/ | ||
196 | |||
197 | enum dmx_frontend_source { | ||
198 | DMX_MEMORY_FE, | ||
199 | DMX_FRONTEND_0, | ||
200 | DMX_FRONTEND_1, | ||
201 | DMX_FRONTEND_2, | ||
202 | DMX_FRONTEND_3, | ||
203 | DMX_STREAM_0, /* external stream input, e.g. LVDS */ | ||
204 | DMX_STREAM_1, | ||
205 | DMX_STREAM_2, | ||
206 | DMX_STREAM_3 | ||
207 | }; | ||
208 | |||
209 | struct dmx_frontend { | ||
210 | struct list_head connectivity_list; /* List of front-ends that can | ||
211 | be connected to a particular | ||
212 | demux */ | ||
213 | enum dmx_frontend_source source; | ||
214 | }; | ||
215 | |||
216 | /*--------------------------------------------------------------------------*/ | ||
217 | /* MPEG-2 TS Demux */ | ||
218 | /*--------------------------------------------------------------------------*/ | ||
219 | |||
220 | /* | ||
221 | * Flags OR'ed in the capabilities field of struct dmx_demux. | ||
222 | */ | ||
223 | |||
224 | #define DMX_TS_FILTERING 1 | ||
225 | #define DMX_PES_FILTERING 2 | ||
226 | #define DMX_SECTION_FILTERING 4 | ||
227 | #define DMX_MEMORY_BASED_FILTERING 8 /* write() available */ | ||
228 | #define DMX_CRC_CHECKING 16 | ||
229 | #define DMX_TS_DESCRAMBLING 32 | ||
230 | |||
231 | /* | ||
232 | * Demux resource type identifier. | ||
233 | */ | ||
234 | |||
235 | /* | ||
236 | * DMX_FE_ENTRY(): Casts elements in the list of registered | ||
237 | * front-ends from the generic type struct list_head | ||
238 | * to the type * struct dmx_frontend | ||
239 | *. | ||
240 | */ | ||
241 | |||
242 | #define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list) | ||
243 | |||
244 | struct dmx_demux { | ||
245 | u32 capabilities; /* Bitfield of capability flags */ | ||
246 | struct dmx_frontend* frontend; /* Front-end connected to the demux */ | ||
247 | void* priv; /* Pointer to private data of the API client */ | ||
248 | int (*open) (struct dmx_demux* demux); | ||
249 | int (*close) (struct dmx_demux* demux); | ||
250 | int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count); | ||
251 | int (*allocate_ts_feed) (struct dmx_demux* demux, | ||
252 | struct dmx_ts_feed** feed, | ||
253 | dmx_ts_cb callback); | ||
254 | int (*release_ts_feed) (struct dmx_demux* demux, | ||
255 | struct dmx_ts_feed* feed); | ||
256 | int (*allocate_section_feed) (struct dmx_demux* demux, | ||
257 | struct dmx_section_feed** feed, | ||
258 | dmx_section_cb callback); | ||
259 | int (*release_section_feed) (struct dmx_demux* demux, | ||
260 | struct dmx_section_feed* feed); | ||
261 | int (*add_frontend) (struct dmx_demux* demux, | ||
262 | struct dmx_frontend* frontend); | ||
263 | int (*remove_frontend) (struct dmx_demux* demux, | ||
264 | struct dmx_frontend* frontend); | ||
265 | struct list_head* (*get_frontends) (struct dmx_demux* demux); | ||
266 | int (*connect_frontend) (struct dmx_demux* demux, | ||
267 | struct dmx_frontend* frontend); | ||
268 | int (*disconnect_frontend) (struct dmx_demux* demux); | ||
269 | |||
270 | int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids); | ||
271 | |||
272 | int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps); | ||
273 | |||
274 | int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src); | ||
275 | |||
276 | int (*get_stc) (struct dmx_demux* demux, unsigned int num, | ||
277 | u64 *stc, unsigned int *base); | ||
278 | }; | ||
279 | |||
280 | #endif /* #ifndef __DEMUX_H */ | ||
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c deleted file mode 100644 index 889c9c16c6df..000000000000 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ /dev/null | |||
@@ -1,1275 +0,0 @@ | |||
1 | /* | ||
2 | * dmxdev.c - DVB demultiplexer device | ||
3 | * | ||
4 | * Copyright (C) 2000 Ralph Metzler & Marcus Metzler | ||
5 | * for convergence integrated media GmbH | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public License | ||
9 | * as published by the Free Software Foundation; either version 2.1 | ||
10 | * of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/sched.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/vmalloc.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/poll.h> | ||
29 | #include <linux/ioctl.h> | ||
30 | #include <linux/wait.h> | ||
31 | #include <asm/uaccess.h> | ||
32 | #include "dmxdev.h" | ||
33 | |||
34 | static int debug; | ||
35 | |||
36 | module_param(debug, int, 0644); | ||
37 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | ||
38 | |||
39 | #define dprintk if (debug) printk | ||
40 | |||
41 | static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, | ||
42 | const u8 *src, size_t len) | ||
43 | { | ||
44 | ssize_t free; | ||
45 | |||
46 | if (!len) | ||
47 | return 0; | ||
48 | if (!buf->data) | ||
49 | return 0; | ||
50 | |||
51 | free = dvb_ringbuffer_free(buf); | ||
52 | if (len > free) { | ||
53 | dprintk("dmxdev: buffer overflow\n"); | ||
54 | return -EOVERFLOW; | ||
55 | } | ||
56 | |||
57 | return dvb_ringbuffer_write(buf, src, len); | ||
58 | } | ||
59 | |||
60 | static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, | ||
61 | int non_blocking, char __user *buf, | ||
62 | size_t count, loff_t *ppos) | ||
63 | { | ||
64 | size_t todo; | ||
65 | ssize_t avail; | ||
66 | ssize_t ret = 0; | ||
67 | |||
68 | if (!src->data) | ||
69 | return 0; | ||
70 | |||
71 | if (src->error) { | ||
72 | ret = src->error; | ||
73 | dvb_ringbuffer_flush(src); | ||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | for (todo = count; todo > 0; todo -= ret) { | ||
78 | if (non_blocking && dvb_ringbuffer_empty(src)) { | ||
79 | ret = -EWOULDBLOCK; | ||
80 | break; | ||
81 | } | ||
82 | |||
83 | ret = wait_event_interruptible(src->queue, | ||
84 | !dvb_ringbuffer_empty(src) || | ||
85 | (src->error != 0)); | ||
86 | if (ret < 0) | ||
87 | break; | ||
88 | |||
89 | if (src->error) { | ||
90 | ret = src->error; | ||
91 | dvb_ringbuffer_flush(src); | ||
92 | break; | ||
93 | } | ||
94 | |||
95 | avail = dvb_ringbuffer_avail(src); | ||
96 | if (avail > todo) | ||
97 | avail = todo; | ||
98 | |||
99 | ret = dvb_ringbuffer_read_user(src, buf, avail); | ||
100 | if (ret < 0) | ||
101 | break; | ||
102 | |||
103 | buf += ret; | ||
104 | } | ||
105 | |||
106 | return (count - todo) ? (count - todo) : ret; | ||
107 | } | ||
108 | |||
109 | static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type) | ||
110 | { | ||
111 | struct list_head *head, *pos; | ||
112 | |||
113 | head = demux->get_frontends(demux); | ||
114 | if (!head) | ||
115 | return NULL; | ||
116 | list_for_each(pos, head) | ||
117 | if (DMX_FE_ENTRY(pos)->source == type) | ||
118 | return DMX_FE_ENTRY(pos); | ||
119 | |||
120 | return NULL; | ||
121 | } | ||
122 | |||
123 | static int dvb_dvr_open(struct inode *inode, struct file *file) | ||
124 | { | ||
125 | struct dvb_device *dvbdev = file->private_data; | ||
126 | struct dmxdev *dmxdev = dvbdev->priv; | ||
127 | struct dmx_frontend *front; | ||
128 | |||
129 | dprintk("function : %s\n", __func__); | ||
130 | |||
131 | if (mutex_lock_interruptible(&dmxdev->mutex)) | ||
132 | return -ERESTARTSYS; | ||
133 | |||
134 | if (dmxdev->exit) { | ||
135 | mutex_unlock(&dmxdev->mutex); | ||
136 | return -ENODEV; | ||
137 | } | ||
138 | |||
139 | if ((file->f_flags & O_ACCMODE) == O_RDWR) { | ||
140 | if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { | ||
141 | mutex_unlock(&dmxdev->mutex); | ||
142 | return -EOPNOTSUPP; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||
147 | void *mem; | ||
148 | if (!dvbdev->readers) { | ||
149 | mutex_unlock(&dmxdev->mutex); | ||
150 | return -EBUSY; | ||
151 | } | ||
152 | mem = vmalloc(DVR_BUFFER_SIZE); | ||
153 | if (!mem) { | ||
154 | mutex_unlock(&dmxdev->mutex); | ||
155 | return -ENOMEM; | ||
156 | } | ||
157 | dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); | ||
158 | dvbdev->readers--; | ||
159 | } | ||
160 | |||
161 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) { | ||
162 | dmxdev->dvr_orig_fe = dmxdev->demux->frontend; | ||
163 | |||
164 | if (!dmxdev->demux->write) { | ||
165 | mutex_unlock(&dmxdev->mutex); | ||
166 | return -EOPNOTSUPP; | ||
167 | } | ||
168 | |||
169 | front = get_fe(dmxdev->demux, DMX_MEMORY_FE); | ||
170 | |||
171 | if (!front) { | ||
172 | mutex_unlock(&dmxdev->mutex); | ||
173 | return -EINVAL; | ||
174 | } | ||
175 | dmxdev->demux->disconnect_frontend(dmxdev->demux); | ||
176 | dmxdev->demux->connect_frontend(dmxdev->demux, front); | ||
177 | } | ||
178 | dvbdev->users++; | ||
179 | mutex_unlock(&dmxdev->mutex); | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int dvb_dvr_release(struct inode *inode, struct file *file) | ||
184 | { | ||
185 | struct dvb_device *dvbdev = file->private_data; | ||
186 | struct dmxdev *dmxdev = dvbdev->priv; | ||
187 | |||
188 | mutex_lock(&dmxdev->mutex); | ||
189 | |||
190 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) { | ||
191 | dmxdev->demux->disconnect_frontend(dmxdev->demux); | ||
192 | dmxdev->demux->connect_frontend(dmxdev->demux, | ||
193 | dmxdev->dvr_orig_fe); | ||
194 | } | ||
195 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||
196 | dvbdev->readers++; | ||
197 | if (dmxdev->dvr_buffer.data) { | ||
198 | void *mem = dmxdev->dvr_buffer.data; | ||
199 | mb(); | ||
200 | spin_lock_irq(&dmxdev->lock); | ||
201 | dmxdev->dvr_buffer.data = NULL; | ||
202 | spin_unlock_irq(&dmxdev->lock); | ||
203 | vfree(mem); | ||
204 | } | ||
205 | } | ||
206 | /* TODO */ | ||
207 | dvbdev->users--; | ||
208 | if (dvbdev->users == 1 && dmxdev->exit == 1) { | ||
209 | fops_put(file->f_op); | ||
210 | file->f_op = NULL; | ||
211 | mutex_unlock(&dmxdev->mutex); | ||
212 | wake_up(&dvbdev->wait_queue); | ||
213 | } else | ||
214 | mutex_unlock(&dmxdev->mutex); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, | ||
220 | size_t count, loff_t *ppos) | ||
221 | { | ||
222 | struct dvb_device *dvbdev = file->private_data; | ||
223 | struct dmxdev *dmxdev = dvbdev->priv; | ||
224 | int ret; | ||
225 | |||
226 | if (!dmxdev->demux->write) | ||
227 | return -EOPNOTSUPP; | ||
228 | if ((file->f_flags & O_ACCMODE) != O_WRONLY) | ||
229 | return -EINVAL; | ||
230 | if (mutex_lock_interruptible(&dmxdev->mutex)) | ||
231 | return -ERESTARTSYS; | ||
232 | |||
233 | if (dmxdev->exit) { | ||
234 | mutex_unlock(&dmxdev->mutex); | ||
235 | return -ENODEV; | ||
236 | } | ||
237 | ret = dmxdev->demux->write(dmxdev->demux, buf, count); | ||
238 | mutex_unlock(&dmxdev->mutex); | ||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, | ||
243 | loff_t *ppos) | ||
244 | { | ||
245 | struct dvb_device *dvbdev = file->private_data; | ||
246 | struct dmxdev *dmxdev = dvbdev->priv; | ||
247 | |||
248 | if (dmxdev->exit) | ||
249 | return -ENODEV; | ||
250 | |||
251 | return dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, | ||
252 | file->f_flags & O_NONBLOCK, | ||
253 | buf, count, ppos); | ||
254 | } | ||
255 | |||
256 | static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev, | ||
257 | unsigned long size) | ||
258 | { | ||
259 | struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer; | ||
260 | void *newmem; | ||
261 | void *oldmem; | ||
262 | |||
263 | dprintk("function : %s\n", __func__); | ||
264 | |||
265 | if (buf->size == size) | ||
266 | return 0; | ||
267 | if (!size) | ||
268 | return -EINVAL; | ||
269 | |||
270 | newmem = vmalloc(size); | ||
271 | if (!newmem) | ||
272 | return -ENOMEM; | ||
273 | |||
274 | oldmem = buf->data; | ||
275 | |||
276 | spin_lock_irq(&dmxdev->lock); | ||
277 | buf->data = newmem; | ||
278 | buf->size = size; | ||
279 | |||
280 | /* reset and not flush in case the buffer shrinks */ | ||
281 | dvb_ringbuffer_reset(buf); | ||
282 | spin_unlock_irq(&dmxdev->lock); | ||
283 | |||
284 | vfree(oldmem); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter | ||
290 | *dmxdevfilter, int state) | ||
291 | { | ||
292 | spin_lock_irq(&dmxdevfilter->dev->lock); | ||
293 | dmxdevfilter->state = state; | ||
294 | spin_unlock_irq(&dmxdevfilter->dev->lock); | ||
295 | } | ||
296 | |||
297 | static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, | ||
298 | unsigned long size) | ||
299 | { | ||
300 | struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; | ||
301 | void *newmem; | ||
302 | void *oldmem; | ||
303 | |||
304 | if (buf->size == size) | ||
305 | return 0; | ||
306 | if (!size) | ||
307 | return -EINVAL; | ||
308 | if (dmxdevfilter->state >= DMXDEV_STATE_GO) | ||
309 | return -EBUSY; | ||
310 | |||
311 | newmem = vmalloc(size); | ||
312 | if (!newmem) | ||
313 | return -ENOMEM; | ||
314 | |||
315 | oldmem = buf->data; | ||
316 | |||
317 | spin_lock_irq(&dmxdevfilter->dev->lock); | ||
318 | buf->data = newmem; | ||
319 | buf->size = size; | ||
320 | |||
321 | /* reset and not flush in case the buffer shrinks */ | ||
322 | dvb_ringbuffer_reset(buf); | ||
323 | spin_unlock_irq(&dmxdevfilter->dev->lock); | ||
324 | |||
325 | vfree(oldmem); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static void dvb_dmxdev_filter_timeout(unsigned long data) | ||
331 | { | ||
332 | struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data; | ||
333 | |||
334 | dmxdevfilter->buffer.error = -ETIMEDOUT; | ||
335 | spin_lock_irq(&dmxdevfilter->dev->lock); | ||
336 | dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT; | ||
337 | spin_unlock_irq(&dmxdevfilter->dev->lock); | ||
338 | wake_up(&dmxdevfilter->buffer.queue); | ||
339 | } | ||
340 | |||
341 | static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) | ||
342 | { | ||
343 | struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec; | ||
344 | |||
345 | del_timer(&dmxdevfilter->timer); | ||
346 | if (para->timeout) { | ||
347 | dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout; | ||
348 | dmxdevfilter->timer.data = (unsigned long)dmxdevfilter; | ||
349 | dmxdevfilter->timer.expires = | ||
350 | jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000; | ||
351 | add_timer(&dmxdevfilter->timer); | ||
352 | } | ||
353 | } | ||
354 | |||
355 | static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, | ||
356 | const u8 *buffer2, size_t buffer2_len, | ||
357 | struct dmx_section_filter *filter, | ||
358 | enum dmx_success success) | ||
359 | { | ||
360 | struct dmxdev_filter *dmxdevfilter = filter->priv; | ||
361 | int ret; | ||
362 | |||
363 | if (dmxdevfilter->buffer.error) { | ||
364 | wake_up(&dmxdevfilter->buffer.queue); | ||
365 | return 0; | ||
366 | } | ||
367 | spin_lock(&dmxdevfilter->dev->lock); | ||
368 | if (dmxdevfilter->state != DMXDEV_STATE_GO) { | ||
369 | spin_unlock(&dmxdevfilter->dev->lock); | ||
370 | return 0; | ||
371 | } | ||
372 | del_timer(&dmxdevfilter->timer); | ||
373 | dprintk("dmxdev: section callback %*ph\n", 6, buffer1); | ||
374 | ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, | ||
375 | buffer1_len); | ||
376 | if (ret == buffer1_len) { | ||
377 | ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, | ||
378 | buffer2_len); | ||
379 | } | ||
380 | if (ret < 0) { | ||
381 | dvb_ringbuffer_flush(&dmxdevfilter->buffer); | ||
382 | dmxdevfilter->buffer.error = ret; | ||
383 | } | ||
384 | if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) | ||
385 | dmxdevfilter->state = DMXDEV_STATE_DONE; | ||
386 | spin_unlock(&dmxdevfilter->dev->lock); | ||
387 | wake_up(&dmxdevfilter->buffer.queue); | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, | ||
392 | const u8 *buffer2, size_t buffer2_len, | ||
393 | struct dmx_ts_feed *feed, | ||
394 | enum dmx_success success) | ||
395 | { | ||
396 | struct dmxdev_filter *dmxdevfilter = feed->priv; | ||
397 | struct dvb_ringbuffer *buffer; | ||
398 | int ret; | ||
399 | |||
400 | spin_lock(&dmxdevfilter->dev->lock); | ||
401 | if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { | ||
402 | spin_unlock(&dmxdevfilter->dev->lock); | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | if (dmxdevfilter->params.pes.output == DMX_OUT_TAP | ||
407 | || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) | ||
408 | buffer = &dmxdevfilter->buffer; | ||
409 | else | ||
410 | buffer = &dmxdevfilter->dev->dvr_buffer; | ||
411 | if (buffer->error) { | ||
412 | spin_unlock(&dmxdevfilter->dev->lock); | ||
413 | wake_up(&buffer->queue); | ||
414 | return 0; | ||
415 | } | ||
416 | ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); | ||
417 | if (ret == buffer1_len) | ||
418 | ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); | ||
419 | if (ret < 0) { | ||
420 | dvb_ringbuffer_flush(buffer); | ||
421 | buffer->error = ret; | ||
422 | } | ||
423 | spin_unlock(&dmxdevfilter->dev->lock); | ||
424 | wake_up(&buffer->queue); | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | /* stop feed but only mark the specified filter as stopped (state set) */ | ||
429 | static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) | ||
430 | { | ||
431 | struct dmxdev_feed *feed; | ||
432 | |||
433 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); | ||
434 | |||
435 | switch (dmxdevfilter->type) { | ||
436 | case DMXDEV_TYPE_SEC: | ||
437 | del_timer(&dmxdevfilter->timer); | ||
438 | dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec); | ||
439 | break; | ||
440 | case DMXDEV_TYPE_PES: | ||
441 | list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) | ||
442 | feed->ts->stop_filtering(feed->ts); | ||
443 | break; | ||
444 | default: | ||
445 | return -EINVAL; | ||
446 | } | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | /* start feed associated with the specified filter */ | ||
451 | static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter) | ||
452 | { | ||
453 | struct dmxdev_feed *feed; | ||
454 | int ret; | ||
455 | |||
456 | dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO); | ||
457 | |||
458 | switch (filter->type) { | ||
459 | case DMXDEV_TYPE_SEC: | ||
460 | return filter->feed.sec->start_filtering(filter->feed.sec); | ||
461 | case DMXDEV_TYPE_PES: | ||
462 | list_for_each_entry(feed, &filter->feed.ts, next) { | ||
463 | ret = feed->ts->start_filtering(feed->ts); | ||
464 | if (ret < 0) { | ||
465 | dvb_dmxdev_feed_stop(filter); | ||
466 | return ret; | ||
467 | } | ||
468 | } | ||
469 | break; | ||
470 | default: | ||
471 | return -EINVAL; | ||
472 | } | ||
473 | |||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | /* restart section feed if it has filters left associated with it, | ||
478 | otherwise release the feed */ | ||
479 | static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter) | ||
480 | { | ||
481 | int i; | ||
482 | struct dmxdev *dmxdev = filter->dev; | ||
483 | u16 pid = filter->params.sec.pid; | ||
484 | |||
485 | for (i = 0; i < dmxdev->filternum; i++) | ||
486 | if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && | ||
487 | dmxdev->filter[i].type == DMXDEV_TYPE_SEC && | ||
488 | dmxdev->filter[i].params.sec.pid == pid) { | ||
489 | dvb_dmxdev_feed_start(&dmxdev->filter[i]); | ||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | filter->dev->demux->release_section_feed(dmxdev->demux, | ||
494 | filter->feed.sec); | ||
495 | |||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) | ||
500 | { | ||
501 | struct dmxdev_feed *feed; | ||
502 | struct dmx_demux *demux; | ||
503 | |||
504 | if (dmxdevfilter->state < DMXDEV_STATE_GO) | ||
505 | return 0; | ||
506 | |||
507 | switch (dmxdevfilter->type) { | ||
508 | case DMXDEV_TYPE_SEC: | ||
509 | if (!dmxdevfilter->feed.sec) | ||
510 | break; | ||
511 | dvb_dmxdev_feed_stop(dmxdevfilter); | ||
512 | if (dmxdevfilter->filter.sec) | ||
513 | dmxdevfilter->feed.sec-> | ||
514 | release_filter(dmxdevfilter->feed.sec, | ||
515 | dmxdevfilter->filter.sec); | ||
516 | dvb_dmxdev_feed_restart(dmxdevfilter); | ||
517 | dmxdevfilter->feed.sec = NULL; | ||
518 | break; | ||
519 | case DMXDEV_TYPE_PES: | ||
520 | dvb_dmxdev_feed_stop(dmxdevfilter); | ||
521 | demux = dmxdevfilter->dev->demux; | ||
522 | list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) { | ||
523 | demux->release_ts_feed(demux, feed->ts); | ||
524 | feed->ts = NULL; | ||
525 | } | ||
526 | break; | ||
527 | default: | ||
528 | if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED) | ||
529 | return 0; | ||
530 | return -EINVAL; | ||
531 | } | ||
532 | |||
533 | dvb_ringbuffer_flush(&dmxdevfilter->buffer); | ||
534 | return 0; | ||
535 | } | ||
536 | |||
537 | static void dvb_dmxdev_delete_pids(struct dmxdev_filter *dmxdevfilter) | ||
538 | { | ||
539 | struct dmxdev_feed *feed, *tmp; | ||
540 | |||
541 | /* delete all PIDs */ | ||
542 | list_for_each_entry_safe(feed, tmp, &dmxdevfilter->feed.ts, next) { | ||
543 | list_del(&feed->next); | ||
544 | kfree(feed); | ||
545 | } | ||
546 | |||
547 | BUG_ON(!list_empty(&dmxdevfilter->feed.ts)); | ||
548 | } | ||
549 | |||
550 | static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter) | ||
551 | { | ||
552 | if (dmxdevfilter->state < DMXDEV_STATE_SET) | ||
553 | return 0; | ||
554 | |||
555 | if (dmxdevfilter->type == DMXDEV_TYPE_PES) | ||
556 | dvb_dmxdev_delete_pids(dmxdevfilter); | ||
557 | |||
558 | dmxdevfilter->type = DMXDEV_TYPE_NONE; | ||
559 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev, | ||
564 | struct dmxdev_filter *filter, | ||
565 | struct dmxdev_feed *feed) | ||
566 | { | ||
567 | struct timespec timeout = { 0 }; | ||
568 | struct dmx_pes_filter_params *para = &filter->params.pes; | ||
569 | dmx_output_t otype; | ||
570 | int ret; | ||
571 | int ts_type; | ||
572 | dmx_pes_type_t ts_pes; | ||
573 | struct dmx_ts_feed *tsfeed; | ||
574 | |||
575 | feed->ts = NULL; | ||
576 | otype = para->output; | ||
577 | |||
578 | ts_pes = para->pes_type; | ||
579 | |||
580 | if (ts_pes < DMX_PES_OTHER) | ||
581 | ts_type = TS_DECODER; | ||
582 | else | ||
583 | ts_type = 0; | ||
584 | |||
585 | if (otype == DMX_OUT_TS_TAP) | ||
586 | ts_type |= TS_PACKET; | ||
587 | else if (otype == DMX_OUT_TSDEMUX_TAP) | ||
588 | ts_type |= TS_PACKET | TS_DEMUX; | ||
589 | else if (otype == DMX_OUT_TAP) | ||
590 | ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY; | ||
591 | |||
592 | ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux, &feed->ts, | ||
593 | dvb_dmxdev_ts_callback); | ||
594 | if (ret < 0) | ||
595 | return ret; | ||
596 | |||
597 | tsfeed = feed->ts; | ||
598 | tsfeed->priv = filter; | ||
599 | |||
600 | ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, 32768, timeout); | ||
601 | if (ret < 0) { | ||
602 | dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | ret = tsfeed->start_filtering(tsfeed); | ||
607 | if (ret < 0) { | ||
608 | dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); | ||
609 | return ret; | ||
610 | } | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) | ||
616 | { | ||
617 | struct dmxdev *dmxdev = filter->dev; | ||
618 | struct dmxdev_feed *feed; | ||
619 | void *mem; | ||
620 | int ret, i; | ||
621 | |||
622 | if (filter->state < DMXDEV_STATE_SET) | ||
623 | return -EINVAL; | ||
624 | |||
625 | if (filter->state >= DMXDEV_STATE_GO) | ||
626 | dvb_dmxdev_filter_stop(filter); | ||
627 | |||
628 | if (!filter->buffer.data) { | ||
629 | mem = vmalloc(filter->buffer.size); | ||
630 | if (!mem) | ||
631 | return -ENOMEM; | ||
632 | spin_lock_irq(&filter->dev->lock); | ||
633 | filter->buffer.data = mem; | ||
634 | spin_unlock_irq(&filter->dev->lock); | ||
635 | } | ||
636 | |||
637 | dvb_ringbuffer_flush(&filter->buffer); | ||
638 | |||
639 | switch (filter->type) { | ||
640 | case DMXDEV_TYPE_SEC: | ||
641 | { | ||
642 | struct dmx_sct_filter_params *para = &filter->params.sec; | ||
643 | struct dmx_section_filter **secfilter = &filter->filter.sec; | ||
644 | struct dmx_section_feed **secfeed = &filter->feed.sec; | ||
645 | |||
646 | *secfilter = NULL; | ||
647 | *secfeed = NULL; | ||
648 | |||
649 | |||
650 | /* find active filter/feed with same PID */ | ||
651 | for (i = 0; i < dmxdev->filternum; i++) { | ||
652 | if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && | ||
653 | dmxdev->filter[i].type == DMXDEV_TYPE_SEC && | ||
654 | dmxdev->filter[i].params.sec.pid == para->pid) { | ||
655 | *secfeed = dmxdev->filter[i].feed.sec; | ||
656 | break; | ||
657 | } | ||
658 | } | ||
659 | |||
660 | /* if no feed found, try to allocate new one */ | ||
661 | if (!*secfeed) { | ||
662 | ret = dmxdev->demux->allocate_section_feed(dmxdev->demux, | ||
663 | secfeed, | ||
664 | dvb_dmxdev_section_callback); | ||
665 | if (ret < 0) { | ||
666 | printk("DVB (%s): could not alloc feed\n", | ||
667 | __func__); | ||
668 | return ret; | ||
669 | } | ||
670 | |||
671 | ret = (*secfeed)->set(*secfeed, para->pid, 32768, | ||
672 | (para->flags & DMX_CHECK_CRC) ? 1 : 0); | ||
673 | if (ret < 0) { | ||
674 | printk("DVB (%s): could not set feed\n", | ||
675 | __func__); | ||
676 | dvb_dmxdev_feed_restart(filter); | ||
677 | return ret; | ||
678 | } | ||
679 | } else { | ||
680 | dvb_dmxdev_feed_stop(filter); | ||
681 | } | ||
682 | |||
683 | ret = (*secfeed)->allocate_filter(*secfeed, secfilter); | ||
684 | if (ret < 0) { | ||
685 | dvb_dmxdev_feed_restart(filter); | ||
686 | filter->feed.sec->start_filtering(*secfeed); | ||
687 | dprintk("could not get filter\n"); | ||
688 | return ret; | ||
689 | } | ||
690 | |||
691 | (*secfilter)->priv = filter; | ||
692 | |||
693 | memcpy(&((*secfilter)->filter_value[3]), | ||
694 | &(para->filter.filter[1]), DMX_FILTER_SIZE - 1); | ||
695 | memcpy(&(*secfilter)->filter_mask[3], | ||
696 | ¶->filter.mask[1], DMX_FILTER_SIZE - 1); | ||
697 | memcpy(&(*secfilter)->filter_mode[3], | ||
698 | ¶->filter.mode[1], DMX_FILTER_SIZE - 1); | ||
699 | |||
700 | (*secfilter)->filter_value[0] = para->filter.filter[0]; | ||
701 | (*secfilter)->filter_mask[0] = para->filter.mask[0]; | ||
702 | (*secfilter)->filter_mode[0] = para->filter.mode[0]; | ||
703 | (*secfilter)->filter_mask[1] = 0; | ||
704 | (*secfilter)->filter_mask[2] = 0; | ||
705 | |||
706 | filter->todo = 0; | ||
707 | |||
708 | ret = filter->feed.sec->start_filtering(filter->feed.sec); | ||
709 | if (ret < 0) | ||
710 | return ret; | ||
711 | |||
712 | dvb_dmxdev_filter_timer(filter); | ||
713 | break; | ||
714 | } | ||
715 | case DMXDEV_TYPE_PES: | ||
716 | list_for_each_entry(feed, &filter->feed.ts, next) { | ||
717 | ret = dvb_dmxdev_start_feed(dmxdev, filter, feed); | ||
718 | if (ret < 0) { | ||
719 | dvb_dmxdev_filter_stop(filter); | ||
720 | return ret; | ||
721 | } | ||
722 | } | ||
723 | break; | ||
724 | default: | ||
725 | return -EINVAL; | ||
726 | } | ||
727 | |||
728 | dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO); | ||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static int dvb_demux_open(struct inode *inode, struct file *file) | ||
733 | { | ||
734 | struct dvb_device *dvbdev = file->private_data; | ||
735 | struct dmxdev *dmxdev = dvbdev->priv; | ||
736 | int i; | ||
737 | struct dmxdev_filter *dmxdevfilter; | ||
738 | |||
739 | if (!dmxdev->filter) | ||
740 | return -EINVAL; | ||
741 | |||
742 | if (mutex_lock_interruptible(&dmxdev->mutex)) | ||
743 | return -ERESTARTSYS; | ||
744 | |||
745 | for (i = 0; i < dmxdev->filternum; i++) | ||
746 | if (dmxdev->filter[i].state == DMXDEV_STATE_FREE) | ||
747 | break; | ||
748 | |||
749 | if (i == dmxdev->filternum) { | ||
750 | mutex_unlock(&dmxdev->mutex); | ||
751 | return -EMFILE; | ||
752 | } | ||
753 | |||
754 | dmxdevfilter = &dmxdev->filter[i]; | ||
755 | mutex_init(&dmxdevfilter->mutex); | ||
756 | file->private_data = dmxdevfilter; | ||
757 | |||
758 | dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); | ||
759 | dmxdevfilter->type = DMXDEV_TYPE_NONE; | ||
760 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); | ||
761 | init_timer(&dmxdevfilter->timer); | ||
762 | |||
763 | dvbdev->users++; | ||
764 | |||
765 | mutex_unlock(&dmxdev->mutex); | ||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, | ||
770 | struct dmxdev_filter *dmxdevfilter) | ||
771 | { | ||
772 | mutex_lock(&dmxdev->mutex); | ||
773 | mutex_lock(&dmxdevfilter->mutex); | ||
774 | |||
775 | dvb_dmxdev_filter_stop(dmxdevfilter); | ||
776 | dvb_dmxdev_filter_reset(dmxdevfilter); | ||
777 | |||
778 | if (dmxdevfilter->buffer.data) { | ||
779 | void *mem = dmxdevfilter->buffer.data; | ||
780 | |||
781 | spin_lock_irq(&dmxdev->lock); | ||
782 | dmxdevfilter->buffer.data = NULL; | ||
783 | spin_unlock_irq(&dmxdev->lock); | ||
784 | vfree(mem); | ||
785 | } | ||
786 | |||
787 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE); | ||
788 | wake_up(&dmxdevfilter->buffer.queue); | ||
789 | mutex_unlock(&dmxdevfilter->mutex); | ||
790 | mutex_unlock(&dmxdev->mutex); | ||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | static inline void invert_mode(dmx_filter_t *filter) | ||
795 | { | ||
796 | int i; | ||
797 | |||
798 | for (i = 0; i < DMX_FILTER_SIZE; i++) | ||
799 | filter->mode[i] ^= 0xff; | ||
800 | } | ||
801 | |||
802 | static int dvb_dmxdev_add_pid(struct dmxdev *dmxdev, | ||
803 | struct dmxdev_filter *filter, u16 pid) | ||
804 | { | ||
805 | struct dmxdev_feed *feed; | ||
806 | |||
807 | if ((filter->type != DMXDEV_TYPE_PES) || | ||
808 | (filter->state < DMXDEV_STATE_SET)) | ||
809 | return -EINVAL; | ||
810 | |||
811 | /* only TS packet filters may have multiple PIDs */ | ||
812 | if ((filter->params.pes.output != DMX_OUT_TSDEMUX_TAP) && | ||
813 | (!list_empty(&filter->feed.ts))) | ||
814 | return -EINVAL; | ||
815 | |||
816 | feed = kzalloc(sizeof(struct dmxdev_feed), GFP_KERNEL); | ||
817 | if (feed == NULL) | ||
818 | return -ENOMEM; | ||
819 | |||
820 | feed->pid = pid; | ||
821 | list_add(&feed->next, &filter->feed.ts); | ||
822 | |||
823 | if (filter->state >= DMXDEV_STATE_GO) | ||
824 | return dvb_dmxdev_start_feed(dmxdev, filter, feed); | ||
825 | |||
826 | return 0; | ||
827 | } | ||
828 | |||
829 | static int dvb_dmxdev_remove_pid(struct dmxdev *dmxdev, | ||
830 | struct dmxdev_filter *filter, u16 pid) | ||
831 | { | ||
832 | struct dmxdev_feed *feed, *tmp; | ||
833 | |||
834 | if ((filter->type != DMXDEV_TYPE_PES) || | ||
835 | (filter->state < DMXDEV_STATE_SET)) | ||
836 | return -EINVAL; | ||
837 | |||
838 | list_for_each_entry_safe(feed, tmp, &filter->feed.ts, next) { | ||
839 | if ((feed->pid == pid) && (feed->ts != NULL)) { | ||
840 | feed->ts->stop_filtering(feed->ts); | ||
841 | filter->dev->demux->release_ts_feed(filter->dev->demux, | ||
842 | feed->ts); | ||
843 | list_del(&feed->next); | ||
844 | kfree(feed); | ||
845 | } | ||
846 | } | ||
847 | |||
848 | return 0; | ||
849 | } | ||
850 | |||
851 | static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev, | ||
852 | struct dmxdev_filter *dmxdevfilter, | ||
853 | struct dmx_sct_filter_params *params) | ||
854 | { | ||
855 | dprintk("function : %s\n", __func__); | ||
856 | |||
857 | dvb_dmxdev_filter_stop(dmxdevfilter); | ||
858 | |||
859 | dmxdevfilter->type = DMXDEV_TYPE_SEC; | ||
860 | memcpy(&dmxdevfilter->params.sec, | ||
861 | params, sizeof(struct dmx_sct_filter_params)); | ||
862 | invert_mode(&dmxdevfilter->params.sec.filter); | ||
863 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); | ||
864 | |||
865 | if (params->flags & DMX_IMMEDIATE_START) | ||
866 | return dvb_dmxdev_filter_start(dmxdevfilter); | ||
867 | |||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev, | ||
872 | struct dmxdev_filter *dmxdevfilter, | ||
873 | struct dmx_pes_filter_params *params) | ||
874 | { | ||
875 | int ret; | ||
876 | |||
877 | dvb_dmxdev_filter_stop(dmxdevfilter); | ||
878 | dvb_dmxdev_filter_reset(dmxdevfilter); | ||
879 | |||
880 | if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0) | ||
881 | return -EINVAL; | ||
882 | |||
883 | dmxdevfilter->type = DMXDEV_TYPE_PES; | ||
884 | memcpy(&dmxdevfilter->params, params, | ||
885 | sizeof(struct dmx_pes_filter_params)); | ||
886 | INIT_LIST_HEAD(&dmxdevfilter->feed.ts); | ||
887 | |||
888 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); | ||
889 | |||
890 | ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter, | ||
891 | dmxdevfilter->params.pes.pid); | ||
892 | if (ret < 0) | ||
893 | return ret; | ||
894 | |||
895 | if (params->flags & DMX_IMMEDIATE_START) | ||
896 | return dvb_dmxdev_filter_start(dmxdevfilter); | ||
897 | |||
898 | return 0; | ||
899 | } | ||
900 | |||
901 | static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil, | ||
902 | struct file *file, char __user *buf, | ||
903 | size_t count, loff_t *ppos) | ||
904 | { | ||
905 | int result, hcount; | ||
906 | int done = 0; | ||
907 | |||
908 | if (dfil->todo <= 0) { | ||
909 | hcount = 3 + dfil->todo; | ||
910 | if (hcount > count) | ||
911 | hcount = count; | ||
912 | result = dvb_dmxdev_buffer_read(&dfil->buffer, | ||
913 | file->f_flags & O_NONBLOCK, | ||
914 | buf, hcount, ppos); | ||
915 | if (result < 0) { | ||
916 | dfil->todo = 0; | ||
917 | return result; | ||
918 | } | ||
919 | if (copy_from_user(dfil->secheader - dfil->todo, buf, result)) | ||
920 | return -EFAULT; | ||
921 | buf += result; | ||
922 | done = result; | ||
923 | count -= result; | ||
924 | dfil->todo -= result; | ||
925 | if (dfil->todo > -3) | ||
926 | return done; | ||
927 | dfil->todo = ((dfil->secheader[1] << 8) | dfil->secheader[2]) & 0xfff; | ||
928 | if (!count) | ||
929 | return done; | ||
930 | } | ||
931 | if (count > dfil->todo) | ||
932 | count = dfil->todo; | ||
933 | result = dvb_dmxdev_buffer_read(&dfil->buffer, | ||
934 | file->f_flags & O_NONBLOCK, | ||
935 | buf, count, ppos); | ||
936 | if (result < 0) | ||
937 | return result; | ||
938 | dfil->todo -= result; | ||
939 | return (result + done); | ||
940 | } | ||
941 | |||
942 | static ssize_t | ||
943 | dvb_demux_read(struct file *file, char __user *buf, size_t count, | ||
944 | loff_t *ppos) | ||
945 | { | ||
946 | struct dmxdev_filter *dmxdevfilter = file->private_data; | ||
947 | int ret; | ||
948 | |||
949 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) | ||
950 | return -ERESTARTSYS; | ||
951 | |||
952 | if (dmxdevfilter->type == DMXDEV_TYPE_SEC) | ||
953 | ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos); | ||
954 | else | ||
955 | ret = dvb_dmxdev_buffer_read(&dmxdevfilter->buffer, | ||
956 | file->f_flags & O_NONBLOCK, | ||
957 | buf, count, ppos); | ||
958 | |||
959 | mutex_unlock(&dmxdevfilter->mutex); | ||
960 | return ret; | ||
961 | } | ||
962 | |||
963 | static int dvb_demux_do_ioctl(struct file *file, | ||
964 | unsigned int cmd, void *parg) | ||
965 | { | ||
966 | struct dmxdev_filter *dmxdevfilter = file->private_data; | ||
967 | struct dmxdev *dmxdev = dmxdevfilter->dev; | ||
968 | unsigned long arg = (unsigned long)parg; | ||
969 | int ret = 0; | ||
970 | |||
971 | if (mutex_lock_interruptible(&dmxdev->mutex)) | ||
972 | return -ERESTARTSYS; | ||
973 | |||
974 | switch (cmd) { | ||
975 | case DMX_START: | ||
976 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
977 | mutex_unlock(&dmxdev->mutex); | ||
978 | return -ERESTARTSYS; | ||
979 | } | ||
980 | if (dmxdevfilter->state < DMXDEV_STATE_SET) | ||
981 | ret = -EINVAL; | ||
982 | else | ||
983 | ret = dvb_dmxdev_filter_start(dmxdevfilter); | ||
984 | mutex_unlock(&dmxdevfilter->mutex); | ||
985 | break; | ||
986 | |||
987 | case DMX_STOP: | ||
988 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
989 | mutex_unlock(&dmxdev->mutex); | ||
990 | return -ERESTARTSYS; | ||
991 | } | ||
992 | ret = dvb_dmxdev_filter_stop(dmxdevfilter); | ||
993 | mutex_unlock(&dmxdevfilter->mutex); | ||
994 | break; | ||
995 | |||
996 | case DMX_SET_FILTER: | ||
997 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
998 | mutex_unlock(&dmxdev->mutex); | ||
999 | return -ERESTARTSYS; | ||
1000 | } | ||
1001 | ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, parg); | ||
1002 | mutex_unlock(&dmxdevfilter->mutex); | ||
1003 | break; | ||
1004 | |||
1005 | case DMX_SET_PES_FILTER: | ||
1006 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
1007 | mutex_unlock(&dmxdev->mutex); | ||
1008 | return -ERESTARTSYS; | ||
1009 | } | ||
1010 | ret = dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, parg); | ||
1011 | mutex_unlock(&dmxdevfilter->mutex); | ||
1012 | break; | ||
1013 | |||
1014 | case DMX_SET_BUFFER_SIZE: | ||
1015 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
1016 | mutex_unlock(&dmxdev->mutex); | ||
1017 | return -ERESTARTSYS; | ||
1018 | } | ||
1019 | ret = dvb_dmxdev_set_buffer_size(dmxdevfilter, arg); | ||
1020 | mutex_unlock(&dmxdevfilter->mutex); | ||
1021 | break; | ||
1022 | |||
1023 | case DMX_GET_PES_PIDS: | ||
1024 | if (!dmxdev->demux->get_pes_pids) { | ||
1025 | ret = -EINVAL; | ||
1026 | break; | ||
1027 | } | ||
1028 | dmxdev->demux->get_pes_pids(dmxdev->demux, parg); | ||
1029 | break; | ||
1030 | |||
1031 | case DMX_GET_CAPS: | ||
1032 | if (!dmxdev->demux->get_caps) { | ||
1033 | ret = -EINVAL; | ||
1034 | break; | ||
1035 | } | ||
1036 | ret = dmxdev->demux->get_caps(dmxdev->demux, parg); | ||
1037 | break; | ||
1038 | |||
1039 | case DMX_SET_SOURCE: | ||
1040 | if (!dmxdev->demux->set_source) { | ||
1041 | ret = -EINVAL; | ||
1042 | break; | ||
1043 | } | ||
1044 | ret = dmxdev->demux->set_source(dmxdev->demux, parg); | ||
1045 | break; | ||
1046 | |||
1047 | case DMX_GET_STC: | ||
1048 | if (!dmxdev->demux->get_stc) { | ||
1049 | ret = -EINVAL; | ||
1050 | break; | ||
1051 | } | ||
1052 | ret = dmxdev->demux->get_stc(dmxdev->demux, | ||
1053 | ((struct dmx_stc *)parg)->num, | ||
1054 | &((struct dmx_stc *)parg)->stc, | ||
1055 | &((struct dmx_stc *)parg)->base); | ||
1056 | break; | ||
1057 | |||
1058 | case DMX_ADD_PID: | ||
1059 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
1060 | ret = -ERESTARTSYS; | ||
1061 | break; | ||
1062 | } | ||
1063 | ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter, *(u16 *)parg); | ||
1064 | mutex_unlock(&dmxdevfilter->mutex); | ||
1065 | break; | ||
1066 | |||
1067 | case DMX_REMOVE_PID: | ||
1068 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
1069 | ret = -ERESTARTSYS; | ||
1070 | break; | ||
1071 | } | ||
1072 | ret = dvb_dmxdev_remove_pid(dmxdev, dmxdevfilter, *(u16 *)parg); | ||
1073 | mutex_unlock(&dmxdevfilter->mutex); | ||
1074 | break; | ||
1075 | |||
1076 | default: | ||
1077 | ret = -EINVAL; | ||
1078 | break; | ||
1079 | } | ||
1080 | mutex_unlock(&dmxdev->mutex); | ||
1081 | return ret; | ||
1082 | } | ||
1083 | |||
1084 | static long dvb_demux_ioctl(struct file *file, unsigned int cmd, | ||
1085 | unsigned long arg) | ||
1086 | { | ||
1087 | return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl); | ||
1088 | } | ||
1089 | |||
1090 | static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) | ||
1091 | { | ||
1092 | struct dmxdev_filter *dmxdevfilter = file->private_data; | ||
1093 | unsigned int mask = 0; | ||
1094 | |||
1095 | if (!dmxdevfilter) | ||
1096 | return -EINVAL; | ||
1097 | |||
1098 | poll_wait(file, &dmxdevfilter->buffer.queue, wait); | ||
1099 | |||
1100 | if (dmxdevfilter->state != DMXDEV_STATE_GO && | ||
1101 | dmxdevfilter->state != DMXDEV_STATE_DONE && | ||
1102 | dmxdevfilter->state != DMXDEV_STATE_TIMEDOUT) | ||
1103 | return 0; | ||
1104 | |||
1105 | if (dmxdevfilter->buffer.error) | ||
1106 | mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); | ||
1107 | |||
1108 | if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer)) | ||
1109 | mask |= (POLLIN | POLLRDNORM | POLLPRI); | ||
1110 | |||
1111 | return mask; | ||
1112 | } | ||
1113 | |||
1114 | static int dvb_demux_release(struct inode *inode, struct file *file) | ||
1115 | { | ||
1116 | struct dmxdev_filter *dmxdevfilter = file->private_data; | ||
1117 | struct dmxdev *dmxdev = dmxdevfilter->dev; | ||
1118 | |||
1119 | int ret; | ||
1120 | |||
1121 | ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter); | ||
1122 | |||
1123 | mutex_lock(&dmxdev->mutex); | ||
1124 | dmxdev->dvbdev->users--; | ||
1125 | if(dmxdev->dvbdev->users==1 && dmxdev->exit==1) { | ||
1126 | fops_put(file->f_op); | ||
1127 | file->f_op = NULL; | ||
1128 | mutex_unlock(&dmxdev->mutex); | ||
1129 | wake_up(&dmxdev->dvbdev->wait_queue); | ||
1130 | } else | ||
1131 | mutex_unlock(&dmxdev->mutex); | ||
1132 | |||
1133 | return ret; | ||
1134 | } | ||
1135 | |||
1136 | static const struct file_operations dvb_demux_fops = { | ||
1137 | .owner = THIS_MODULE, | ||
1138 | .read = dvb_demux_read, | ||
1139 | .unlocked_ioctl = dvb_demux_ioctl, | ||
1140 | .open = dvb_demux_open, | ||
1141 | .release = dvb_demux_release, | ||
1142 | .poll = dvb_demux_poll, | ||
1143 | .llseek = default_llseek, | ||
1144 | }; | ||
1145 | |||
1146 | static struct dvb_device dvbdev_demux = { | ||
1147 | .priv = NULL, | ||
1148 | .users = 1, | ||
1149 | .writers = 1, | ||
1150 | .fops = &dvb_demux_fops | ||
1151 | }; | ||
1152 | |||
1153 | static int dvb_dvr_do_ioctl(struct file *file, | ||
1154 | unsigned int cmd, void *parg) | ||
1155 | { | ||
1156 | struct dvb_device *dvbdev = file->private_data; | ||
1157 | struct dmxdev *dmxdev = dvbdev->priv; | ||
1158 | unsigned long arg = (unsigned long)parg; | ||
1159 | int ret; | ||
1160 | |||
1161 | if (mutex_lock_interruptible(&dmxdev->mutex)) | ||
1162 | return -ERESTARTSYS; | ||
1163 | |||
1164 | switch (cmd) { | ||
1165 | case DMX_SET_BUFFER_SIZE: | ||
1166 | ret = dvb_dvr_set_buffer_size(dmxdev, arg); | ||
1167 | break; | ||
1168 | |||
1169 | default: | ||
1170 | ret = -EINVAL; | ||
1171 | break; | ||
1172 | } | ||
1173 | mutex_unlock(&dmxdev->mutex); | ||
1174 | return ret; | ||
1175 | } | ||
1176 | |||
1177 | static long dvb_dvr_ioctl(struct file *file, | ||
1178 | unsigned int cmd, unsigned long arg) | ||
1179 | { | ||
1180 | return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl); | ||
1181 | } | ||
1182 | |||
1183 | static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) | ||
1184 | { | ||
1185 | struct dvb_device *dvbdev = file->private_data; | ||
1186 | struct dmxdev *dmxdev = dvbdev->priv; | ||
1187 | unsigned int mask = 0; | ||
1188 | |||
1189 | dprintk("function : %s\n", __func__); | ||
1190 | |||
1191 | poll_wait(file, &dmxdev->dvr_buffer.queue, wait); | ||
1192 | |||
1193 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||
1194 | if (dmxdev->dvr_buffer.error) | ||
1195 | mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); | ||
1196 | |||
1197 | if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer)) | ||
1198 | mask |= (POLLIN | POLLRDNORM | POLLPRI); | ||
1199 | } else | ||
1200 | mask |= (POLLOUT | POLLWRNORM | POLLPRI); | ||
1201 | |||
1202 | return mask; | ||
1203 | } | ||
1204 | |||
1205 | static const struct file_operations dvb_dvr_fops = { | ||
1206 | .owner = THIS_MODULE, | ||
1207 | .read = dvb_dvr_read, | ||
1208 | .write = dvb_dvr_write, | ||
1209 | .unlocked_ioctl = dvb_dvr_ioctl, | ||
1210 | .open = dvb_dvr_open, | ||
1211 | .release = dvb_dvr_release, | ||
1212 | .poll = dvb_dvr_poll, | ||
1213 | .llseek = default_llseek, | ||
1214 | }; | ||
1215 | |||
1216 | static struct dvb_device dvbdev_dvr = { | ||
1217 | .priv = NULL, | ||
1218 | .readers = 1, | ||
1219 | .users = 1, | ||
1220 | .fops = &dvb_dvr_fops | ||
1221 | }; | ||
1222 | |||
1223 | int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) | ||
1224 | { | ||
1225 | int i; | ||
1226 | |||
1227 | if (dmxdev->demux->open(dmxdev->demux) < 0) | ||
1228 | return -EUSERS; | ||
1229 | |||
1230 | dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter)); | ||
1231 | if (!dmxdev->filter) | ||
1232 | return -ENOMEM; | ||
1233 | |||
1234 | mutex_init(&dmxdev->mutex); | ||
1235 | spin_lock_init(&dmxdev->lock); | ||
1236 | for (i = 0; i < dmxdev->filternum; i++) { | ||
1237 | dmxdev->filter[i].dev = dmxdev; | ||
1238 | dmxdev->filter[i].buffer.data = NULL; | ||
1239 | dvb_dmxdev_filter_state_set(&dmxdev->filter[i], | ||
1240 | DMXDEV_STATE_FREE); | ||
1241 | } | ||
1242 | |||
1243 | dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, | ||
1244 | DVB_DEVICE_DEMUX); | ||
1245 | dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, | ||
1246 | dmxdev, DVB_DEVICE_DVR); | ||
1247 | |||
1248 | dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); | ||
1249 | |||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1253 | EXPORT_SYMBOL(dvb_dmxdev_init); | ||
1254 | |||
1255 | void dvb_dmxdev_release(struct dmxdev *dmxdev) | ||
1256 | { | ||
1257 | dmxdev->exit=1; | ||
1258 | if (dmxdev->dvbdev->users > 1) { | ||
1259 | wait_event(dmxdev->dvbdev->wait_queue, | ||
1260 | dmxdev->dvbdev->users==1); | ||
1261 | } | ||
1262 | if (dmxdev->dvr_dvbdev->users > 1) { | ||
1263 | wait_event(dmxdev->dvr_dvbdev->wait_queue, | ||
1264 | dmxdev->dvr_dvbdev->users==1); | ||
1265 | } | ||
1266 | |||
1267 | dvb_unregister_device(dmxdev->dvbdev); | ||
1268 | dvb_unregister_device(dmxdev->dvr_dvbdev); | ||
1269 | |||
1270 | vfree(dmxdev->filter); | ||
1271 | dmxdev->filter = NULL; | ||
1272 | dmxdev->demux->close(dmxdev->demux); | ||
1273 | } | ||
1274 | |||
1275 | EXPORT_SYMBOL(dvb_dmxdev_release); | ||
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h deleted file mode 100644 index 02ebe28f830d..000000000000 --- a/drivers/media/dvb/dvb-core/dmxdev.h +++ /dev/null | |||
@@ -1,118 +0,0 @@ | |||
1 | /* | ||
2 | * dmxdev.h | ||
3 | * | ||
4 | * Copyright (C) 2000 Ralph Metzler & Marcus Metzler | ||
5 | * for convergence integrated media GmbH | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public License | ||
9 | * as published by the Free Software Foundation; either version 2.1 | ||
10 | * of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef _DMXDEV_H_ | ||
24 | #define _DMXDEV_H_ | ||
25 | |||
26 | #include <linux/types.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/timer.h> | ||
30 | #include <linux/wait.h> | ||
31 | #include <linux/fs.h> | ||
32 | #include <linux/string.h> | ||
33 | #include <linux/mutex.h> | ||
34 | #include <linux/slab.h> | ||
35 | |||
36 | #include <linux/dvb/dmx.h> | ||
37 | |||
38 | #include "dvbdev.h" | ||
39 | #include "demux.h" | ||
40 | #include "dvb_ringbuffer.h" | ||
41 | |||
42 | enum dmxdev_type { | ||
43 | DMXDEV_TYPE_NONE, | ||
44 | DMXDEV_TYPE_SEC, | ||
45 | DMXDEV_TYPE_PES, | ||
46 | }; | ||
47 | |||
48 | enum dmxdev_state { | ||
49 | DMXDEV_STATE_FREE, | ||
50 | DMXDEV_STATE_ALLOCATED, | ||
51 | DMXDEV_STATE_SET, | ||
52 | DMXDEV_STATE_GO, | ||
53 | DMXDEV_STATE_DONE, | ||
54 | DMXDEV_STATE_TIMEDOUT | ||
55 | }; | ||
56 | |||
57 | struct dmxdev_feed { | ||
58 | u16 pid; | ||
59 | struct dmx_ts_feed *ts; | ||
60 | struct list_head next; | ||
61 | }; | ||
62 | |||
63 | struct dmxdev_filter { | ||
64 | union { | ||
65 | struct dmx_section_filter *sec; | ||
66 | } filter; | ||
67 | |||
68 | union { | ||
69 | /* list of TS and PES feeds (struct dmxdev_feed) */ | ||
70 | struct list_head ts; | ||
71 | struct dmx_section_feed *sec; | ||
72 | } feed; | ||
73 | |||
74 | union { | ||
75 | struct dmx_sct_filter_params sec; | ||
76 | struct dmx_pes_filter_params pes; | ||
77 | } params; | ||
78 | |||
79 | enum dmxdev_type type; | ||
80 | enum dmxdev_state state; | ||
81 | struct dmxdev *dev; | ||
82 | struct dvb_ringbuffer buffer; | ||
83 | |||
84 | struct mutex mutex; | ||
85 | |||
86 | /* only for sections */ | ||
87 | struct timer_list timer; | ||
88 | int todo; | ||
89 | u8 secheader[3]; | ||
90 | }; | ||
91 | |||
92 | |||
93 | struct dmxdev { | ||
94 | struct dvb_device *dvbdev; | ||
95 | struct dvb_device *dvr_dvbdev; | ||
96 | |||
97 | struct dmxdev_filter *filter; | ||
98 | struct dmx_demux *demux; | ||
99 | |||
100 | int filternum; | ||
101 | int capabilities; | ||
102 | |||
103 | unsigned int exit:1; | ||
104 | #define DMXDEV_CAP_DUPLEX 1 | ||
105 | struct dmx_frontend *dvr_orig_fe; | ||
106 | |||
107 | struct dvb_ringbuffer dvr_buffer; | ||
108 | #define DVR_BUFFER_SIZE (10*188*1024) | ||
109 | |||
110 | struct mutex mutex; | ||
111 | spinlock_t lock; | ||
112 | }; | ||
113 | |||
114 | |||
115 | int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *); | ||
116 | void dvb_dmxdev_release(struct dmxdev *dmxdev); | ||
117 | |||
118 | #endif /* _DMXDEV_H_ */ | ||
diff --git a/drivers/media/dvb/dvb-core/dvb-usb-ids.h b/drivers/media/dvb/dvb-core/dvb-usb-ids.h deleted file mode 100644 index 26c44818a5ab..000000000000 --- a/drivers/media/dvb/dvb-core/dvb-usb-ids.h +++ /dev/null | |||
@@ -1,361 +0,0 @@ | |||
1 | /* dvb-usb-ids.h is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) see | ||
4 | * dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * a header file containing define's for the USB device supported by the | ||
7 | * various drivers. | ||
8 | */ | ||
9 | #ifndef _DVB_USB_IDS_H_ | ||
10 | #define _DVB_USB_IDS_H_ | ||
11 | |||
12 | /* Vendor IDs */ | ||
13 | #define USB_VID_ADSTECH 0x06e1 | ||
14 | #define USB_VID_AFATECH 0x15a4 | ||
15 | #define USB_VID_ALCOR_MICRO 0x058f | ||
16 | #define USB_VID_ALINK 0x05e3 | ||
17 | #define USB_VID_AMT 0x1c73 | ||
18 | #define USB_VID_ANCHOR 0x0547 | ||
19 | #define USB_VID_ANSONIC 0x10b9 | ||
20 | #define USB_VID_ANUBIS_ELECTRONIC 0x10fd | ||
21 | #define USB_VID_ASUS 0x0b05 | ||
22 | #define USB_VID_AVERMEDIA 0x07ca | ||
23 | #define USB_VID_COMPRO 0x185b | ||
24 | #define USB_VID_COMPRO_UNK 0x145f | ||
25 | #define USB_VID_CONEXANT 0x0572 | ||
26 | #define USB_VID_CYPRESS 0x04b4 | ||
27 | #define USB_VID_DIBCOM 0x10b8 | ||
28 | #define USB_VID_DPOSH 0x1498 | ||
29 | #define USB_VID_DVICO 0x0fe9 | ||
30 | #define USB_VID_E3C 0x18b4 | ||
31 | #define USB_VID_ELGATO 0x0fd9 | ||
32 | #define USB_VID_EMPIA 0xeb1a | ||
33 | #define USB_VID_GENPIX 0x09c0 | ||
34 | #define USB_VID_GRANDTEC 0x5032 | ||
35 | #define USB_VID_GTEK 0x1f4d | ||
36 | #define USB_VID_HANFTEK 0x15f4 | ||
37 | #define USB_VID_HAUPPAUGE 0x2040 | ||
38 | #define USB_VID_HYPER_PALTEK 0x1025 | ||
39 | #define USB_VID_INTEL 0x8086 | ||
40 | #define USB_VID_ITETECH 0x048d | ||
41 | #define USB_VID_KWORLD 0xeb2a | ||
42 | #define USB_VID_KWORLD_2 0x1b80 | ||
43 | #define USB_VID_KYE 0x0458 | ||
44 | #define USB_VID_LEADTEK 0x0413 | ||
45 | #define USB_VID_LITEON 0x04ca | ||
46 | #define USB_VID_MEDION 0x1660 | ||
47 | #define USB_VID_MIGLIA 0x18f3 | ||
48 | #define USB_VID_MSI 0x0db0 | ||
49 | #define USB_VID_MSI_2 0x1462 | ||
50 | #define USB_VID_OPERA1 0x695c | ||
51 | #define USB_VID_PINNACLE 0x2304 | ||
52 | #define USB_VID_PCTV 0x2013 | ||
53 | #define USB_VID_PIXELVIEW 0x1554 | ||
54 | #define USB_VID_REALTEK 0x0bda | ||
55 | #define USB_VID_TECHNOTREND 0x0b48 | ||
56 | #define USB_VID_TERRATEC 0x0ccd | ||
57 | #define USB_VID_TELESTAR 0x10b9 | ||
58 | #define USB_VID_VISIONPLUS 0x13d3 | ||
59 | #define USB_VID_SONY 0x1415 | ||
60 | #define USB_VID_TWINHAN 0x1822 | ||
61 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 | ||
62 | #define USB_VID_UNIWILL 0x1584 | ||
63 | #define USB_VID_WIDEVIEW 0x14aa | ||
64 | #define USB_VID_GIGABYTE 0x1044 | ||
65 | #define USB_VID_YUAN 0x1164 | ||
66 | #define USB_VID_XTENSIONS 0x1ae7 | ||
67 | #define USB_VID_HUMAX_COEX 0x10b9 | ||
68 | #define USB_VID_774 0x7a69 | ||
69 | #define USB_VID_EVOLUTEPC 0x1e59 | ||
70 | #define USB_VID_AZUREWAVE 0x13d3 | ||
71 | #define USB_VID_TECHNISAT 0x14f7 | ||
72 | |||
73 | /* Product IDs */ | ||
74 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 | ||
75 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 | ||
76 | #define USB_PID_AFATECH_AF9005 0x9020 | ||
77 | #define USB_PID_AFATECH_AF9015_9015 0x9015 | ||
78 | #define USB_PID_AFATECH_AF9015_9016 0x9016 | ||
79 | #define USB_PID_AFATECH_AF9035_1000 0x1000 | ||
80 | #define USB_PID_AFATECH_AF9035_1001 0x1001 | ||
81 | #define USB_PID_AFATECH_AF9035_1002 0x1002 | ||
82 | #define USB_PID_AFATECH_AF9035_1003 0x1003 | ||
83 | #define USB_PID_AFATECH_AF9035_9035 0x9035 | ||
84 | #define USB_PID_TREKSTOR_DVBT 0x901b | ||
85 | #define USB_VID_ALINK_DTU 0xf170 | ||
86 | #define USB_PID_ANSONIC_DVBT_USB 0x6000 | ||
87 | #define USB_PID_ANYSEE 0x861f | ||
88 | #define USB_PID_AZUREWAVE_AD_TU700 0x3237 | ||
89 | #define USB_PID_AZUREWAVE_6007 0x0ccd | ||
90 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 | ||
91 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 | ||
92 | #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 | ||
93 | #define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801 | ||
94 | #define USB_PID_COMPRO_DVBU2000_COLD 0xd000 | ||
95 | #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 | ||
96 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c | ||
97 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d | ||
98 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 | ||
99 | #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 | ||
100 | #define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397 | ||
101 | #define USB_PID_CONEXANT_D680_DMB 0x86d6 | ||
102 | #define USB_PID_CREATIX_CTX1921 0x1921 | ||
103 | #define USB_PID_DELOCK_USB2_DVBT 0xb803 | ||
104 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 | ||
105 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 | ||
106 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | ||
107 | #define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9 | ||
108 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 | ||
109 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 | ||
110 | #define USB_PID_DIBCOM_STK7700P 0x1e14 | ||
111 | #define USB_PID_DIBCOM_STK7700P_PC 0x1e78 | ||
112 | #define USB_PID_DIBCOM_STK7700D 0x1ef0 | ||
113 | #define USB_PID_DIBCOM_STK7700_U7000 0x7001 | ||
114 | #define USB_PID_DIBCOM_STK7070P 0x1ebc | ||
115 | #define USB_PID_DIBCOM_STK7070PD 0x1ebe | ||
116 | #define USB_PID_DIBCOM_STK807XP 0x1f90 | ||
117 | #define USB_PID_DIBCOM_STK807XPVR 0x1f98 | ||
118 | #define USB_PID_DIBCOM_STK8096GP 0x1fa0 | ||
119 | #define USB_PID_DIBCOM_NIM8096MD 0x1fa8 | ||
120 | #define USB_PID_DIBCOM_TFE8096P 0x1f9C | ||
121 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 | ||
122 | #define USB_PID_DIBCOM_STK7770P 0x1e80 | ||
123 | #define USB_PID_DIBCOM_NIM7090 0x1bb2 | ||
124 | #define USB_PID_DIBCOM_TFE7090PVR 0x1bb4 | ||
125 | #define USB_PID_DIBCOM_TFE7090E 0x1bb7 | ||
126 | #define USB_PID_DIBCOM_TFE7790E 0x1e6e | ||
127 | #define USB_PID_DIBCOM_NIM9090M 0x2383 | ||
128 | #define USB_PID_DIBCOM_NIM9090MD 0x2384 | ||
129 | #define USB_PID_DPOSH_M9206_COLD 0x9206 | ||
130 | #define USB_PID_DPOSH_M9206_WARM 0xa090 | ||
131 | #define USB_PID_E3C_EC168 0x1689 | ||
132 | #define USB_PID_E3C_EC168_2 0xfffa | ||
133 | #define USB_PID_E3C_EC168_3 0xfffb | ||
134 | #define USB_PID_E3C_EC168_4 0x1001 | ||
135 | #define USB_PID_E3C_EC168_5 0x1002 | ||
136 | #define USB_PID_FREECOM_DVBT 0x0160 | ||
137 | #define USB_PID_FREECOM_DVBT_2 0x0161 | ||
138 | #define USB_PID_UNIWILL_STK7700P 0x6003 | ||
139 | #define USB_PID_GENIUS_TVGO_DVB_T03 0x4012 | ||
140 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 | ||
141 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 | ||
142 | #define USB_PID_INTEL_CE9500 0x9500 | ||
143 | #define USB_PID_ITETECH_IT9135 0x9135 | ||
144 | #define USB_PID_ITETECH_IT9135_9005 0x9005 | ||
145 | #define USB_PID_ITETECH_IT9135_9006 0x9006 | ||
146 | #define USB_PID_KWORLD_399U 0xe399 | ||
147 | #define USB_PID_KWORLD_399U_2 0xe400 | ||
148 | #define USB_PID_KWORLD_395U 0xe396 | ||
149 | #define USB_PID_KWORLD_395U_2 0xe39b | ||
150 | #define USB_PID_KWORLD_395U_3 0xe395 | ||
151 | #define USB_PID_KWORLD_395U_4 0xe39a | ||
152 | #define USB_PID_KWORLD_MC810 0xc810 | ||
153 | #define USB_PID_KWORLD_PC160_2T 0xc160 | ||
154 | #define USB_PID_KWORLD_PC160_T 0xc161 | ||
155 | #define USB_PID_KWORLD_UB383_T 0xe383 | ||
156 | #define USB_PID_KWORLD_UB499_2T_T09 0xe409 | ||
157 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de | ||
158 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df | ||
159 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 | ||
160 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069 | ||
161 | #define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093 | ||
162 | #define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097 | ||
163 | #define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099 | ||
164 | #define USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1 0x00a9 | ||
165 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 | ||
166 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 | ||
167 | #define USB_PID_TWINHAN_VP7020_COLD 0x3203 | ||
168 | #define USB_PID_TWINHAN_VP7020_WARM 0x3204 | ||
169 | #define USB_PID_TWINHAN_VP7045_COLD 0x3205 | ||
170 | #define USB_PID_TWINHAN_VP7045_WARM 0x3206 | ||
171 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 | ||
172 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 | ||
173 | #define USB_PID_TINYTWIN 0x3226 | ||
174 | #define USB_PID_TINYTWIN_2 0xe402 | ||
175 | #define USB_PID_TINYTWIN_3 0x9016 | ||
176 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 | ||
177 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 | ||
178 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 | ||
179 | #define USB_PID_ULTIMA_TVBOX_WARM 0x8106 | ||
180 | #define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107 | ||
181 | #define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108 | ||
182 | #define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235 | ||
183 | #define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109 | ||
184 | #define USB_PID_ULTIMA_TVBOX_USB2_WARM 0x810a | ||
185 | #define USB_PID_ARTEC_T14_COLD 0x810b | ||
186 | #define USB_PID_ARTEC_T14_WARM 0x810c | ||
187 | #define USB_PID_ARTEC_T14BR 0x810f | ||
188 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613 | ||
189 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002 | ||
190 | #define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e | ||
191 | #define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f | ||
192 | #define USB_PID_HANFTEK_UMT_010_COLD 0x0001 | ||
193 | #define USB_PID_HANFTEK_UMT_010_WARM 0x0015 | ||
194 | #define USB_PID_DTT200U_COLD 0x0201 | ||
195 | #define USB_PID_DTT200U_WARM 0x0301 | ||
196 | #define USB_PID_WT220U_ZAP250_COLD 0x0220 | ||
197 | #define USB_PID_WT220U_COLD 0x0222 | ||
198 | #define USB_PID_WT220U_WARM 0x0221 | ||
199 | #define USB_PID_WT220U_FC_COLD 0x0225 | ||
200 | #define USB_PID_WT220U_FC_WARM 0x0226 | ||
201 | #define USB_PID_WT220U_ZL0353_COLD 0x022a | ||
202 | #define USB_PID_WT220U_ZL0353_WARM 0x022b | ||
203 | #define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300 | ||
204 | #define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 | ||
205 | #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 | ||
206 | #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 | ||
207 | #define USB_PID_HAUPPAUGE_NOVA_T_500_3 0x8400 | ||
208 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 | ||
209 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 | ||
210 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070 | ||
211 | #define USB_PID_HAUPPAUGE_MYTV_T 0x7080 | ||
212 | #define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580 | ||
213 | #define USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009 0x5200 | ||
214 | #define USB_PID_HAUPPAUGE_TIGER_ATSC 0xb200 | ||
215 | #define USB_PID_HAUPPAUGE_TIGER_ATSC_B210 0xb210 | ||
216 | #define USB_PID_AVERMEDIA_EXPRESS 0xb568 | ||
217 | #define USB_PID_AVERMEDIA_VOLAR 0xa807 | ||
218 | #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 | ||
219 | #define USB_PID_AVERMEDIA_VOLAR_A868R 0xa868 | ||
220 | #define USB_PID_AVERMEDIA_MCE_USB_M038 0x1228 | ||
221 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039 | ||
222 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039 | ||
223 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039 | ||
224 | #define USB_PID_AVERMEDIA_VOLAR_X 0xa815 | ||
225 | #define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150 | ||
226 | #define USB_PID_AVERMEDIA_A309 0xa309 | ||
227 | #define USB_PID_AVERMEDIA_A310 0xa310 | ||
228 | #define USB_PID_AVERMEDIA_A850 0x850a | ||
229 | #define USB_PID_AVERMEDIA_A850T 0x850b | ||
230 | #define USB_PID_AVERMEDIA_A805 0xa805 | ||
231 | #define USB_PID_AVERMEDIA_A815M 0x815a | ||
232 | #define USB_PID_AVERMEDIA_A835 0xa835 | ||
233 | #define USB_PID_AVERMEDIA_B835 0xb835 | ||
234 | #define USB_PID_AVERMEDIA_1867 0x1867 | ||
235 | #define USB_PID_AVERMEDIA_A867 0xa867 | ||
236 | #define USB_PID_AVERMEDIA_TWINSTAR 0x0825 | ||
237 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 | ||
238 | #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d | ||
239 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a | ||
240 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 | ||
241 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 | ||
242 | #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 | ||
243 | #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 | ||
244 | #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 | ||
245 | #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab | ||
246 | #define USB_PID_TERRATEC_H7 0x10b4 | ||
247 | #define USB_PID_TERRATEC_H7_2 0x10a3 | ||
248 | #define USB_PID_TERRATEC_T3 0x10a0 | ||
249 | #define USB_PID_TERRATEC_T5 0x10a1 | ||
250 | #define USB_PID_NOXON_DAB_STICK 0x00b3 | ||
251 | #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e | ||
252 | #define USB_PID_PINNACLE_PCTV2000E 0x022c | ||
253 | #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 | ||
254 | #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229 | ||
255 | #define USB_PID_PINNACLE_PCTV71E 0x022b | ||
256 | #define USB_PID_PINNACLE_PCTV72E 0x0236 | ||
257 | #define USB_PID_PINNACLE_PCTV73E 0x0237 | ||
258 | #define USB_PID_PINNACLE_PCTV310E 0x3211 | ||
259 | #define USB_PID_PINNACLE_PCTV801E 0x023a | ||
260 | #define USB_PID_PINNACLE_PCTV801E_SE 0x023b | ||
261 | #define USB_PID_PINNACLE_PCTV340E 0x023d | ||
262 | #define USB_PID_PINNACLE_PCTV340E_SE 0x023e | ||
263 | #define USB_PID_PINNACLE_PCTV73A 0x0243 | ||
264 | #define USB_PID_PINNACLE_PCTV73ESE 0x0245 | ||
265 | #define USB_PID_PINNACLE_PCTV74E 0x0246 | ||
266 | #define USB_PID_PINNACLE_PCTV282E 0x0248 | ||
267 | #define USB_PID_PIXELVIEW_SBTVD 0x5010 | ||
268 | #define USB_PID_PCTV_200E 0x020e | ||
269 | #define USB_PID_PCTV_400E 0x020f | ||
270 | #define USB_PID_PCTV_450E 0x0222 | ||
271 | #define USB_PID_PCTV_452E 0x021f | ||
272 | #define USB_PID_REALTEK_RTL2831U 0x2831 | ||
273 | #define USB_PID_REALTEK_RTL2832U 0x2832 | ||
274 | #define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007 | ||
275 | #define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI 0x300a | ||
276 | #define USB_PID_NEBULA_DIGITV 0x0201 | ||
277 | #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 | ||
278 | #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 | ||
279 | #define USB_PID_DVICO_BLUEBIRD_LG064F_WARM 0xd501 | ||
280 | #define USB_PID_DVICO_BLUEBIRD_LGZ201_COLD 0xdb00 | ||
281 | #define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM 0xdb01 | ||
282 | #define USB_PID_DVICO_BLUEBIRD_TH7579_COLD 0xdb10 | ||
283 | #define USB_PID_DVICO_BLUEBIRD_TH7579_WARM 0xdb11 | ||
284 | #define USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD 0xdb50 | ||
285 | #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51 | ||
286 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 | ||
287 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 | ||
288 | #define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78 | ||
289 | #define USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2 0xdb98 | ||
290 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70 | ||
291 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71 | ||
292 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 | ||
293 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 | ||
294 | #define USB_PID_MEDION_MD95700 0x0932 | ||
295 | #define USB_PID_MSI_MEGASKY580 0x5580 | ||
296 | #define USB_PID_MSI_MEGASKY580_55801 0x5581 | ||
297 | #define USB_PID_KYE_DVB_T_COLD 0x701e | ||
298 | #define USB_PID_KYE_DVB_T_WARM 0x701f | ||
299 | #define USB_PID_LITEON_DVB_T_COLD 0xf000 | ||
300 | #define USB_PID_LITEON_DVB_T_WARM 0xf001 | ||
301 | #define USB_PID_DIGIVOX_MINI_SL_COLD 0xe360 | ||
302 | #define USB_PID_DIGIVOX_MINI_SL_WARM 0xe361 | ||
303 | #define USB_PID_GRANDTEC_DVBT_USB2_COLD 0x0bc6 | ||
304 | #define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 | ||
305 | #define USB_PID_WINFAST_DTV2000DS 0x6a04 | ||
306 | #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 | ||
307 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 | ||
308 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 | ||
309 | #define USB_PID_WINFAST_DTV_DONGLE_H 0x60f6 | ||
310 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01 | ||
311 | #define USB_PID_WINFAST_DTV_DONGLE_GOLD 0x6029 | ||
312 | #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 | ||
313 | #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201 | ||
314 | #define USB_PID_GENPIX_8PSK_REV_2 0x0202 | ||
315 | #define USB_PID_GENPIX_SKYWALKER_1 0x0203 | ||
316 | #define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204 | ||
317 | #define USB_PID_GENPIX_SKYWALKER_2 0x0206 | ||
318 | #define USB_PID_SIGMATEK_DVB_110 0x6610 | ||
319 | #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 | ||
320 | #define USB_PID_MSI_DIGIVOX_DUO 0x8801 | ||
321 | #define USB_PID_OPERA1_COLD 0x2830 | ||
322 | #define USB_PID_OPERA1_WARM 0x3829 | ||
323 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 | ||
324 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 | ||
325 | #define USB_PID_GIGABYTE_U7000 0x7001 | ||
326 | #define USB_PID_GIGABYTE_U8000 0x7002 | ||
327 | #define USB_PID_ASUS_U3000 0x171f | ||
328 | #define USB_PID_ASUS_U3000H 0x1736 | ||
329 | #define USB_PID_ASUS_U3100 0x173f | ||
330 | #define USB_PID_YUAN_EC372S 0x1edc | ||
331 | #define USB_PID_YUAN_STK7700PH 0x1f08 | ||
332 | #define USB_PID_YUAN_PD378S 0x2edc | ||
333 | #define USB_PID_YUAN_MC770 0x0871 | ||
334 | #define USB_PID_YUAN_STK7700D 0x1efc | ||
335 | #define USB_PID_YUAN_STK7700D_2 0x1e8c | ||
336 | #define USB_PID_DW2102 0x2102 | ||
337 | #define USB_PID_XTENSIONS_XD_380 0x0381 | ||
338 | #define USB_PID_TELESTAR_STARSTICK_2 0x8000 | ||
339 | #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 | ||
340 | #define USB_PID_SONY_PLAYTV 0x0003 | ||
341 | #define USB_PID_MYGICA_D689 0xd811 | ||
342 | #define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011 | ||
343 | #define USB_PID_ELGATO_EYETV_DTT 0x0021 | ||
344 | #define USB_PID_ELGATO_EYETV_DTT_2 0x003f | ||
345 | #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 | ||
346 | #define USB_PID_ELGATO_EYETV_SAT 0x002a | ||
347 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 | ||
348 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001 | ||
349 | #define USB_PID_FRIIO_WHITE 0x0001 | ||
350 | #define USB_PID_TVWAY_PLUS 0x0002 | ||
351 | #define USB_PID_SVEON_STV20 0xe39d | ||
352 | #define USB_PID_SVEON_STV22 0xe401 | ||
353 | #define USB_PID_SVEON_STV22_IT9137 0xe411 | ||
354 | #define USB_PID_AZUREWAVE_AZ6027 0x3275 | ||
355 | #define USB_PID_TERRATEC_DVBS2CI_V1 0x10a4 | ||
356 | #define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac | ||
357 | #define USB_PID_TECHNISAT_USB2_HDCI_V1 0x0001 | ||
358 | #define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002 | ||
359 | #define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004 | ||
360 | #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 | ||
361 | #endif | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c deleted file mode 100644 index 9be65a3b931f..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ /dev/null | |||
@@ -1,1753 +0,0 @@ | |||
1 | /* | ||
2 | * dvb_ca.c: generic DVB functions for EN50221 CAM interfaces | ||
3 | * | ||
4 | * Copyright (C) 2004 Andrew de Quincey | ||
5 | * | ||
6 | * Parts of this file were based on sources as follows: | ||
7 | * | ||
8 | * Copyright (C) 2003 Ralph Metzler <rjkm@metzlerbros.de> | ||
9 | * | ||
10 | * based on code: | ||
11 | * | ||
12 | * Copyright (C) 1999-2002 Ralph Metzler | ||
13 | * & Marcus Metzler for convergence integrated media GmbH | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * as published by the Free Software Foundation; either version 2 | ||
18 | * of the License, or (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
28 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
29 | */ | ||
30 | |||
31 | #include <linux/errno.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/list.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/vmalloc.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/spinlock.h> | ||
38 | #include <linux/sched.h> | ||
39 | #include <linux/kthread.h> | ||
40 | |||
41 | #include "dvb_ca_en50221.h" | ||
42 | #include "dvb_ringbuffer.h" | ||
43 | |||
44 | static int dvb_ca_en50221_debug; | ||
45 | |||
46 | module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644); | ||
47 | MODULE_PARM_DESC(cam_debug, "enable verbose debug messages"); | ||
48 | |||
49 | #define dprintk if (dvb_ca_en50221_debug) printk | ||
50 | |||
51 | #define INIT_TIMEOUT_SECS 10 | ||
52 | |||
53 | #define HOST_LINK_BUF_SIZE 0x200 | ||
54 | |||
55 | #define RX_BUFFER_SIZE 65535 | ||
56 | |||
57 | #define MAX_RX_PACKETS_PER_ITERATION 10 | ||
58 | |||
59 | #define CTRLIF_DATA 0 | ||
60 | #define CTRLIF_COMMAND 1 | ||
61 | #define CTRLIF_STATUS 1 | ||
62 | #define CTRLIF_SIZE_LOW 2 | ||
63 | #define CTRLIF_SIZE_HIGH 3 | ||
64 | |||
65 | #define CMDREG_HC 1 /* Host control */ | ||
66 | #define CMDREG_SW 2 /* Size write */ | ||
67 | #define CMDREG_SR 4 /* Size read */ | ||
68 | #define CMDREG_RS 8 /* Reset interface */ | ||
69 | #define CMDREG_FRIE 0x40 /* Enable FR interrupt */ | ||
70 | #define CMDREG_DAIE 0x80 /* Enable DA interrupt */ | ||
71 | #define IRQEN (CMDREG_DAIE) | ||
72 | |||
73 | #define STATUSREG_RE 1 /* read error */ | ||
74 | #define STATUSREG_WE 2 /* write error */ | ||
75 | #define STATUSREG_FR 0x40 /* module free */ | ||
76 | #define STATUSREG_DA 0x80 /* data available */ | ||
77 | #define STATUSREG_TXERR (STATUSREG_RE|STATUSREG_WE) /* general transfer error */ | ||
78 | |||
79 | |||
80 | #define DVB_CA_SLOTSTATE_NONE 0 | ||
81 | #define DVB_CA_SLOTSTATE_UNINITIALISED 1 | ||
82 | #define DVB_CA_SLOTSTATE_RUNNING 2 | ||
83 | #define DVB_CA_SLOTSTATE_INVALID 3 | ||
84 | #define DVB_CA_SLOTSTATE_WAITREADY 4 | ||
85 | #define DVB_CA_SLOTSTATE_VALIDATE 5 | ||
86 | #define DVB_CA_SLOTSTATE_WAITFR 6 | ||
87 | #define DVB_CA_SLOTSTATE_LINKINIT 7 | ||
88 | |||
89 | |||
90 | /* Information on a CA slot */ | ||
91 | struct dvb_ca_slot { | ||
92 | |||
93 | /* current state of the CAM */ | ||
94 | int slot_state; | ||
95 | |||
96 | /* mutex used for serializing access to one CI slot */ | ||
97 | struct mutex slot_lock; | ||
98 | |||
99 | /* Number of CAMCHANGES that have occurred since last processing */ | ||
100 | atomic_t camchange_count; | ||
101 | |||
102 | /* Type of last CAMCHANGE */ | ||
103 | int camchange_type; | ||
104 | |||
105 | /* base address of CAM config */ | ||
106 | u32 config_base; | ||
107 | |||
108 | /* value to write into Config Control register */ | ||
109 | u8 config_option; | ||
110 | |||
111 | /* if 1, the CAM supports DA IRQs */ | ||
112 | u8 da_irq_supported:1; | ||
113 | |||
114 | /* size of the buffer to use when talking to the CAM */ | ||
115 | int link_buf_size; | ||
116 | |||
117 | /* buffer for incoming packets */ | ||
118 | struct dvb_ringbuffer rx_buffer; | ||
119 | |||
120 | /* timer used during various states of the slot */ | ||
121 | unsigned long timeout; | ||
122 | }; | ||
123 | |||
124 | /* Private CA-interface information */ | ||
125 | struct dvb_ca_private { | ||
126 | |||
127 | /* pointer back to the public data structure */ | ||
128 | struct dvb_ca_en50221 *pub; | ||
129 | |||
130 | /* the DVB device */ | ||
131 | struct dvb_device *dvbdev; | ||
132 | |||
133 | /* Flags describing the interface (DVB_CA_FLAG_*) */ | ||
134 | u32 flags; | ||
135 | |||
136 | /* number of slots supported by this CA interface */ | ||
137 | unsigned int slot_count; | ||
138 | |||
139 | /* information on each slot */ | ||
140 | struct dvb_ca_slot *slot_info; | ||
141 | |||
142 | /* wait queues for read() and write() operations */ | ||
143 | wait_queue_head_t wait_queue; | ||
144 | |||
145 | /* PID of the monitoring thread */ | ||
146 | struct task_struct *thread; | ||
147 | |||
148 | /* Flag indicating if the CA device is open */ | ||
149 | unsigned int open:1; | ||
150 | |||
151 | /* Flag indicating the thread should wake up now */ | ||
152 | unsigned int wakeup:1; | ||
153 | |||
154 | /* Delay the main thread should use */ | ||
155 | unsigned long delay; | ||
156 | |||
157 | /* Slot to start looking for data to read from in the next user-space read operation */ | ||
158 | int next_read_slot; | ||
159 | }; | ||
160 | |||
161 | static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca); | ||
162 | static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount); | ||
163 | static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount); | ||
164 | |||
165 | |||
166 | /** | ||
167 | * Safely find needle in haystack. | ||
168 | * | ||
169 | * @param haystack Buffer to look in. | ||
170 | * @param hlen Number of bytes in haystack. | ||
171 | * @param needle Buffer to find. | ||
172 | * @param nlen Number of bytes in needle. | ||
173 | * @return Pointer into haystack needle was found at, or NULL if not found. | ||
174 | */ | ||
175 | static char *findstr(char * haystack, int hlen, char * needle, int nlen) | ||
176 | { | ||
177 | int i; | ||
178 | |||
179 | if (hlen < nlen) | ||
180 | return NULL; | ||
181 | |||
182 | for (i = 0; i <= hlen - nlen; i++) { | ||
183 | if (!strncmp(haystack + i, needle, nlen)) | ||
184 | return haystack + i; | ||
185 | } | ||
186 | |||
187 | return NULL; | ||
188 | } | ||
189 | |||
190 | |||
191 | |||
192 | /* ******************************************************************************** */ | ||
193 | /* EN50221 physical interface functions */ | ||
194 | |||
195 | |||
196 | /** | ||
197 | * Check CAM status. | ||
198 | */ | ||
199 | static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot) | ||
200 | { | ||
201 | int slot_status; | ||
202 | int cam_present_now; | ||
203 | int cam_changed; | ||
204 | |||
205 | /* IRQ mode */ | ||
206 | if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) { | ||
207 | return (atomic_read(&ca->slot_info[slot].camchange_count) != 0); | ||
208 | } | ||
209 | |||
210 | /* poll mode */ | ||
211 | slot_status = ca->pub->poll_slot_status(ca->pub, slot, ca->open); | ||
212 | |||
213 | cam_present_now = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1 : 0; | ||
214 | cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1 : 0; | ||
215 | if (!cam_changed) { | ||
216 | int cam_present_old = (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE); | ||
217 | cam_changed = (cam_present_now != cam_present_old); | ||
218 | } | ||
219 | |||
220 | if (cam_changed) { | ||
221 | if (!cam_present_now) { | ||
222 | ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; | ||
223 | } else { | ||
224 | ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_INSERTED; | ||
225 | } | ||
226 | atomic_set(&ca->slot_info[slot].camchange_count, 1); | ||
227 | } else { | ||
228 | if ((ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) && | ||
229 | (slot_status & DVB_CA_EN50221_POLL_CAM_READY)) { | ||
230 | // move to validate state if reset is completed | ||
231 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | return cam_changed; | ||
236 | } | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Wait for flags to become set on the STATUS register on a CAM interface, | ||
241 | * checking for errors and timeout. | ||
242 | * | ||
243 | * @param ca CA instance. | ||
244 | * @param slot Slot on interface. | ||
245 | * @param waitfor Flags to wait for. | ||
246 | * @param timeout_ms Timeout in milliseconds. | ||
247 | * | ||
248 | * @return 0 on success, nonzero on error. | ||
249 | */ | ||
250 | static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot, | ||
251 | u8 waitfor, int timeout_hz) | ||
252 | { | ||
253 | unsigned long timeout; | ||
254 | unsigned long start; | ||
255 | |||
256 | dprintk("%s\n", __func__); | ||
257 | |||
258 | /* loop until timeout elapsed */ | ||
259 | start = jiffies; | ||
260 | timeout = jiffies + timeout_hz; | ||
261 | while (1) { | ||
262 | /* read the status and check for error */ | ||
263 | int res = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS); | ||
264 | if (res < 0) | ||
265 | return -EIO; | ||
266 | |||
267 | /* if we got the flags, it was successful! */ | ||
268 | if (res & waitfor) { | ||
269 | dprintk("%s succeeded timeout:%lu\n", __func__, jiffies - start); | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | /* check for timeout */ | ||
274 | if (time_after(jiffies, timeout)) { | ||
275 | break; | ||
276 | } | ||
277 | |||
278 | /* wait for a bit */ | ||
279 | msleep(1); | ||
280 | } | ||
281 | |||
282 | dprintk("%s failed timeout:%lu\n", __func__, jiffies - start); | ||
283 | |||
284 | /* if we get here, we've timed out */ | ||
285 | return -ETIMEDOUT; | ||
286 | } | ||
287 | |||
288 | |||
289 | /** | ||
290 | * Initialise the link layer connection to a CAM. | ||
291 | * | ||
292 | * @param ca CA instance. | ||
293 | * @param slot Slot id. | ||
294 | * | ||
295 | * @return 0 on success, nonzero on failure. | ||
296 | */ | ||
297 | static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) | ||
298 | { | ||
299 | int ret; | ||
300 | int buf_size; | ||
301 | u8 buf[2]; | ||
302 | |||
303 | dprintk("%s\n", __func__); | ||
304 | |||
305 | /* we'll be determining these during this function */ | ||
306 | ca->slot_info[slot].da_irq_supported = 0; | ||
307 | |||
308 | /* set the host link buffer size temporarily. it will be overwritten with the | ||
309 | * real negotiated size later. */ | ||
310 | ca->slot_info[slot].link_buf_size = 2; | ||
311 | |||
312 | /* read the buffer size from the CAM */ | ||
313 | if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0) | ||
314 | return ret; | ||
315 | if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0) | ||
316 | return ret; | ||
317 | if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2) | ||
318 | return -EIO; | ||
319 | if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) | ||
320 | return ret; | ||
321 | |||
322 | /* store it, and choose the minimum of our buffer and the CAM's buffer size */ | ||
323 | buf_size = (buf[0] << 8) | buf[1]; | ||
324 | if (buf_size > HOST_LINK_BUF_SIZE) | ||
325 | buf_size = HOST_LINK_BUF_SIZE; | ||
326 | ca->slot_info[slot].link_buf_size = buf_size; | ||
327 | buf[0] = buf_size >> 8; | ||
328 | buf[1] = buf_size & 0xff; | ||
329 | dprintk("Chosen link buffer size of %i\n", buf_size); | ||
330 | |||
331 | /* write the buffer size to the CAM */ | ||
332 | if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0) | ||
333 | return ret; | ||
334 | if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10)) != 0) | ||
335 | return ret; | ||
336 | if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2) | ||
337 | return -EIO; | ||
338 | if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) | ||
339 | return ret; | ||
340 | |||
341 | /* success */ | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | /** | ||
346 | * Read a tuple from attribute memory. | ||
347 | * | ||
348 | * @param ca CA instance. | ||
349 | * @param slot Slot id. | ||
350 | * @param address Address to read from. Updated. | ||
351 | * @param tupleType Tuple id byte. Updated. | ||
352 | * @param tupleLength Tuple length. Updated. | ||
353 | * @param tuple Dest buffer for tuple (must be 256 bytes). Updated. | ||
354 | * | ||
355 | * @return 0 on success, nonzero on error. | ||
356 | */ | ||
357 | static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, int slot, | ||
358 | int *address, int *tupleType, int *tupleLength, u8 * tuple) | ||
359 | { | ||
360 | int i; | ||
361 | int _tupleType; | ||
362 | int _tupleLength; | ||
363 | int _address = *address; | ||
364 | |||
365 | /* grab the next tuple length and type */ | ||
366 | if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0) | ||
367 | return _tupleType; | ||
368 | if (_tupleType == 0xff) { | ||
369 | dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType); | ||
370 | *address += 2; | ||
371 | *tupleType = _tupleType; | ||
372 | *tupleLength = 0; | ||
373 | return 0; | ||
374 | } | ||
375 | if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address + 2)) < 0) | ||
376 | return _tupleLength; | ||
377 | _address += 4; | ||
378 | |||
379 | dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength); | ||
380 | |||
381 | /* read in the whole tuple */ | ||
382 | for (i = 0; i < _tupleLength; i++) { | ||
383 | tuple[i] = ca->pub->read_attribute_mem(ca->pub, slot, _address + (i * 2)); | ||
384 | dprintk(" 0x%02x: 0x%02x %c\n", | ||
385 | i, tuple[i] & 0xff, | ||
386 | ((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.'); | ||
387 | } | ||
388 | _address += (_tupleLength * 2); | ||
389 | |||
390 | // success | ||
391 | *tupleType = _tupleType; | ||
392 | *tupleLength = _tupleLength; | ||
393 | *address = _address; | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | |||
398 | /** | ||
399 | * Parse attribute memory of a CAM module, extracting Config register, and checking | ||
400 | * it is a DVB CAM module. | ||
401 | * | ||
402 | * @param ca CA instance. | ||
403 | * @param slot Slot id. | ||
404 | * | ||
405 | * @return 0 on success, <0 on failure. | ||
406 | */ | ||
407 | static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot) | ||
408 | { | ||
409 | int address = 0; | ||
410 | int tupleLength; | ||
411 | int tupleType; | ||
412 | u8 tuple[257]; | ||
413 | char *dvb_str; | ||
414 | int rasz; | ||
415 | int status; | ||
416 | int got_cftableentry = 0; | ||
417 | int end_chain = 0; | ||
418 | int i; | ||
419 | u16 manfid = 0; | ||
420 | u16 devid = 0; | ||
421 | |||
422 | |||
423 | // CISTPL_DEVICE_0A | ||
424 | if ((status = | ||
425 | dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) | ||
426 | return status; | ||
427 | if (tupleType != 0x1D) | ||
428 | return -EINVAL; | ||
429 | |||
430 | |||
431 | |||
432 | // CISTPL_DEVICE_0C | ||
433 | if ((status = | ||
434 | dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) | ||
435 | return status; | ||
436 | if (tupleType != 0x1C) | ||
437 | return -EINVAL; | ||
438 | |||
439 | |||
440 | |||
441 | // CISTPL_VERS_1 | ||
442 | if ((status = | ||
443 | dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) | ||
444 | return status; | ||
445 | if (tupleType != 0x15) | ||
446 | return -EINVAL; | ||
447 | |||
448 | |||
449 | |||
450 | // CISTPL_MANFID | ||
451 | if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, | ||
452 | &tupleLength, tuple)) < 0) | ||
453 | return status; | ||
454 | if (tupleType != 0x20) | ||
455 | return -EINVAL; | ||
456 | if (tupleLength != 4) | ||
457 | return -EINVAL; | ||
458 | manfid = (tuple[1] << 8) | tuple[0]; | ||
459 | devid = (tuple[3] << 8) | tuple[2]; | ||
460 | |||
461 | |||
462 | |||
463 | // CISTPL_CONFIG | ||
464 | if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, | ||
465 | &tupleLength, tuple)) < 0) | ||
466 | return status; | ||
467 | if (tupleType != 0x1A) | ||
468 | return -EINVAL; | ||
469 | if (tupleLength < 3) | ||
470 | return -EINVAL; | ||
471 | |||
472 | /* extract the configbase */ | ||
473 | rasz = tuple[0] & 3; | ||
474 | if (tupleLength < (3 + rasz + 14)) | ||
475 | return -EINVAL; | ||
476 | ca->slot_info[slot].config_base = 0; | ||
477 | for (i = 0; i < rasz + 1; i++) { | ||
478 | ca->slot_info[slot].config_base |= (tuple[2 + i] << (8 * i)); | ||
479 | } | ||
480 | |||
481 | /* check it contains the correct DVB string */ | ||
482 | dvb_str = findstr((char *)tuple, tupleLength, "DVB_CI_V", 8); | ||
483 | if (dvb_str == NULL) | ||
484 | return -EINVAL; | ||
485 | if (tupleLength < ((dvb_str - (char *) tuple) + 12)) | ||
486 | return -EINVAL; | ||
487 | |||
488 | /* is it a version we support? */ | ||
489 | if (strncmp(dvb_str + 8, "1.00", 4)) { | ||
490 | printk("dvb_ca adapter %d: Unsupported DVB CAM module version %c%c%c%c\n", | ||
491 | ca->dvbdev->adapter->num, dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]); | ||
492 | return -EINVAL; | ||
493 | } | ||
494 | |||
495 | /* process the CFTABLE_ENTRY tuples, and any after those */ | ||
496 | while ((!end_chain) && (address < 0x1000)) { | ||
497 | if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, | ||
498 | &tupleLength, tuple)) < 0) | ||
499 | return status; | ||
500 | switch (tupleType) { | ||
501 | case 0x1B: // CISTPL_CFTABLE_ENTRY | ||
502 | if (tupleLength < (2 + 11 + 17)) | ||
503 | break; | ||
504 | |||
505 | /* if we've already parsed one, just use it */ | ||
506 | if (got_cftableentry) | ||
507 | break; | ||
508 | |||
509 | /* get the config option */ | ||
510 | ca->slot_info[slot].config_option = tuple[0] & 0x3f; | ||
511 | |||
512 | /* OK, check it contains the correct strings */ | ||
513 | if ((findstr((char *)tuple, tupleLength, "DVB_HOST", 8) == NULL) || | ||
514 | (findstr((char *)tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL)) | ||
515 | break; | ||
516 | |||
517 | got_cftableentry = 1; | ||
518 | break; | ||
519 | |||
520 | case 0x14: // CISTPL_NO_LINK | ||
521 | break; | ||
522 | |||
523 | case 0xFF: // CISTPL_END | ||
524 | end_chain = 1; | ||
525 | break; | ||
526 | |||
527 | default: /* Unknown tuple type - just skip this tuple and move to the next one */ | ||
528 | dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType, | ||
529 | tupleLength); | ||
530 | break; | ||
531 | } | ||
532 | } | ||
533 | |||
534 | if ((address > 0x1000) || (!got_cftableentry)) | ||
535 | return -EINVAL; | ||
536 | |||
537 | dprintk("Valid DVB CAM detected MANID:%x DEVID:%x CONFIGBASE:0x%x CONFIGOPTION:0x%x\n", | ||
538 | manfid, devid, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option); | ||
539 | |||
540 | // success! | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | |||
545 | /** | ||
546 | * Set CAM's configoption correctly. | ||
547 | * | ||
548 | * @param ca CA instance. | ||
549 | * @param slot Slot containing the CAM. | ||
550 | */ | ||
551 | static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot) | ||
552 | { | ||
553 | int configoption; | ||
554 | |||
555 | dprintk("%s\n", __func__); | ||
556 | |||
557 | /* set the config option */ | ||
558 | ca->pub->write_attribute_mem(ca->pub, slot, | ||
559 | ca->slot_info[slot].config_base, | ||
560 | ca->slot_info[slot].config_option); | ||
561 | |||
562 | /* check it */ | ||
563 | configoption = ca->pub->read_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base); | ||
564 | dprintk("Set configoption 0x%x, read configoption 0x%x\n", | ||
565 | ca->slot_info[slot].config_option, configoption & 0x3f); | ||
566 | |||
567 | /* fine! */ | ||
568 | return 0; | ||
569 | |||
570 | } | ||
571 | |||
572 | |||
573 | /** | ||
574 | * This function talks to an EN50221 CAM control interface. It reads a buffer of | ||
575 | * data from the CAM. The data can either be stored in a supplied buffer, or | ||
576 | * automatically be added to the slot's rx_buffer. | ||
577 | * | ||
578 | * @param ca CA instance. | ||
579 | * @param slot Slot to read from. | ||
580 | * @param ebuf If non-NULL, the data will be written to this buffer. If NULL, | ||
581 | * the data will be added into the buffering system as a normal fragment. | ||
582 | * @param ecount Size of ebuf. Ignored if ebuf is NULL. | ||
583 | * | ||
584 | * @return Number of bytes read, or < 0 on error | ||
585 | */ | ||
586 | static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount) | ||
587 | { | ||
588 | int bytes_read; | ||
589 | int status; | ||
590 | u8 buf[HOST_LINK_BUF_SIZE]; | ||
591 | int i; | ||
592 | |||
593 | dprintk("%s\n", __func__); | ||
594 | |||
595 | /* check if we have space for a link buf in the rx_buffer */ | ||
596 | if (ebuf == NULL) { | ||
597 | int buf_free; | ||
598 | |||
599 | if (ca->slot_info[slot].rx_buffer.data == NULL) { | ||
600 | status = -EIO; | ||
601 | goto exit; | ||
602 | } | ||
603 | buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer); | ||
604 | |||
605 | if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) { | ||
606 | status = -EAGAIN; | ||
607 | goto exit; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | /* check if there is data available */ | ||
612 | if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) | ||
613 | goto exit; | ||
614 | if (!(status & STATUSREG_DA)) { | ||
615 | /* no data */ | ||
616 | status = 0; | ||
617 | goto exit; | ||
618 | } | ||
619 | |||
620 | /* read the amount of data */ | ||
621 | if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0) | ||
622 | goto exit; | ||
623 | bytes_read = status << 8; | ||
624 | if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0) | ||
625 | goto exit; | ||
626 | bytes_read |= status; | ||
627 | |||
628 | /* check it will fit */ | ||
629 | if (ebuf == NULL) { | ||
630 | if (bytes_read > ca->slot_info[slot].link_buf_size) { | ||
631 | printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n", | ||
632 | ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size); | ||
633 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; | ||
634 | status = -EIO; | ||
635 | goto exit; | ||
636 | } | ||
637 | if (bytes_read < 2) { | ||
638 | printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", | ||
639 | ca->dvbdev->adapter->num); | ||
640 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; | ||
641 | status = -EIO; | ||
642 | goto exit; | ||
643 | } | ||
644 | } else { | ||
645 | if (bytes_read > ecount) { | ||
646 | printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", | ||
647 | ca->dvbdev->adapter->num); | ||
648 | status = -EIO; | ||
649 | goto exit; | ||
650 | } | ||
651 | } | ||
652 | |||
653 | /* fill the buffer */ | ||
654 | for (i = 0; i < bytes_read; i++) { | ||
655 | /* read byte and check */ | ||
656 | if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0) | ||
657 | goto exit; | ||
658 | |||
659 | /* OK, store it in the buffer */ | ||
660 | buf[i] = status; | ||
661 | } | ||
662 | |||
663 | /* check for read error (RE should now be 0) */ | ||
664 | if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) | ||
665 | goto exit; | ||
666 | if (status & STATUSREG_RE) { | ||
667 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; | ||
668 | status = -EIO; | ||
669 | goto exit; | ||
670 | } | ||
671 | |||
672 | /* OK, add it to the receive buffer, or copy into external buffer if supplied */ | ||
673 | if (ebuf == NULL) { | ||
674 | if (ca->slot_info[slot].rx_buffer.data == NULL) { | ||
675 | status = -EIO; | ||
676 | goto exit; | ||
677 | } | ||
678 | dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read); | ||
679 | } else { | ||
680 | memcpy(ebuf, buf, bytes_read); | ||
681 | } | ||
682 | |||
683 | dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot, | ||
684 | buf[0], (buf[1] & 0x80) == 0, bytes_read); | ||
685 | |||
686 | /* wake up readers when a last_fragment is received */ | ||
687 | if ((buf[1] & 0x80) == 0x00) { | ||
688 | wake_up_interruptible(&ca->wait_queue); | ||
689 | } | ||
690 | status = bytes_read; | ||
691 | |||
692 | exit: | ||
693 | return status; | ||
694 | } | ||
695 | |||
696 | |||
697 | /** | ||
698 | * This function talks to an EN50221 CAM control interface. It writes a buffer of data | ||
699 | * to a CAM. | ||
700 | * | ||
701 | * @param ca CA instance. | ||
702 | * @param slot Slot to write to. | ||
703 | * @param ebuf The data in this buffer is treated as a complete link-level packet to | ||
704 | * be written. | ||
705 | * @param count Size of ebuf. | ||
706 | * | ||
707 | * @return Number of bytes written, or < 0 on error. | ||
708 | */ | ||
709 | static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * buf, int bytes_write) | ||
710 | { | ||
711 | int status; | ||
712 | int i; | ||
713 | |||
714 | dprintk("%s\n", __func__); | ||
715 | |||
716 | |||
717 | /* sanity check */ | ||
718 | if (bytes_write > ca->slot_info[slot].link_buf_size) | ||
719 | return -EINVAL; | ||
720 | |||
721 | /* it is possible we are dealing with a single buffer implementation, | ||
722 | thus if there is data available for read or if there is even a read | ||
723 | already in progress, we do nothing but awake the kernel thread to | ||
724 | process the data if necessary. */ | ||
725 | if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) | ||
726 | goto exitnowrite; | ||
727 | if (status & (STATUSREG_DA | STATUSREG_RE)) { | ||
728 | if (status & STATUSREG_DA) | ||
729 | dvb_ca_en50221_thread_wakeup(ca); | ||
730 | |||
731 | status = -EAGAIN; | ||
732 | goto exitnowrite; | ||
733 | } | ||
734 | |||
735 | /* OK, set HC bit */ | ||
736 | if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, | ||
737 | IRQEN | CMDREG_HC)) != 0) | ||
738 | goto exit; | ||
739 | |||
740 | /* check if interface is still free */ | ||
741 | if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) | ||
742 | goto exit; | ||
743 | if (!(status & STATUSREG_FR)) { | ||
744 | /* it wasn't free => try again later */ | ||
745 | status = -EAGAIN; | ||
746 | goto exit; | ||
747 | } | ||
748 | |||
749 | /* send the amount of data */ | ||
750 | if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0) | ||
751 | goto exit; | ||
752 | if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW, | ||
753 | bytes_write & 0xff)) != 0) | ||
754 | goto exit; | ||
755 | |||
756 | /* send the buffer */ | ||
757 | for (i = 0; i < bytes_write; i++) { | ||
758 | if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0) | ||
759 | goto exit; | ||
760 | } | ||
761 | |||
762 | /* check for write error (WE should now be 0) */ | ||
763 | if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) | ||
764 | goto exit; | ||
765 | if (status & STATUSREG_WE) { | ||
766 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; | ||
767 | status = -EIO; | ||
768 | goto exit; | ||
769 | } | ||
770 | status = bytes_write; | ||
771 | |||
772 | dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot, | ||
773 | buf[0], (buf[1] & 0x80) == 0, bytes_write); | ||
774 | |||
775 | exit: | ||
776 | ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN); | ||
777 | |||
778 | exitnowrite: | ||
779 | return status; | ||
780 | } | ||
781 | EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq); | ||
782 | |||
783 | |||
784 | |||
785 | /* ******************************************************************************** */ | ||
786 | /* EN50221 higher level functions */ | ||
787 | |||
788 | |||
789 | /** | ||
790 | * A CAM has been removed => shut it down. | ||
791 | * | ||
792 | * @param ca CA instance. | ||
793 | * @param slot Slot to shut down. | ||
794 | */ | ||
795 | static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot) | ||
796 | { | ||
797 | dprintk("%s\n", __func__); | ||
798 | |||
799 | ca->pub->slot_shutdown(ca->pub, slot); | ||
800 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; | ||
801 | |||
802 | /* need to wake up all processes to check if they're now | ||
803 | trying to write to a defunct CAM */ | ||
804 | wake_up_interruptible(&ca->wait_queue); | ||
805 | |||
806 | dprintk("Slot %i shutdown\n", slot); | ||
807 | |||
808 | /* success */ | ||
809 | return 0; | ||
810 | } | ||
811 | EXPORT_SYMBOL(dvb_ca_en50221_camready_irq); | ||
812 | |||
813 | |||
814 | /** | ||
815 | * A CAMCHANGE IRQ has occurred. | ||
816 | * | ||
817 | * @param ca CA instance. | ||
818 | * @param slot Slot concerned. | ||
819 | * @param change_type One of the DVB_CA_CAMCHANGE_* values. | ||
820 | */ | ||
821 | void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221 *pubca, int slot, int change_type) | ||
822 | { | ||
823 | struct dvb_ca_private *ca = pubca->private; | ||
824 | |||
825 | dprintk("CAMCHANGE IRQ slot:%i change_type:%i\n", slot, change_type); | ||
826 | |||
827 | switch (change_type) { | ||
828 | case DVB_CA_EN50221_CAMCHANGE_REMOVED: | ||
829 | case DVB_CA_EN50221_CAMCHANGE_INSERTED: | ||
830 | break; | ||
831 | |||
832 | default: | ||
833 | return; | ||
834 | } | ||
835 | |||
836 | ca->slot_info[slot].camchange_type = change_type; | ||
837 | atomic_inc(&ca->slot_info[slot].camchange_count); | ||
838 | dvb_ca_en50221_thread_wakeup(ca); | ||
839 | } | ||
840 | EXPORT_SYMBOL(dvb_ca_en50221_frda_irq); | ||
841 | |||
842 | |||
843 | /** | ||
844 | * A CAMREADY IRQ has occurred. | ||
845 | * | ||
846 | * @param ca CA instance. | ||
847 | * @param slot Slot concerned. | ||
848 | */ | ||
849 | void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot) | ||
850 | { | ||
851 | struct dvb_ca_private *ca = pubca->private; | ||
852 | |||
853 | dprintk("CAMREADY IRQ slot:%i\n", slot); | ||
854 | |||
855 | if (ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) { | ||
856 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE; | ||
857 | dvb_ca_en50221_thread_wakeup(ca); | ||
858 | } | ||
859 | } | ||
860 | |||
861 | |||
862 | /** | ||
863 | * An FR or DA IRQ has occurred. | ||
864 | * | ||
865 | * @param ca CA instance. | ||
866 | * @param slot Slot concerned. | ||
867 | */ | ||
868 | void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot) | ||
869 | { | ||
870 | struct dvb_ca_private *ca = pubca->private; | ||
871 | int flags; | ||
872 | |||
873 | dprintk("FR/DA IRQ slot:%i\n", slot); | ||
874 | |||
875 | switch (ca->slot_info[slot].slot_state) { | ||
876 | case DVB_CA_SLOTSTATE_LINKINIT: | ||
877 | flags = ca->pub->read_cam_control(pubca, slot, CTRLIF_STATUS); | ||
878 | if (flags & STATUSREG_DA) { | ||
879 | dprintk("CAM supports DA IRQ\n"); | ||
880 | ca->slot_info[slot].da_irq_supported = 1; | ||
881 | } | ||
882 | break; | ||
883 | |||
884 | case DVB_CA_SLOTSTATE_RUNNING: | ||
885 | if (ca->open) | ||
886 | dvb_ca_en50221_thread_wakeup(ca); | ||
887 | break; | ||
888 | } | ||
889 | } | ||
890 | |||
891 | |||
892 | |||
893 | /* ******************************************************************************** */ | ||
894 | /* EN50221 thread functions */ | ||
895 | |||
896 | /** | ||
897 | * Wake up the DVB CA thread | ||
898 | * | ||
899 | * @param ca CA instance. | ||
900 | */ | ||
901 | static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca) | ||
902 | { | ||
903 | |||
904 | dprintk("%s\n", __func__); | ||
905 | |||
906 | ca->wakeup = 1; | ||
907 | mb(); | ||
908 | wake_up_process(ca->thread); | ||
909 | } | ||
910 | |||
911 | /** | ||
912 | * Update the delay used by the thread. | ||
913 | * | ||
914 | * @param ca CA instance. | ||
915 | */ | ||
916 | static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) | ||
917 | { | ||
918 | int delay; | ||
919 | int curdelay = 100000000; | ||
920 | int slot; | ||
921 | |||
922 | /* Beware of too high polling frequency, because one polling | ||
923 | * call might take several hundred milliseconds until timeout! | ||
924 | */ | ||
925 | for (slot = 0; slot < ca->slot_count; slot++) { | ||
926 | switch (ca->slot_info[slot].slot_state) { | ||
927 | default: | ||
928 | case DVB_CA_SLOTSTATE_NONE: | ||
929 | delay = HZ * 60; /* 60s */ | ||
930 | if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) | ||
931 | delay = HZ * 5; /* 5s */ | ||
932 | break; | ||
933 | case DVB_CA_SLOTSTATE_INVALID: | ||
934 | delay = HZ * 60; /* 60s */ | ||
935 | if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) | ||
936 | delay = HZ / 10; /* 100ms */ | ||
937 | break; | ||
938 | |||
939 | case DVB_CA_SLOTSTATE_UNINITIALISED: | ||
940 | case DVB_CA_SLOTSTATE_WAITREADY: | ||
941 | case DVB_CA_SLOTSTATE_VALIDATE: | ||
942 | case DVB_CA_SLOTSTATE_WAITFR: | ||
943 | case DVB_CA_SLOTSTATE_LINKINIT: | ||
944 | delay = HZ / 10; /* 100ms */ | ||
945 | break; | ||
946 | |||
947 | case DVB_CA_SLOTSTATE_RUNNING: | ||
948 | delay = HZ * 60; /* 60s */ | ||
949 | if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) | ||
950 | delay = HZ / 10; /* 100ms */ | ||
951 | if (ca->open) { | ||
952 | if ((!ca->slot_info[slot].da_irq_supported) || | ||
953 | (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA))) | ||
954 | delay = HZ / 10; /* 100ms */ | ||
955 | } | ||
956 | break; | ||
957 | } | ||
958 | |||
959 | if (delay < curdelay) | ||
960 | curdelay = delay; | ||
961 | } | ||
962 | |||
963 | ca->delay = curdelay; | ||
964 | } | ||
965 | |||
966 | |||
967 | |||
968 | /** | ||
969 | * Kernel thread which monitors CA slots for CAM changes, and performs data transfers. | ||
970 | */ | ||
971 | static int dvb_ca_en50221_thread(void *data) | ||
972 | { | ||
973 | struct dvb_ca_private *ca = data; | ||
974 | int slot; | ||
975 | int flags; | ||
976 | int status; | ||
977 | int pktcount; | ||
978 | void *rxbuf; | ||
979 | |||
980 | dprintk("%s\n", __func__); | ||
981 | |||
982 | /* choose the correct initial delay */ | ||
983 | dvb_ca_en50221_thread_update_delay(ca); | ||
984 | |||
985 | /* main loop */ | ||
986 | while (!kthread_should_stop()) { | ||
987 | /* sleep for a bit */ | ||
988 | if (!ca->wakeup) { | ||
989 | set_current_state(TASK_INTERRUPTIBLE); | ||
990 | schedule_timeout(ca->delay); | ||
991 | if (kthread_should_stop()) | ||
992 | return 0; | ||
993 | } | ||
994 | ca->wakeup = 0; | ||
995 | |||
996 | /* go through all the slots processing them */ | ||
997 | for (slot = 0; slot < ca->slot_count; slot++) { | ||
998 | |||
999 | mutex_lock(&ca->slot_info[slot].slot_lock); | ||
1000 | |||
1001 | // check the cam status + deal with CAMCHANGEs | ||
1002 | while (dvb_ca_en50221_check_camstatus(ca, slot)) { | ||
1003 | /* clear down an old CI slot if necessary */ | ||
1004 | if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) | ||
1005 | dvb_ca_en50221_slot_shutdown(ca, slot); | ||
1006 | |||
1007 | /* if a CAM is NOW present, initialise it */ | ||
1008 | if (ca->slot_info[slot].camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) { | ||
1009 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_UNINITIALISED; | ||
1010 | } | ||
1011 | |||
1012 | /* we've handled one CAMCHANGE */ | ||
1013 | dvb_ca_en50221_thread_update_delay(ca); | ||
1014 | atomic_dec(&ca->slot_info[slot].camchange_count); | ||
1015 | } | ||
1016 | |||
1017 | // CAM state machine | ||
1018 | switch (ca->slot_info[slot].slot_state) { | ||
1019 | case DVB_CA_SLOTSTATE_NONE: | ||
1020 | case DVB_CA_SLOTSTATE_INVALID: | ||
1021 | // no action needed | ||
1022 | break; | ||
1023 | |||
1024 | case DVB_CA_SLOTSTATE_UNINITIALISED: | ||
1025 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITREADY; | ||
1026 | ca->pub->slot_reset(ca->pub, slot); | ||
1027 | ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ); | ||
1028 | break; | ||
1029 | |||
1030 | case DVB_CA_SLOTSTATE_WAITREADY: | ||
1031 | if (time_after(jiffies, ca->slot_info[slot].timeout)) { | ||
1032 | printk("dvb_ca adaptor %d: PC card did not respond :(\n", | ||
1033 | ca->dvbdev->adapter->num); | ||
1034 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; | ||
1035 | dvb_ca_en50221_thread_update_delay(ca); | ||
1036 | break; | ||
1037 | } | ||
1038 | // no other action needed; will automatically change state when ready | ||
1039 | break; | ||
1040 | |||
1041 | case DVB_CA_SLOTSTATE_VALIDATE: | ||
1042 | if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { | ||
1043 | /* we need this extra check for annoying interfaces like the budget-av */ | ||
1044 | if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && | ||
1045 | (ca->pub->poll_slot_status)) { | ||
1046 | status = ca->pub->poll_slot_status(ca->pub, slot, 0); | ||
1047 | if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { | ||
1048 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; | ||
1049 | dvb_ca_en50221_thread_update_delay(ca); | ||
1050 | break; | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | printk("dvb_ca adapter %d: Invalid PC card inserted :(\n", | ||
1055 | ca->dvbdev->adapter->num); | ||
1056 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; | ||
1057 | dvb_ca_en50221_thread_update_delay(ca); | ||
1058 | break; | ||
1059 | } | ||
1060 | if (dvb_ca_en50221_set_configoption(ca, slot) != 0) { | ||
1061 | printk("dvb_ca adapter %d: Unable to initialise CAM :(\n", | ||
1062 | ca->dvbdev->adapter->num); | ||
1063 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; | ||
1064 | dvb_ca_en50221_thread_update_delay(ca); | ||
1065 | break; | ||
1066 | } | ||
1067 | if (ca->pub->write_cam_control(ca->pub, slot, | ||
1068 | CTRLIF_COMMAND, CMDREG_RS) != 0) { | ||
1069 | printk("dvb_ca adapter %d: Unable to reset CAM IF\n", | ||
1070 | ca->dvbdev->adapter->num); | ||
1071 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; | ||
1072 | dvb_ca_en50221_thread_update_delay(ca); | ||
1073 | break; | ||
1074 | } | ||
1075 | dprintk("DVB CAM validated successfully\n"); | ||
1076 | |||
1077 | ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ); | ||
1078 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITFR; | ||
1079 | ca->wakeup = 1; | ||
1080 | break; | ||
1081 | |||
1082 | case DVB_CA_SLOTSTATE_WAITFR: | ||
1083 | if (time_after(jiffies, ca->slot_info[slot].timeout)) { | ||
1084 | printk("dvb_ca adapter %d: DVB CAM did not respond :(\n", | ||
1085 | ca->dvbdev->adapter->num); | ||
1086 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; | ||
1087 | dvb_ca_en50221_thread_update_delay(ca); | ||
1088 | break; | ||
1089 | } | ||
1090 | |||
1091 | flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS); | ||
1092 | if (flags & STATUSREG_FR) { | ||
1093 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; | ||
1094 | ca->wakeup = 1; | ||
1095 | } | ||
1096 | break; | ||
1097 | |||
1098 | case DVB_CA_SLOTSTATE_LINKINIT: | ||
1099 | if (dvb_ca_en50221_link_init(ca, slot) != 0) { | ||
1100 | /* we need this extra check for annoying interfaces like the budget-av */ | ||
1101 | if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && | ||
1102 | (ca->pub->poll_slot_status)) { | ||
1103 | status = ca->pub->poll_slot_status(ca->pub, slot, 0); | ||
1104 | if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { | ||
1105 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; | ||
1106 | dvb_ca_en50221_thread_update_delay(ca); | ||
1107 | break; | ||
1108 | } | ||
1109 | } | ||
1110 | |||
1111 | printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num); | ||
1112 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; | ||
1113 | dvb_ca_en50221_thread_update_delay(ca); | ||
1114 | break; | ||
1115 | } | ||
1116 | |||
1117 | if (ca->slot_info[slot].rx_buffer.data == NULL) { | ||
1118 | rxbuf = vmalloc(RX_BUFFER_SIZE); | ||
1119 | if (rxbuf == NULL) { | ||
1120 | printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num); | ||
1121 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; | ||
1122 | dvb_ca_en50221_thread_update_delay(ca); | ||
1123 | break; | ||
1124 | } | ||
1125 | dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE); | ||
1126 | } | ||
1127 | |||
1128 | ca->pub->slot_ts_enable(ca->pub, slot); | ||
1129 | ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING; | ||
1130 | dvb_ca_en50221_thread_update_delay(ca); | ||
1131 | printk("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", ca->dvbdev->adapter->num); | ||
1132 | break; | ||
1133 | |||
1134 | case DVB_CA_SLOTSTATE_RUNNING: | ||
1135 | if (!ca->open) | ||
1136 | break; | ||
1137 | |||
1138 | // poll slots for data | ||
1139 | pktcount = 0; | ||
1140 | while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) { | ||
1141 | if (!ca->open) | ||
1142 | break; | ||
1143 | |||
1144 | /* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */ | ||
1145 | if (dvb_ca_en50221_check_camstatus(ca, slot)) { | ||
1146 | // we dont want to sleep on the next iteration so we can handle the cam change | ||
1147 | ca->wakeup = 1; | ||
1148 | break; | ||
1149 | } | ||
1150 | |||
1151 | /* check if we've hit our limit this time */ | ||
1152 | if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) { | ||
1153 | // dont sleep; there is likely to be more data to read | ||
1154 | ca->wakeup = 1; | ||
1155 | break; | ||
1156 | } | ||
1157 | } | ||
1158 | break; | ||
1159 | } | ||
1160 | |||
1161 | mutex_unlock(&ca->slot_info[slot].slot_lock); | ||
1162 | } | ||
1163 | } | ||
1164 | |||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1168 | |||
1169 | |||
1170 | /* ******************************************************************************** */ | ||
1171 | /* EN50221 IO interface functions */ | ||
1172 | |||
1173 | /** | ||
1174 | * Real ioctl implementation. | ||
1175 | * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them. | ||
1176 | * | ||
1177 | * @param inode Inode concerned. | ||
1178 | * @param file File concerned. | ||
1179 | * @param cmd IOCTL command. | ||
1180 | * @param arg Associated argument. | ||
1181 | * | ||
1182 | * @return 0 on success, <0 on error. | ||
1183 | */ | ||
1184 | static int dvb_ca_en50221_io_do_ioctl(struct file *file, | ||
1185 | unsigned int cmd, void *parg) | ||
1186 | { | ||
1187 | struct dvb_device *dvbdev = file->private_data; | ||
1188 | struct dvb_ca_private *ca = dvbdev->priv; | ||
1189 | int err = 0; | ||
1190 | int slot; | ||
1191 | |||
1192 | dprintk("%s\n", __func__); | ||
1193 | |||
1194 | switch (cmd) { | ||
1195 | case CA_RESET: | ||
1196 | for (slot = 0; slot < ca->slot_count; slot++) { | ||
1197 | mutex_lock(&ca->slot_info[slot].slot_lock); | ||
1198 | if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) { | ||
1199 | dvb_ca_en50221_slot_shutdown(ca, slot); | ||
1200 | if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) | ||
1201 | dvb_ca_en50221_camchange_irq(ca->pub, | ||
1202 | slot, | ||
1203 | DVB_CA_EN50221_CAMCHANGE_INSERTED); | ||
1204 | } | ||
1205 | mutex_unlock(&ca->slot_info[slot].slot_lock); | ||
1206 | } | ||
1207 | ca->next_read_slot = 0; | ||
1208 | dvb_ca_en50221_thread_wakeup(ca); | ||
1209 | break; | ||
1210 | |||
1211 | case CA_GET_CAP: { | ||
1212 | struct ca_caps *caps = parg; | ||
1213 | |||
1214 | caps->slot_num = ca->slot_count; | ||
1215 | caps->slot_type = CA_CI_LINK; | ||
1216 | caps->descr_num = 0; | ||
1217 | caps->descr_type = 0; | ||
1218 | break; | ||
1219 | } | ||
1220 | |||
1221 | case CA_GET_SLOT_INFO: { | ||
1222 | struct ca_slot_info *info = parg; | ||
1223 | |||
1224 | if ((info->num > ca->slot_count) || (info->num < 0)) | ||
1225 | return -EINVAL; | ||
1226 | |||
1227 | info->type = CA_CI_LINK; | ||
1228 | info->flags = 0; | ||
1229 | if ((ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_NONE) | ||
1230 | && (ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_INVALID)) { | ||
1231 | info->flags = CA_CI_MODULE_PRESENT; | ||
1232 | } | ||
1233 | if (ca->slot_info[info->num].slot_state == DVB_CA_SLOTSTATE_RUNNING) { | ||
1234 | info->flags |= CA_CI_MODULE_READY; | ||
1235 | } | ||
1236 | break; | ||
1237 | } | ||
1238 | |||
1239 | default: | ||
1240 | err = -EINVAL; | ||
1241 | break; | ||
1242 | } | ||
1243 | |||
1244 | return err; | ||
1245 | } | ||
1246 | |||
1247 | |||
1248 | /** | ||
1249 | * Wrapper for ioctl implementation. | ||
1250 | * | ||
1251 | * @param inode Inode concerned. | ||
1252 | * @param file File concerned. | ||
1253 | * @param cmd IOCTL command. | ||
1254 | * @param arg Associated argument. | ||
1255 | * | ||
1256 | * @return 0 on success, <0 on error. | ||
1257 | */ | ||
1258 | static long dvb_ca_en50221_io_ioctl(struct file *file, | ||
1259 | unsigned int cmd, unsigned long arg) | ||
1260 | { | ||
1261 | return dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl); | ||
1262 | } | ||
1263 | |||
1264 | |||
1265 | /** | ||
1266 | * Implementation of write() syscall. | ||
1267 | * | ||
1268 | * @param file File structure. | ||
1269 | * @param buf Source buffer. | ||
1270 | * @param count Size of source buffer. | ||
1271 | * @param ppos Position in file (ignored). | ||
1272 | * | ||
1273 | * @return Number of bytes read, or <0 on error. | ||
1274 | */ | ||
1275 | static ssize_t dvb_ca_en50221_io_write(struct file *file, | ||
1276 | const char __user * buf, size_t count, loff_t * ppos) | ||
1277 | { | ||
1278 | struct dvb_device *dvbdev = file->private_data; | ||
1279 | struct dvb_ca_private *ca = dvbdev->priv; | ||
1280 | u8 slot, connection_id; | ||
1281 | int status; | ||
1282 | u8 fragbuf[HOST_LINK_BUF_SIZE]; | ||
1283 | int fragpos = 0; | ||
1284 | int fraglen; | ||
1285 | unsigned long timeout; | ||
1286 | int written; | ||
1287 | |||
1288 | dprintk("%s\n", __func__); | ||
1289 | |||
1290 | /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */ | ||
1291 | if (count < 2) | ||
1292 | return -EINVAL; | ||
1293 | |||
1294 | /* extract slot & connection id */ | ||
1295 | if (copy_from_user(&slot, buf, 1)) | ||
1296 | return -EFAULT; | ||
1297 | if (copy_from_user(&connection_id, buf + 1, 1)) | ||
1298 | return -EFAULT; | ||
1299 | buf += 2; | ||
1300 | count -= 2; | ||
1301 | |||
1302 | /* check if the slot is actually running */ | ||
1303 | if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) | ||
1304 | return -EINVAL; | ||
1305 | |||
1306 | /* fragment the packets & store in the buffer */ | ||
1307 | while (fragpos < count) { | ||
1308 | fraglen = ca->slot_info[slot].link_buf_size - 2; | ||
1309 | if (fraglen < 0) | ||
1310 | break; | ||
1311 | if (fraglen > HOST_LINK_BUF_SIZE - 2) | ||
1312 | fraglen = HOST_LINK_BUF_SIZE - 2; | ||
1313 | if ((count - fragpos) < fraglen) | ||
1314 | fraglen = count - fragpos; | ||
1315 | |||
1316 | fragbuf[0] = connection_id; | ||
1317 | fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00; | ||
1318 | status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen); | ||
1319 | if (status) { | ||
1320 | status = -EFAULT; | ||
1321 | goto exit; | ||
1322 | } | ||
1323 | |||
1324 | timeout = jiffies + HZ / 2; | ||
1325 | written = 0; | ||
1326 | while (!time_after(jiffies, timeout)) { | ||
1327 | /* check the CAM hasn't been removed/reset in the meantime */ | ||
1328 | if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) { | ||
1329 | status = -EIO; | ||
1330 | goto exit; | ||
1331 | } | ||
1332 | |||
1333 | mutex_lock(&ca->slot_info[slot].slot_lock); | ||
1334 | status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2); | ||
1335 | mutex_unlock(&ca->slot_info[slot].slot_lock); | ||
1336 | if (status == (fraglen + 2)) { | ||
1337 | written = 1; | ||
1338 | break; | ||
1339 | } | ||
1340 | if (status != -EAGAIN) | ||
1341 | goto exit; | ||
1342 | |||
1343 | msleep(1); | ||
1344 | } | ||
1345 | if (!written) { | ||
1346 | status = -EIO; | ||
1347 | goto exit; | ||
1348 | } | ||
1349 | |||
1350 | fragpos += fraglen; | ||
1351 | } | ||
1352 | status = count + 2; | ||
1353 | |||
1354 | exit: | ||
1355 | return status; | ||
1356 | } | ||
1357 | |||
1358 | |||
1359 | /** | ||
1360 | * Condition for waking up in dvb_ca_en50221_io_read_condition | ||
1361 | */ | ||
1362 | static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, | ||
1363 | int *result, int *_slot) | ||
1364 | { | ||
1365 | int slot; | ||
1366 | int slot_count = 0; | ||
1367 | int idx; | ||
1368 | size_t fraglen; | ||
1369 | int connection_id = -1; | ||
1370 | int found = 0; | ||
1371 | u8 hdr[2]; | ||
1372 | |||
1373 | slot = ca->next_read_slot; | ||
1374 | while ((slot_count < ca->slot_count) && (!found)) { | ||
1375 | if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) | ||
1376 | goto nextslot; | ||
1377 | |||
1378 | if (ca->slot_info[slot].rx_buffer.data == NULL) { | ||
1379 | return 0; | ||
1380 | } | ||
1381 | |||
1382 | idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen); | ||
1383 | while (idx != -1) { | ||
1384 | dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2); | ||
1385 | if (connection_id == -1) | ||
1386 | connection_id = hdr[0]; | ||
1387 | if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) { | ||
1388 | *_slot = slot; | ||
1389 | found = 1; | ||
1390 | break; | ||
1391 | } | ||
1392 | |||
1393 | idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); | ||
1394 | } | ||
1395 | |||
1396 | nextslot: | ||
1397 | slot = (slot + 1) % ca->slot_count; | ||
1398 | slot_count++; | ||
1399 | } | ||
1400 | |||
1401 | ca->next_read_slot = slot; | ||
1402 | return found; | ||
1403 | } | ||
1404 | |||
1405 | |||
1406 | /** | ||
1407 | * Implementation of read() syscall. | ||
1408 | * | ||
1409 | * @param file File structure. | ||
1410 | * @param buf Destination buffer. | ||
1411 | * @param count Size of destination buffer. | ||
1412 | * @param ppos Position in file (ignored). | ||
1413 | * | ||
1414 | * @return Number of bytes read, or <0 on error. | ||
1415 | */ | ||
1416 | static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, | ||
1417 | size_t count, loff_t * ppos) | ||
1418 | { | ||
1419 | struct dvb_device *dvbdev = file->private_data; | ||
1420 | struct dvb_ca_private *ca = dvbdev->priv; | ||
1421 | int status; | ||
1422 | int result = 0; | ||
1423 | u8 hdr[2]; | ||
1424 | int slot; | ||
1425 | int connection_id = -1; | ||
1426 | size_t idx, idx2; | ||
1427 | int last_fragment = 0; | ||
1428 | size_t fraglen; | ||
1429 | int pktlen; | ||
1430 | int dispose = 0; | ||
1431 | |||
1432 | dprintk("%s\n", __func__); | ||
1433 | |||
1434 | /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */ | ||
1435 | if (count < 2) | ||
1436 | return -EINVAL; | ||
1437 | |||
1438 | /* wait for some data */ | ||
1439 | if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot)) == 0) { | ||
1440 | |||
1441 | /* if we're in nonblocking mode, exit immediately */ | ||
1442 | if (file->f_flags & O_NONBLOCK) | ||
1443 | return -EWOULDBLOCK; | ||
1444 | |||
1445 | /* wait for some data */ | ||
1446 | status = wait_event_interruptible(ca->wait_queue, | ||
1447 | dvb_ca_en50221_io_read_condition | ||
1448 | (ca, &result, &slot)); | ||
1449 | } | ||
1450 | if ((status < 0) || (result < 0)) { | ||
1451 | if (result) | ||
1452 | return result; | ||
1453 | return status; | ||
1454 | } | ||
1455 | |||
1456 | idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen); | ||
1457 | pktlen = 2; | ||
1458 | do { | ||
1459 | if (idx == -1) { | ||
1460 | printk("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n", ca->dvbdev->adapter->num); | ||
1461 | status = -EIO; | ||
1462 | goto exit; | ||
1463 | } | ||
1464 | |||
1465 | dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2); | ||
1466 | if (connection_id == -1) | ||
1467 | connection_id = hdr[0]; | ||
1468 | if (hdr[0] == connection_id) { | ||
1469 | if (pktlen < count) { | ||
1470 | if ((pktlen + fraglen - 2) > count) { | ||
1471 | fraglen = count - pktlen; | ||
1472 | } else { | ||
1473 | fraglen -= 2; | ||
1474 | } | ||
1475 | |||
1476 | if ((status = dvb_ringbuffer_pkt_read_user(&ca->slot_info[slot].rx_buffer, idx, 2, | ||
1477 | buf + pktlen, fraglen)) < 0) { | ||
1478 | goto exit; | ||
1479 | } | ||
1480 | pktlen += fraglen; | ||
1481 | } | ||
1482 | |||
1483 | if ((hdr[1] & 0x80) == 0) | ||
1484 | last_fragment = 1; | ||
1485 | dispose = 1; | ||
1486 | } | ||
1487 | |||
1488 | idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); | ||
1489 | if (dispose) | ||
1490 | dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx); | ||
1491 | idx = idx2; | ||
1492 | dispose = 0; | ||
1493 | } while (!last_fragment); | ||
1494 | |||
1495 | hdr[0] = slot; | ||
1496 | hdr[1] = connection_id; | ||
1497 | status = copy_to_user(buf, hdr, 2); | ||
1498 | if (status) { | ||
1499 | status = -EFAULT; | ||
1500 | goto exit; | ||
1501 | } | ||
1502 | status = pktlen; | ||
1503 | |||
1504 | exit: | ||
1505 | return status; | ||
1506 | } | ||
1507 | |||
1508 | |||
1509 | /** | ||
1510 | * Implementation of file open syscall. | ||
1511 | * | ||
1512 | * @param inode Inode concerned. | ||
1513 | * @param file File concerned. | ||
1514 | * | ||
1515 | * @return 0 on success, <0 on failure. | ||
1516 | */ | ||
1517 | static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) | ||
1518 | { | ||
1519 | struct dvb_device *dvbdev = file->private_data; | ||
1520 | struct dvb_ca_private *ca = dvbdev->priv; | ||
1521 | int err; | ||
1522 | int i; | ||
1523 | |||
1524 | dprintk("%s\n", __func__); | ||
1525 | |||
1526 | if (!try_module_get(ca->pub->owner)) | ||
1527 | return -EIO; | ||
1528 | |||
1529 | err = dvb_generic_open(inode, file); | ||
1530 | if (err < 0) { | ||
1531 | module_put(ca->pub->owner); | ||
1532 | return err; | ||
1533 | } | ||
1534 | |||
1535 | for (i = 0; i < ca->slot_count; i++) { | ||
1536 | |||
1537 | if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) { | ||
1538 | if (ca->slot_info[i].rx_buffer.data != NULL) { | ||
1539 | /* it is safe to call this here without locks because | ||
1540 | * ca->open == 0. Data is not read in this case */ | ||
1541 | dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer); | ||
1542 | } | ||
1543 | } | ||
1544 | } | ||
1545 | |||
1546 | ca->open = 1; | ||
1547 | dvb_ca_en50221_thread_update_delay(ca); | ||
1548 | dvb_ca_en50221_thread_wakeup(ca); | ||
1549 | |||
1550 | return 0; | ||
1551 | } | ||
1552 | |||
1553 | |||
1554 | /** | ||
1555 | * Implementation of file close syscall. | ||
1556 | * | ||
1557 | * @param inode Inode concerned. | ||
1558 | * @param file File concerned. | ||
1559 | * | ||
1560 | * @return 0 on success, <0 on failure. | ||
1561 | */ | ||
1562 | static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) | ||
1563 | { | ||
1564 | struct dvb_device *dvbdev = file->private_data; | ||
1565 | struct dvb_ca_private *ca = dvbdev->priv; | ||
1566 | int err; | ||
1567 | |||
1568 | dprintk("%s\n", __func__); | ||
1569 | |||
1570 | /* mark the CA device as closed */ | ||
1571 | ca->open = 0; | ||
1572 | dvb_ca_en50221_thread_update_delay(ca); | ||
1573 | |||
1574 | err = dvb_generic_release(inode, file); | ||
1575 | |||
1576 | module_put(ca->pub->owner); | ||
1577 | |||
1578 | return err; | ||
1579 | } | ||
1580 | |||
1581 | |||
1582 | /** | ||
1583 | * Implementation of poll() syscall. | ||
1584 | * | ||
1585 | * @param file File concerned. | ||
1586 | * @param wait poll wait table. | ||
1587 | * | ||
1588 | * @return Standard poll mask. | ||
1589 | */ | ||
1590 | static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait) | ||
1591 | { | ||
1592 | struct dvb_device *dvbdev = file->private_data; | ||
1593 | struct dvb_ca_private *ca = dvbdev->priv; | ||
1594 | unsigned int mask = 0; | ||
1595 | int slot; | ||
1596 | int result = 0; | ||
1597 | |||
1598 | dprintk("%s\n", __func__); | ||
1599 | |||
1600 | if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { | ||
1601 | mask |= POLLIN; | ||
1602 | } | ||
1603 | |||
1604 | /* if there is something, return now */ | ||
1605 | if (mask) | ||
1606 | return mask; | ||
1607 | |||
1608 | /* wait for something to happen */ | ||
1609 | poll_wait(file, &ca->wait_queue, wait); | ||
1610 | |||
1611 | if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { | ||
1612 | mask |= POLLIN; | ||
1613 | } | ||
1614 | |||
1615 | return mask; | ||
1616 | } | ||
1617 | EXPORT_SYMBOL(dvb_ca_en50221_init); | ||
1618 | |||
1619 | |||
1620 | static const struct file_operations dvb_ca_fops = { | ||
1621 | .owner = THIS_MODULE, | ||
1622 | .read = dvb_ca_en50221_io_read, | ||
1623 | .write = dvb_ca_en50221_io_write, | ||
1624 | .unlocked_ioctl = dvb_ca_en50221_io_ioctl, | ||
1625 | .open = dvb_ca_en50221_io_open, | ||
1626 | .release = dvb_ca_en50221_io_release, | ||
1627 | .poll = dvb_ca_en50221_io_poll, | ||
1628 | .llseek = noop_llseek, | ||
1629 | }; | ||
1630 | |||
1631 | static struct dvb_device dvbdev_ca = { | ||
1632 | .priv = NULL, | ||
1633 | .users = 1, | ||
1634 | .readers = 1, | ||
1635 | .writers = 1, | ||
1636 | .fops = &dvb_ca_fops, | ||
1637 | }; | ||
1638 | |||
1639 | |||
1640 | /* ******************************************************************************** */ | ||
1641 | /* Initialisation/shutdown functions */ | ||
1642 | |||
1643 | |||
1644 | /** | ||
1645 | * Initialise a new DVB CA EN50221 interface device. | ||
1646 | * | ||
1647 | * @param dvb_adapter DVB adapter to attach the new CA device to. | ||
1648 | * @param ca The dvb_ca instance. | ||
1649 | * @param flags Flags describing the CA device (DVB_CA_FLAG_*). | ||
1650 | * @param slot_count Number of slots supported. | ||
1651 | * | ||
1652 | * @return 0 on success, nonzero on failure | ||
1653 | */ | ||
1654 | int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, | ||
1655 | struct dvb_ca_en50221 *pubca, int flags, int slot_count) | ||
1656 | { | ||
1657 | int ret; | ||
1658 | struct dvb_ca_private *ca = NULL; | ||
1659 | int i; | ||
1660 | |||
1661 | dprintk("%s\n", __func__); | ||
1662 | |||
1663 | if (slot_count < 1) | ||
1664 | return -EINVAL; | ||
1665 | |||
1666 | /* initialise the system data */ | ||
1667 | if ((ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) { | ||
1668 | ret = -ENOMEM; | ||
1669 | goto error; | ||
1670 | } | ||
1671 | ca->pub = pubca; | ||
1672 | ca->flags = flags; | ||
1673 | ca->slot_count = slot_count; | ||
1674 | if ((ca->slot_info = kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL)) == NULL) { | ||
1675 | ret = -ENOMEM; | ||
1676 | goto error; | ||
1677 | } | ||
1678 | init_waitqueue_head(&ca->wait_queue); | ||
1679 | ca->open = 0; | ||
1680 | ca->wakeup = 0; | ||
1681 | ca->next_read_slot = 0; | ||
1682 | pubca->private = ca; | ||
1683 | |||
1684 | /* register the DVB device */ | ||
1685 | ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA); | ||
1686 | if (ret) | ||
1687 | goto error; | ||
1688 | |||
1689 | /* now initialise each slot */ | ||
1690 | for (i = 0; i < slot_count; i++) { | ||
1691 | memset(&ca->slot_info[i], 0, sizeof(struct dvb_ca_slot)); | ||
1692 | ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; | ||
1693 | atomic_set(&ca->slot_info[i].camchange_count, 0); | ||
1694 | ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; | ||
1695 | mutex_init(&ca->slot_info[i].slot_lock); | ||
1696 | } | ||
1697 | |||
1698 | if (signal_pending(current)) { | ||
1699 | ret = -EINTR; | ||
1700 | goto error; | ||
1701 | } | ||
1702 | mb(); | ||
1703 | |||
1704 | /* create a kthread for monitoring this CA device */ | ||
1705 | ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i", | ||
1706 | ca->dvbdev->adapter->num, ca->dvbdev->id); | ||
1707 | if (IS_ERR(ca->thread)) { | ||
1708 | ret = PTR_ERR(ca->thread); | ||
1709 | printk("dvb_ca_init: failed to start kernel_thread (%d)\n", | ||
1710 | ret); | ||
1711 | goto error; | ||
1712 | } | ||
1713 | return 0; | ||
1714 | |||
1715 | error: | ||
1716 | if (ca != NULL) { | ||
1717 | if (ca->dvbdev != NULL) | ||
1718 | dvb_unregister_device(ca->dvbdev); | ||
1719 | kfree(ca->slot_info); | ||
1720 | kfree(ca); | ||
1721 | } | ||
1722 | pubca->private = NULL; | ||
1723 | return ret; | ||
1724 | } | ||
1725 | EXPORT_SYMBOL(dvb_ca_en50221_release); | ||
1726 | |||
1727 | |||
1728 | |||
1729 | /** | ||
1730 | * Release a DVB CA EN50221 interface device. | ||
1731 | * | ||
1732 | * @param ca_dev The dvb_device_t instance for the CA device. | ||
1733 | * @param ca The associated dvb_ca instance. | ||
1734 | */ | ||
1735 | void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca) | ||
1736 | { | ||
1737 | struct dvb_ca_private *ca = pubca->private; | ||
1738 | int i; | ||
1739 | |||
1740 | dprintk("%s\n", __func__); | ||
1741 | |||
1742 | /* shutdown the thread if there was one */ | ||
1743 | kthread_stop(ca->thread); | ||
1744 | |||
1745 | for (i = 0; i < ca->slot_count; i++) { | ||
1746 | dvb_ca_en50221_slot_shutdown(ca, i); | ||
1747 | vfree(ca->slot_info[i].rx_buffer.data); | ||
1748 | } | ||
1749 | kfree(ca->slot_info); | ||
1750 | dvb_unregister_device(ca->dvbdev); | ||
1751 | kfree(ca); | ||
1752 | pubca->private = NULL; | ||
1753 | } | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h deleted file mode 100644 index 7df2e141187a..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
1 | /* | ||
2 | * dvb_ca.h: generic DVB functions for EN50221 CA interfaces | ||
3 | * | ||
4 | * Copyright (C) 2004 Andrew de Quincey | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public License | ||
8 | * as published by the Free Software Foundation; either version 2.1 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef _DVB_CA_EN50221_H_ | ||
22 | #define _DVB_CA_EN50221_H_ | ||
23 | |||
24 | #include <linux/list.h> | ||
25 | #include <linux/dvb/ca.h> | ||
26 | |||
27 | #include "dvbdev.h" | ||
28 | |||
29 | #define DVB_CA_EN50221_POLL_CAM_PRESENT 1 | ||
30 | #define DVB_CA_EN50221_POLL_CAM_CHANGED 2 | ||
31 | #define DVB_CA_EN50221_POLL_CAM_READY 4 | ||
32 | |||
33 | #define DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE 1 | ||
34 | #define DVB_CA_EN50221_FLAG_IRQ_FR 2 | ||
35 | #define DVB_CA_EN50221_FLAG_IRQ_DA 4 | ||
36 | |||
37 | #define DVB_CA_EN50221_CAMCHANGE_REMOVED 0 | ||
38 | #define DVB_CA_EN50221_CAMCHANGE_INSERTED 1 | ||
39 | |||
40 | |||
41 | |||
42 | /* Structure describing a CA interface */ | ||
43 | struct dvb_ca_en50221 { | ||
44 | |||
45 | /* the module owning this structure */ | ||
46 | struct module* owner; | ||
47 | |||
48 | /* NOTE: the read_*, write_* and poll_slot_status functions will be | ||
49 | * called for different slots concurrently and need to use locks where | ||
50 | * and if appropriate. There will be no concurrent access to one slot. | ||
51 | */ | ||
52 | |||
53 | /* functions for accessing attribute memory on the CAM */ | ||
54 | int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address); | ||
55 | int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value); | ||
56 | |||
57 | /* functions for accessing the control interface on the CAM */ | ||
58 | int (*read_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address); | ||
59 | int (*write_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value); | ||
60 | |||
61 | /* Functions for controlling slots */ | ||
62 | int (*slot_reset)(struct dvb_ca_en50221* ca, int slot); | ||
63 | int (*slot_shutdown)(struct dvb_ca_en50221* ca, int slot); | ||
64 | int (*slot_ts_enable)(struct dvb_ca_en50221* ca, int slot); | ||
65 | |||
66 | /* | ||
67 | * Poll slot status. | ||
68 | * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set | ||
69 | */ | ||
70 | int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open); | ||
71 | |||
72 | /* private data, used by caller */ | ||
73 | void* data; | ||
74 | |||
75 | /* Opaque data used by the dvb_ca core. Do not modify! */ | ||
76 | void* private; | ||
77 | }; | ||
78 | |||
79 | |||
80 | |||
81 | |||
82 | /* ******************************************************************************** */ | ||
83 | /* Functions for reporting IRQ events */ | ||
84 | |||
85 | /** | ||
86 | * A CAMCHANGE IRQ has occurred. | ||
87 | * | ||
88 | * @param ca CA instance. | ||
89 | * @param slot Slot concerned. | ||
90 | * @param change_type One of the DVB_CA_CAMCHANGE_* values | ||
91 | */ | ||
92 | void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int change_type); | ||
93 | |||
94 | /** | ||
95 | * A CAMREADY IRQ has occurred. | ||
96 | * | ||
97 | * @param ca CA instance. | ||
98 | * @param slot Slot concerned. | ||
99 | */ | ||
100 | void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot); | ||
101 | |||
102 | /** | ||
103 | * An FR or a DA IRQ has occurred. | ||
104 | * | ||
105 | * @param ca CA instance. | ||
106 | * @param slot Slot concerned. | ||
107 | */ | ||
108 | void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot); | ||
109 | |||
110 | |||
111 | |||
112 | /* ******************************************************************************** */ | ||
113 | /* Initialisation/shutdown functions */ | ||
114 | |||
115 | /** | ||
116 | * Initialise a new DVB CA device. | ||
117 | * | ||
118 | * @param dvb_adapter DVB adapter to attach the new CA device to. | ||
119 | * @param ca The dvb_ca instance. | ||
120 | * @param flags Flags describing the CA device (DVB_CA_EN50221_FLAG_*). | ||
121 | * @param slot_count Number of slots supported. | ||
122 | * | ||
123 | * @return 0 on success, nonzero on failure | ||
124 | */ | ||
125 | extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca, int flags, int slot_count); | ||
126 | |||
127 | /** | ||
128 | * Release a DVB CA device. | ||
129 | * | ||
130 | * @param ca The associated dvb_ca instance. | ||
131 | */ | ||
132 | extern void dvb_ca_en50221_release(struct dvb_ca_en50221* ca); | ||
133 | |||
134 | |||
135 | |||
136 | #endif | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c deleted file mode 100644 index 17cb81fd194c..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ /dev/null | |||
@@ -1,1318 +0,0 @@ | |||
1 | /* | ||
2 | * dvb_demux.c - DVB kernel demux API | ||
3 | * | ||
4 | * Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de> | ||
5 | * & Marcus Metzler <marcus@convergence.de> | ||
6 | * for convergence integrated media GmbH | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 | ||
11 | * of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/sched.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/vmalloc.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/poll.h> | ||
30 | #include <linux/string.h> | ||
31 | #include <linux/crc32.h> | ||
32 | #include <asm/uaccess.h> | ||
33 | #include <asm/div64.h> | ||
34 | |||
35 | #include "dvb_demux.h" | ||
36 | |||
37 | #define NOBUFS | ||
38 | /* | ||
39 | ** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog | ||
40 | */ | ||
41 | // #define DVB_DEMUX_SECTION_LOSS_LOG | ||
42 | |||
43 | static int dvb_demux_tscheck; | ||
44 | module_param(dvb_demux_tscheck, int, 0644); | ||
45 | MODULE_PARM_DESC(dvb_demux_tscheck, | ||
46 | "enable transport stream continuity and TEI check"); | ||
47 | |||
48 | static int dvb_demux_speedcheck; | ||
49 | module_param(dvb_demux_speedcheck, int, 0644); | ||
50 | MODULE_PARM_DESC(dvb_demux_speedcheck, | ||
51 | "enable transport stream speed check"); | ||
52 | |||
53 | static int dvb_demux_feed_err_pkts = 1; | ||
54 | module_param(dvb_demux_feed_err_pkts, int, 0644); | ||
55 | MODULE_PARM_DESC(dvb_demux_feed_err_pkts, | ||
56 | "when set to 0, drop packets with the TEI bit set (1 by default)"); | ||
57 | |||
58 | #define dprintk_tscheck(x...) do { \ | ||
59 | if (dvb_demux_tscheck && printk_ratelimit()) \ | ||
60 | printk(x); \ | ||
61 | } while (0) | ||
62 | |||
63 | /****************************************************************************** | ||
64 | * static inlined helper functions | ||
65 | ******************************************************************************/ | ||
66 | |||
67 | static inline u16 section_length(const u8 *buf) | ||
68 | { | ||
69 | return 3 + ((buf[1] & 0x0f) << 8) + buf[2]; | ||
70 | } | ||
71 | |||
72 | static inline u16 ts_pid(const u8 *buf) | ||
73 | { | ||
74 | return ((buf[1] & 0x1f) << 8) + buf[2]; | ||
75 | } | ||
76 | |||
77 | static inline u8 payload(const u8 *tsp) | ||
78 | { | ||
79 | if (!(tsp[3] & 0x10)) // no payload? | ||
80 | return 0; | ||
81 | |||
82 | if (tsp[3] & 0x20) { // adaptation field? | ||
83 | if (tsp[4] > 183) // corrupted data? | ||
84 | return 0; | ||
85 | else | ||
86 | return 184 - 1 - tsp[4]; | ||
87 | } | ||
88 | |||
89 | return 184; | ||
90 | } | ||
91 | |||
92 | static u32 dvb_dmx_crc32(struct dvb_demux_feed *f, const u8 *src, size_t len) | ||
93 | { | ||
94 | return (f->feed.sec.crc_val = crc32_be(f->feed.sec.crc_val, src, len)); | ||
95 | } | ||
96 | |||
97 | static void dvb_dmx_memcopy(struct dvb_demux_feed *f, u8 *d, const u8 *s, | ||
98 | size_t len) | ||
99 | { | ||
100 | memcpy(d, s, len); | ||
101 | } | ||
102 | |||
103 | /****************************************************************************** | ||
104 | * Software filter functions | ||
105 | ******************************************************************************/ | ||
106 | |||
107 | static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed, | ||
108 | const u8 *buf) | ||
109 | { | ||
110 | int count = payload(buf); | ||
111 | int p; | ||
112 | //int ccok; | ||
113 | //u8 cc; | ||
114 | |||
115 | if (count == 0) | ||
116 | return -1; | ||
117 | |||
118 | p = 188 - count; | ||
119 | |||
120 | /* | ||
121 | cc = buf[3] & 0x0f; | ||
122 | ccok = ((feed->cc + 1) & 0x0f) == cc; | ||
123 | feed->cc = cc; | ||
124 | if (!ccok) | ||
125 | printk("missed packet!\n"); | ||
126 | */ | ||
127 | |||
128 | if (buf[1] & 0x40) // PUSI ? | ||
129 | feed->peslen = 0xfffa; | ||
130 | |||
131 | feed->peslen += count; | ||
132 | |||
133 | return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK); | ||
134 | } | ||
135 | |||
136 | static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed, | ||
137 | struct dvb_demux_filter *f) | ||
138 | { | ||
139 | u8 neq = 0; | ||
140 | int i; | ||
141 | |||
142 | for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) { | ||
143 | u8 xor = f->filter.filter_value[i] ^ feed->feed.sec.secbuf[i]; | ||
144 | |||
145 | if (f->maskandmode[i] & xor) | ||
146 | return 0; | ||
147 | |||
148 | neq |= f->maskandnotmode[i] & xor; | ||
149 | } | ||
150 | |||
151 | if (f->doneq && !neq) | ||
152 | return 0; | ||
153 | |||
154 | return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen, | ||
155 | NULL, 0, &f->filter, DMX_OK); | ||
156 | } | ||
157 | |||
158 | static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed) | ||
159 | { | ||
160 | struct dvb_demux *demux = feed->demux; | ||
161 | struct dvb_demux_filter *f = feed->filter; | ||
162 | struct dmx_section_feed *sec = &feed->feed.sec; | ||
163 | int section_syntax_indicator; | ||
164 | |||
165 | if (!sec->is_filtering) | ||
166 | return 0; | ||
167 | |||
168 | if (!f) | ||
169 | return 0; | ||
170 | |||
171 | if (sec->check_crc) { | ||
172 | section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0); | ||
173 | if (section_syntax_indicator && | ||
174 | demux->check_crc32(feed, sec->secbuf, sec->seclen)) | ||
175 | return -1; | ||
176 | } | ||
177 | |||
178 | do { | ||
179 | if (dvb_dmx_swfilter_sectionfilter(feed, f) < 0) | ||
180 | return -1; | ||
181 | } while ((f = f->next) && sec->is_filtering); | ||
182 | |||
183 | sec->seclen = 0; | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) | ||
189 | { | ||
190 | struct dmx_section_feed *sec = &feed->feed.sec; | ||
191 | |||
192 | #ifdef DVB_DEMUX_SECTION_LOSS_LOG | ||
193 | if (sec->secbufp < sec->tsfeedp) { | ||
194 | int i, n = sec->tsfeedp - sec->secbufp; | ||
195 | |||
196 | /* | ||
197 | * Section padding is done with 0xff bytes entirely. | ||
198 | * Due to speed reasons, we won't check all of them | ||
199 | * but just first and last. | ||
200 | */ | ||
201 | if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) { | ||
202 | printk("dvb_demux.c section ts padding loss: %d/%d\n", | ||
203 | n, sec->tsfeedp); | ||
204 | printk("dvb_demux.c pad data:"); | ||
205 | for (i = 0; i < n; i++) | ||
206 | printk(" %02x", sec->secbuf[i]); | ||
207 | printk("\n"); | ||
208 | } | ||
209 | } | ||
210 | #endif | ||
211 | |||
212 | sec->tsfeedp = sec->secbufp = sec->seclen = 0; | ||
213 | sec->secbuf = sec->secbuf_base; | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Losless Section Demux 1.4.1 by Emard | ||
218 | * Valsecchi Patrick: | ||
219 | * - middle of section A (no PUSI) | ||
220 | * - end of section A and start of section B | ||
221 | * (with PUSI pointing to the start of the second section) | ||
222 | * | ||
223 | * In this case, without feed->pusi_seen you'll receive a garbage section | ||
224 | * consisting of the end of section A. Basically because tsfeedp | ||
225 | * is incemented and the use=0 condition is not raised | ||
226 | * when the second packet arrives. | ||
227 | * | ||
228 | * Fix: | ||
229 | * when demux is started, let feed->pusi_seen = 0 to | ||
230 | * prevent initial feeding of garbage from the end of | ||
231 | * previous section. When you for the first time see PUSI=1 | ||
232 | * then set feed->pusi_seen = 1 | ||
233 | */ | ||
234 | static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, | ||
235 | const u8 *buf, u8 len) | ||
236 | { | ||
237 | struct dvb_demux *demux = feed->demux; | ||
238 | struct dmx_section_feed *sec = &feed->feed.sec; | ||
239 | u16 limit, seclen, n; | ||
240 | |||
241 | if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE) | ||
242 | return 0; | ||
243 | |||
244 | if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) { | ||
245 | #ifdef DVB_DEMUX_SECTION_LOSS_LOG | ||
246 | printk("dvb_demux.c section buffer full loss: %d/%d\n", | ||
247 | sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, | ||
248 | DMX_MAX_SECFEED_SIZE); | ||
249 | #endif | ||
250 | len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp; | ||
251 | } | ||
252 | |||
253 | if (len <= 0) | ||
254 | return 0; | ||
255 | |||
256 | demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len); | ||
257 | sec->tsfeedp += len; | ||
258 | |||
259 | /* | ||
260 | * Dump all the sections we can find in the data (Emard) | ||
261 | */ | ||
262 | limit = sec->tsfeedp; | ||
263 | if (limit > DMX_MAX_SECFEED_SIZE) | ||
264 | return -1; /* internal error should never happen */ | ||
265 | |||
266 | /* to be sure always set secbuf */ | ||
267 | sec->secbuf = sec->secbuf_base + sec->secbufp; | ||
268 | |||
269 | for (n = 0; sec->secbufp + 2 < limit; n++) { | ||
270 | seclen = section_length(sec->secbuf); | ||
271 | if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE | ||
272 | || seclen + sec->secbufp > limit) | ||
273 | return 0; | ||
274 | sec->seclen = seclen; | ||
275 | sec->crc_val = ~0; | ||
276 | /* dump [secbuf .. secbuf+seclen) */ | ||
277 | if (feed->pusi_seen) | ||
278 | dvb_dmx_swfilter_section_feed(feed); | ||
279 | #ifdef DVB_DEMUX_SECTION_LOSS_LOG | ||
280 | else | ||
281 | printk("dvb_demux.c pusi not seen, discarding section data\n"); | ||
282 | #endif | ||
283 | sec->secbufp += seclen; /* secbufp and secbuf moving together is */ | ||
284 | sec->secbuf += seclen; /* redundant but saves pointer arithmetic */ | ||
285 | } | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, | ||
291 | const u8 *buf) | ||
292 | { | ||
293 | u8 p, count; | ||
294 | int ccok, dc_i = 0; | ||
295 | u8 cc; | ||
296 | |||
297 | count = payload(buf); | ||
298 | |||
299 | if (count == 0) /* count == 0 if no payload or out of range */ | ||
300 | return -1; | ||
301 | |||
302 | p = 188 - count; /* payload start */ | ||
303 | |||
304 | cc = buf[3] & 0x0f; | ||
305 | ccok = ((feed->cc + 1) & 0x0f) == cc; | ||
306 | feed->cc = cc; | ||
307 | |||
308 | if (buf[3] & 0x20) { | ||
309 | /* adaption field present, check for discontinuity_indicator */ | ||
310 | if ((buf[4] > 0) && (buf[5] & 0x80)) | ||
311 | dc_i = 1; | ||
312 | } | ||
313 | |||
314 | if (!ccok || dc_i) { | ||
315 | #ifdef DVB_DEMUX_SECTION_LOSS_LOG | ||
316 | printk("dvb_demux.c discontinuity detected %d bytes lost\n", | ||
317 | count); | ||
318 | /* | ||
319 | * those bytes under sume circumstances will again be reported | ||
320 | * in the following dvb_dmx_swfilter_section_new | ||
321 | */ | ||
322 | #endif | ||
323 | /* | ||
324 | * Discontinuity detected. Reset pusi_seen = 0 to | ||
325 | * stop feeding of suspicious data until next PUSI=1 arrives | ||
326 | */ | ||
327 | feed->pusi_seen = 0; | ||
328 | dvb_dmx_swfilter_section_new(feed); | ||
329 | } | ||
330 | |||
331 | if (buf[1] & 0x40) { | ||
332 | /* PUSI=1 (is set), section boundary is here */ | ||
333 | if (count > 1 && buf[p] < count) { | ||
334 | const u8 *before = &buf[p + 1]; | ||
335 | u8 before_len = buf[p]; | ||
336 | const u8 *after = &before[before_len]; | ||
337 | u8 after_len = count - 1 - before_len; | ||
338 | |||
339 | dvb_dmx_swfilter_section_copy_dump(feed, before, | ||
340 | before_len); | ||
341 | /* before start of new section, set pusi_seen = 1 */ | ||
342 | feed->pusi_seen = 1; | ||
343 | dvb_dmx_swfilter_section_new(feed); | ||
344 | dvb_dmx_swfilter_section_copy_dump(feed, after, | ||
345 | after_len); | ||
346 | } | ||
347 | #ifdef DVB_DEMUX_SECTION_LOSS_LOG | ||
348 | else if (count > 0) | ||
349 | printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count); | ||
350 | #endif | ||
351 | } else { | ||
352 | /* PUSI=0 (is not set), no section boundary */ | ||
353 | dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count); | ||
354 | } | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, | ||
360 | const u8 *buf) | ||
361 | { | ||
362 | switch (feed->type) { | ||
363 | case DMX_TYPE_TS: | ||
364 | if (!feed->feed.ts.is_filtering) | ||
365 | break; | ||
366 | if (feed->ts_type & TS_PACKET) { | ||
367 | if (feed->ts_type & TS_PAYLOAD_ONLY) | ||
368 | dvb_dmx_swfilter_payload(feed, buf); | ||
369 | else | ||
370 | feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, | ||
371 | DMX_OK); | ||
372 | } | ||
373 | if (feed->ts_type & TS_DECODER) | ||
374 | if (feed->demux->write_to_decoder) | ||
375 | feed->demux->write_to_decoder(feed, buf, 188); | ||
376 | break; | ||
377 | |||
378 | case DMX_TYPE_SEC: | ||
379 | if (!feed->feed.sec.is_filtering) | ||
380 | break; | ||
381 | if (dvb_dmx_swfilter_section_packet(feed, buf) < 0) | ||
382 | feed->feed.sec.seclen = feed->feed.sec.secbufp = 0; | ||
383 | break; | ||
384 | |||
385 | default: | ||
386 | break; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | #define DVR_FEED(f) \ | ||
391 | (((f)->type == DMX_TYPE_TS) && \ | ||
392 | ((f)->feed.ts.is_filtering) && \ | ||
393 | (((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET)) | ||
394 | |||
395 | static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) | ||
396 | { | ||
397 | struct dvb_demux_feed *feed; | ||
398 | u16 pid = ts_pid(buf); | ||
399 | int dvr_done = 0; | ||
400 | |||
401 | if (dvb_demux_speedcheck) { | ||
402 | struct timespec cur_time, delta_time; | ||
403 | u64 speed_bytes, speed_timedelta; | ||
404 | |||
405 | demux->speed_pkts_cnt++; | ||
406 | |||
407 | /* show speed every SPEED_PKTS_INTERVAL packets */ | ||
408 | if (!(demux->speed_pkts_cnt % SPEED_PKTS_INTERVAL)) { | ||
409 | cur_time = current_kernel_time(); | ||
410 | |||
411 | if (demux->speed_last_time.tv_sec != 0 && | ||
412 | demux->speed_last_time.tv_nsec != 0) { | ||
413 | delta_time = timespec_sub(cur_time, | ||
414 | demux->speed_last_time); | ||
415 | speed_bytes = (u64)demux->speed_pkts_cnt | ||
416 | * 188 * 8; | ||
417 | /* convert to 1024 basis */ | ||
418 | speed_bytes = 1000 * div64_u64(speed_bytes, | ||
419 | 1024); | ||
420 | speed_timedelta = | ||
421 | (u64)timespec_to_ns(&delta_time); | ||
422 | speed_timedelta = div64_u64(speed_timedelta, | ||
423 | 1000000); /* nsec -> usec */ | ||
424 | printk(KERN_INFO "TS speed %llu Kbits/sec \n", | ||
425 | div64_u64(speed_bytes, | ||
426 | speed_timedelta)); | ||
427 | }; | ||
428 | |||
429 | demux->speed_last_time = cur_time; | ||
430 | demux->speed_pkts_cnt = 0; | ||
431 | }; | ||
432 | }; | ||
433 | |||
434 | if (buf[1] & 0x80) { | ||
435 | dprintk_tscheck("TEI detected. " | ||
436 | "PID=0x%x data1=0x%x\n", | ||
437 | pid, buf[1]); | ||
438 | /* data in this packet cant be trusted - drop it unless | ||
439 | * module option dvb_demux_feed_err_pkts is set */ | ||
440 | if (!dvb_demux_feed_err_pkts) | ||
441 | return; | ||
442 | } else /* if TEI bit is set, pid may be wrong- skip pkt counter */ | ||
443 | if (demux->cnt_storage && dvb_demux_tscheck) { | ||
444 | /* check pkt counter */ | ||
445 | if (pid < MAX_PID) { | ||
446 | if ((buf[3] & 0xf) != demux->cnt_storage[pid]) | ||
447 | dprintk_tscheck("TS packet counter mismatch. " | ||
448 | "PID=0x%x expected 0x%x " | ||
449 | "got 0x%x\n", | ||
450 | pid, demux->cnt_storage[pid], | ||
451 | buf[3] & 0xf); | ||
452 | |||
453 | demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf; | ||
454 | }; | ||
455 | /* end check */ | ||
456 | }; | ||
457 | |||
458 | list_for_each_entry(feed, &demux->feed_list, list_head) { | ||
459 | if ((feed->pid != pid) && (feed->pid != 0x2000)) | ||
460 | continue; | ||
461 | |||
462 | /* copy each packet only once to the dvr device, even | ||
463 | * if a PID is in multiple filters (e.g. video + PCR) */ | ||
464 | if ((DVR_FEED(feed)) && (dvr_done++)) | ||
465 | continue; | ||
466 | |||
467 | if (feed->pid == pid) | ||
468 | dvb_dmx_swfilter_packet_type(feed, buf); | ||
469 | else if (feed->pid == 0x2000) | ||
470 | feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK); | ||
471 | } | ||
472 | } | ||
473 | |||
474 | void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, | ||
475 | size_t count) | ||
476 | { | ||
477 | spin_lock(&demux->lock); | ||
478 | |||
479 | while (count--) { | ||
480 | if (buf[0] == 0x47) | ||
481 | dvb_dmx_swfilter_packet(demux, buf); | ||
482 | buf += 188; | ||
483 | } | ||
484 | |||
485 | spin_unlock(&demux->lock); | ||
486 | } | ||
487 | |||
488 | EXPORT_SYMBOL(dvb_dmx_swfilter_packets); | ||
489 | |||
490 | static inline int find_next_packet(const u8 *buf, int pos, size_t count, | ||
491 | const int pktsize) | ||
492 | { | ||
493 | int start = pos, lost; | ||
494 | |||
495 | while (pos < count) { | ||
496 | if (buf[pos] == 0x47 || | ||
497 | (pktsize == 204 && buf[pos] == 0xB8)) | ||
498 | break; | ||
499 | pos++; | ||
500 | } | ||
501 | |||
502 | lost = pos - start; | ||
503 | if (lost) { | ||
504 | /* This garbage is part of a valid packet? */ | ||
505 | int backtrack = pos - pktsize; | ||
506 | if (backtrack >= 0 && (buf[backtrack] == 0x47 || | ||
507 | (pktsize == 204 && buf[backtrack] == 0xB8))) | ||
508 | return backtrack; | ||
509 | } | ||
510 | |||
511 | return pos; | ||
512 | } | ||
513 | |||
514 | /* Filter all pktsize= 188 or 204 sized packets and skip garbage. */ | ||
515 | static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, | ||
516 | size_t count, const int pktsize) | ||
517 | { | ||
518 | int p = 0, i, j; | ||
519 | const u8 *q; | ||
520 | |||
521 | spin_lock(&demux->lock); | ||
522 | |||
523 | if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */ | ||
524 | i = demux->tsbufp; | ||
525 | j = pktsize - i; | ||
526 | if (count < j) { | ||
527 | memcpy(&demux->tsbuf[i], buf, count); | ||
528 | demux->tsbufp += count; | ||
529 | goto bailout; | ||
530 | } | ||
531 | memcpy(&demux->tsbuf[i], buf, j); | ||
532 | if (demux->tsbuf[0] == 0x47) /* double check */ | ||
533 | dvb_dmx_swfilter_packet(demux, demux->tsbuf); | ||
534 | demux->tsbufp = 0; | ||
535 | p += j; | ||
536 | } | ||
537 | |||
538 | while (1) { | ||
539 | p = find_next_packet(buf, p, count, pktsize); | ||
540 | if (p >= count) | ||
541 | break; | ||
542 | if (count - p < pktsize) | ||
543 | break; | ||
544 | |||
545 | q = &buf[p]; | ||
546 | |||
547 | if (pktsize == 204 && (*q == 0xB8)) { | ||
548 | memcpy(demux->tsbuf, q, 188); | ||
549 | demux->tsbuf[0] = 0x47; | ||
550 | q = demux->tsbuf; | ||
551 | } | ||
552 | dvb_dmx_swfilter_packet(demux, q); | ||
553 | p += pktsize; | ||
554 | } | ||
555 | |||
556 | i = count - p; | ||
557 | if (i) { | ||
558 | memcpy(demux->tsbuf, &buf[p], i); | ||
559 | demux->tsbufp = i; | ||
560 | if (pktsize == 204 && demux->tsbuf[0] == 0xB8) | ||
561 | demux->tsbuf[0] = 0x47; | ||
562 | } | ||
563 | |||
564 | bailout: | ||
565 | spin_unlock(&demux->lock); | ||
566 | } | ||
567 | |||
568 | void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) | ||
569 | { | ||
570 | _dvb_dmx_swfilter(demux, buf, count, 188); | ||
571 | } | ||
572 | EXPORT_SYMBOL(dvb_dmx_swfilter); | ||
573 | |||
574 | void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) | ||
575 | { | ||
576 | _dvb_dmx_swfilter(demux, buf, count, 204); | ||
577 | } | ||
578 | EXPORT_SYMBOL(dvb_dmx_swfilter_204); | ||
579 | |||
580 | void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count) | ||
581 | { | ||
582 | spin_lock(&demux->lock); | ||
583 | |||
584 | demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, DMX_OK); | ||
585 | |||
586 | spin_unlock(&demux->lock); | ||
587 | } | ||
588 | EXPORT_SYMBOL(dvb_dmx_swfilter_raw); | ||
589 | |||
590 | static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux) | ||
591 | { | ||
592 | int i; | ||
593 | |||
594 | for (i = 0; i < demux->filternum; i++) | ||
595 | if (demux->filter[i].state == DMX_STATE_FREE) | ||
596 | break; | ||
597 | |||
598 | if (i == demux->filternum) | ||
599 | return NULL; | ||
600 | |||
601 | demux->filter[i].state = DMX_STATE_ALLOCATED; | ||
602 | |||
603 | return &demux->filter[i]; | ||
604 | } | ||
605 | |||
606 | static struct dvb_demux_feed *dvb_dmx_feed_alloc(struct dvb_demux *demux) | ||
607 | { | ||
608 | int i; | ||
609 | |||
610 | for (i = 0; i < demux->feednum; i++) | ||
611 | if (demux->feed[i].state == DMX_STATE_FREE) | ||
612 | break; | ||
613 | |||
614 | if (i == demux->feednum) | ||
615 | return NULL; | ||
616 | |||
617 | demux->feed[i].state = DMX_STATE_ALLOCATED; | ||
618 | |||
619 | return &demux->feed[i]; | ||
620 | } | ||
621 | |||
622 | static int dvb_demux_feed_find(struct dvb_demux_feed *feed) | ||
623 | { | ||
624 | struct dvb_demux_feed *entry; | ||
625 | |||
626 | list_for_each_entry(entry, &feed->demux->feed_list, list_head) | ||
627 | if (entry == feed) | ||
628 | return 1; | ||
629 | |||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | static void dvb_demux_feed_add(struct dvb_demux_feed *feed) | ||
634 | { | ||
635 | spin_lock_irq(&feed->demux->lock); | ||
636 | if (dvb_demux_feed_find(feed)) { | ||
637 | printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n", | ||
638 | __func__, feed->type, feed->state, feed->pid); | ||
639 | goto out; | ||
640 | } | ||
641 | |||
642 | list_add(&feed->list_head, &feed->demux->feed_list); | ||
643 | out: | ||
644 | spin_unlock_irq(&feed->demux->lock); | ||
645 | } | ||
646 | |||
647 | static void dvb_demux_feed_del(struct dvb_demux_feed *feed) | ||
648 | { | ||
649 | spin_lock_irq(&feed->demux->lock); | ||
650 | if (!(dvb_demux_feed_find(feed))) { | ||
651 | printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n", | ||
652 | __func__, feed->type, feed->state, feed->pid); | ||
653 | goto out; | ||
654 | } | ||
655 | |||
656 | list_del(&feed->list_head); | ||
657 | out: | ||
658 | spin_unlock_irq(&feed->demux->lock); | ||
659 | } | ||
660 | |||
661 | static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type, | ||
662 | enum dmx_ts_pes pes_type, | ||
663 | size_t circular_buffer_size, struct timespec timeout) | ||
664 | { | ||
665 | struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; | ||
666 | struct dvb_demux *demux = feed->demux; | ||
667 | |||
668 | if (pid > DMX_MAX_PID) | ||
669 | return -EINVAL; | ||
670 | |||
671 | if (mutex_lock_interruptible(&demux->mutex)) | ||
672 | return -ERESTARTSYS; | ||
673 | |||
674 | if (ts_type & TS_DECODER) { | ||
675 | if (pes_type >= DMX_TS_PES_OTHER) { | ||
676 | mutex_unlock(&demux->mutex); | ||
677 | return -EINVAL; | ||
678 | } | ||
679 | |||
680 | if (demux->pesfilter[pes_type] && | ||
681 | demux->pesfilter[pes_type] != feed) { | ||
682 | mutex_unlock(&demux->mutex); | ||
683 | return -EINVAL; | ||
684 | } | ||
685 | |||
686 | demux->pesfilter[pes_type] = feed; | ||
687 | demux->pids[pes_type] = pid; | ||
688 | } | ||
689 | |||
690 | dvb_demux_feed_add(feed); | ||
691 | |||
692 | feed->pid = pid; | ||
693 | feed->buffer_size = circular_buffer_size; | ||
694 | feed->timeout = timeout; | ||
695 | feed->ts_type = ts_type; | ||
696 | feed->pes_type = pes_type; | ||
697 | |||
698 | if (feed->buffer_size) { | ||
699 | #ifdef NOBUFS | ||
700 | feed->buffer = NULL; | ||
701 | #else | ||
702 | feed->buffer = vmalloc(feed->buffer_size); | ||
703 | if (!feed->buffer) { | ||
704 | mutex_unlock(&demux->mutex); | ||
705 | return -ENOMEM; | ||
706 | } | ||
707 | #endif | ||
708 | } | ||
709 | |||
710 | feed->state = DMX_STATE_READY; | ||
711 | mutex_unlock(&demux->mutex); | ||
712 | |||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed) | ||
717 | { | ||
718 | struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; | ||
719 | struct dvb_demux *demux = feed->demux; | ||
720 | int ret; | ||
721 | |||
722 | if (mutex_lock_interruptible(&demux->mutex)) | ||
723 | return -ERESTARTSYS; | ||
724 | |||
725 | if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) { | ||
726 | mutex_unlock(&demux->mutex); | ||
727 | return -EINVAL; | ||
728 | } | ||
729 | |||
730 | if (!demux->start_feed) { | ||
731 | mutex_unlock(&demux->mutex); | ||
732 | return -ENODEV; | ||
733 | } | ||
734 | |||
735 | if ((ret = demux->start_feed(feed)) < 0) { | ||
736 | mutex_unlock(&demux->mutex); | ||
737 | return ret; | ||
738 | } | ||
739 | |||
740 | spin_lock_irq(&demux->lock); | ||
741 | ts_feed->is_filtering = 1; | ||
742 | feed->state = DMX_STATE_GO; | ||
743 | spin_unlock_irq(&demux->lock); | ||
744 | mutex_unlock(&demux->mutex); | ||
745 | |||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) | ||
750 | { | ||
751 | struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; | ||
752 | struct dvb_demux *demux = feed->demux; | ||
753 | int ret; | ||
754 | |||
755 | mutex_lock(&demux->mutex); | ||
756 | |||
757 | if (feed->state < DMX_STATE_GO) { | ||
758 | mutex_unlock(&demux->mutex); | ||
759 | return -EINVAL; | ||
760 | } | ||
761 | |||
762 | if (!demux->stop_feed) { | ||
763 | mutex_unlock(&demux->mutex); | ||
764 | return -ENODEV; | ||
765 | } | ||
766 | |||
767 | ret = demux->stop_feed(feed); | ||
768 | |||
769 | spin_lock_irq(&demux->lock); | ||
770 | ts_feed->is_filtering = 0; | ||
771 | feed->state = DMX_STATE_ALLOCATED; | ||
772 | spin_unlock_irq(&demux->lock); | ||
773 | mutex_unlock(&demux->mutex); | ||
774 | |||
775 | return ret; | ||
776 | } | ||
777 | |||
778 | static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, | ||
779 | struct dmx_ts_feed **ts_feed, | ||
780 | dmx_ts_cb callback) | ||
781 | { | ||
782 | struct dvb_demux *demux = (struct dvb_demux *)dmx; | ||
783 | struct dvb_demux_feed *feed; | ||
784 | |||
785 | if (mutex_lock_interruptible(&demux->mutex)) | ||
786 | return -ERESTARTSYS; | ||
787 | |||
788 | if (!(feed = dvb_dmx_feed_alloc(demux))) { | ||
789 | mutex_unlock(&demux->mutex); | ||
790 | return -EBUSY; | ||
791 | } | ||
792 | |||
793 | feed->type = DMX_TYPE_TS; | ||
794 | feed->cb.ts = callback; | ||
795 | feed->demux = demux; | ||
796 | feed->pid = 0xffff; | ||
797 | feed->peslen = 0xfffa; | ||
798 | feed->buffer = NULL; | ||
799 | |||
800 | (*ts_feed) = &feed->feed.ts; | ||
801 | (*ts_feed)->parent = dmx; | ||
802 | (*ts_feed)->priv = NULL; | ||
803 | (*ts_feed)->is_filtering = 0; | ||
804 | (*ts_feed)->start_filtering = dmx_ts_feed_start_filtering; | ||
805 | (*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering; | ||
806 | (*ts_feed)->set = dmx_ts_feed_set; | ||
807 | |||
808 | if (!(feed->filter = dvb_dmx_filter_alloc(demux))) { | ||
809 | feed->state = DMX_STATE_FREE; | ||
810 | mutex_unlock(&demux->mutex); | ||
811 | return -EBUSY; | ||
812 | } | ||
813 | |||
814 | feed->filter->type = DMX_TYPE_TS; | ||
815 | feed->filter->feed = feed; | ||
816 | feed->filter->state = DMX_STATE_READY; | ||
817 | |||
818 | mutex_unlock(&demux->mutex); | ||
819 | |||
820 | return 0; | ||
821 | } | ||
822 | |||
823 | static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, | ||
824 | struct dmx_ts_feed *ts_feed) | ||
825 | { | ||
826 | struct dvb_demux *demux = (struct dvb_demux *)dmx; | ||
827 | struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; | ||
828 | |||
829 | mutex_lock(&demux->mutex); | ||
830 | |||
831 | if (feed->state == DMX_STATE_FREE) { | ||
832 | mutex_unlock(&demux->mutex); | ||
833 | return -EINVAL; | ||
834 | } | ||
835 | #ifndef NOBUFS | ||
836 | vfree(feed->buffer); | ||
837 | feed->buffer = NULL; | ||
838 | #endif | ||
839 | |||
840 | feed->state = DMX_STATE_FREE; | ||
841 | feed->filter->state = DMX_STATE_FREE; | ||
842 | |||
843 | dvb_demux_feed_del(feed); | ||
844 | |||
845 | feed->pid = 0xffff; | ||
846 | |||
847 | if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER) | ||
848 | demux->pesfilter[feed->pes_type] = NULL; | ||
849 | |||
850 | mutex_unlock(&demux->mutex); | ||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | /****************************************************************************** | ||
855 | * dmx_section_feed API calls | ||
856 | ******************************************************************************/ | ||
857 | |||
858 | static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed, | ||
859 | struct dmx_section_filter **filter) | ||
860 | { | ||
861 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
862 | struct dvb_demux *dvbdemux = dvbdmxfeed->demux; | ||
863 | struct dvb_demux_filter *dvbdmxfilter; | ||
864 | |||
865 | if (mutex_lock_interruptible(&dvbdemux->mutex)) | ||
866 | return -ERESTARTSYS; | ||
867 | |||
868 | dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux); | ||
869 | if (!dvbdmxfilter) { | ||
870 | mutex_unlock(&dvbdemux->mutex); | ||
871 | return -EBUSY; | ||
872 | } | ||
873 | |||
874 | spin_lock_irq(&dvbdemux->lock); | ||
875 | *filter = &dvbdmxfilter->filter; | ||
876 | (*filter)->parent = feed; | ||
877 | (*filter)->priv = NULL; | ||
878 | dvbdmxfilter->feed = dvbdmxfeed; | ||
879 | dvbdmxfilter->type = DMX_TYPE_SEC; | ||
880 | dvbdmxfilter->state = DMX_STATE_READY; | ||
881 | dvbdmxfilter->next = dvbdmxfeed->filter; | ||
882 | dvbdmxfeed->filter = dvbdmxfilter; | ||
883 | spin_unlock_irq(&dvbdemux->lock); | ||
884 | |||
885 | mutex_unlock(&dvbdemux->mutex); | ||
886 | return 0; | ||
887 | } | ||
888 | |||
889 | static int dmx_section_feed_set(struct dmx_section_feed *feed, | ||
890 | u16 pid, size_t circular_buffer_size, | ||
891 | int check_crc) | ||
892 | { | ||
893 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
894 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
895 | |||
896 | if (pid > 0x1fff) | ||
897 | return -EINVAL; | ||
898 | |||
899 | if (mutex_lock_interruptible(&dvbdmx->mutex)) | ||
900 | return -ERESTARTSYS; | ||
901 | |||
902 | dvb_demux_feed_add(dvbdmxfeed); | ||
903 | |||
904 | dvbdmxfeed->pid = pid; | ||
905 | dvbdmxfeed->buffer_size = circular_buffer_size; | ||
906 | dvbdmxfeed->feed.sec.check_crc = check_crc; | ||
907 | |||
908 | #ifdef NOBUFS | ||
909 | dvbdmxfeed->buffer = NULL; | ||
910 | #else | ||
911 | dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size); | ||
912 | if (!dvbdmxfeed->buffer) { | ||
913 | mutex_unlock(&dvbdmx->mutex); | ||
914 | return -ENOMEM; | ||
915 | } | ||
916 | #endif | ||
917 | |||
918 | dvbdmxfeed->state = DMX_STATE_READY; | ||
919 | mutex_unlock(&dvbdmx->mutex); | ||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed) | ||
924 | { | ||
925 | int i; | ||
926 | struct dvb_demux_filter *f; | ||
927 | struct dmx_section_filter *sf; | ||
928 | u8 mask, mode, doneq; | ||
929 | |||
930 | if (!(f = dvbdmxfeed->filter)) | ||
931 | return; | ||
932 | do { | ||
933 | sf = &f->filter; | ||
934 | doneq = 0; | ||
935 | for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) { | ||
936 | mode = sf->filter_mode[i]; | ||
937 | mask = sf->filter_mask[i]; | ||
938 | f->maskandmode[i] = mask & mode; | ||
939 | doneq |= f->maskandnotmode[i] = mask & ~mode; | ||
940 | } | ||
941 | f->doneq = doneq ? 1 : 0; | ||
942 | } while ((f = f->next)); | ||
943 | } | ||
944 | |||
945 | static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) | ||
946 | { | ||
947 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
948 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
949 | int ret; | ||
950 | |||
951 | if (mutex_lock_interruptible(&dvbdmx->mutex)) | ||
952 | return -ERESTARTSYS; | ||
953 | |||
954 | if (feed->is_filtering) { | ||
955 | mutex_unlock(&dvbdmx->mutex); | ||
956 | return -EBUSY; | ||
957 | } | ||
958 | |||
959 | if (!dvbdmxfeed->filter) { | ||
960 | mutex_unlock(&dvbdmx->mutex); | ||
961 | return -EINVAL; | ||
962 | } | ||
963 | |||
964 | dvbdmxfeed->feed.sec.tsfeedp = 0; | ||
965 | dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; | ||
966 | dvbdmxfeed->feed.sec.secbufp = 0; | ||
967 | dvbdmxfeed->feed.sec.seclen = 0; | ||
968 | |||
969 | if (!dvbdmx->start_feed) { | ||
970 | mutex_unlock(&dvbdmx->mutex); | ||
971 | return -ENODEV; | ||
972 | } | ||
973 | |||
974 | prepare_secfilters(dvbdmxfeed); | ||
975 | |||
976 | if ((ret = dvbdmx->start_feed(dvbdmxfeed)) < 0) { | ||
977 | mutex_unlock(&dvbdmx->mutex); | ||
978 | return ret; | ||
979 | } | ||
980 | |||
981 | spin_lock_irq(&dvbdmx->lock); | ||
982 | feed->is_filtering = 1; | ||
983 | dvbdmxfeed->state = DMX_STATE_GO; | ||
984 | spin_unlock_irq(&dvbdmx->lock); | ||
985 | |||
986 | mutex_unlock(&dvbdmx->mutex); | ||
987 | return 0; | ||
988 | } | ||
989 | |||
990 | static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed) | ||
991 | { | ||
992 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
993 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
994 | int ret; | ||
995 | |||
996 | mutex_lock(&dvbdmx->mutex); | ||
997 | |||
998 | if (!dvbdmx->stop_feed) { | ||
999 | mutex_unlock(&dvbdmx->mutex); | ||
1000 | return -ENODEV; | ||
1001 | } | ||
1002 | |||
1003 | ret = dvbdmx->stop_feed(dvbdmxfeed); | ||
1004 | |||
1005 | spin_lock_irq(&dvbdmx->lock); | ||
1006 | dvbdmxfeed->state = DMX_STATE_READY; | ||
1007 | feed->is_filtering = 0; | ||
1008 | spin_unlock_irq(&dvbdmx->lock); | ||
1009 | |||
1010 | mutex_unlock(&dvbdmx->mutex); | ||
1011 | return ret; | ||
1012 | } | ||
1013 | |||
1014 | static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, | ||
1015 | struct dmx_section_filter *filter) | ||
1016 | { | ||
1017 | struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *)filter, *f; | ||
1018 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
1019 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
1020 | |||
1021 | mutex_lock(&dvbdmx->mutex); | ||
1022 | |||
1023 | if (dvbdmxfilter->feed != dvbdmxfeed) { | ||
1024 | mutex_unlock(&dvbdmx->mutex); | ||
1025 | return -EINVAL; | ||
1026 | } | ||
1027 | |||
1028 | if (feed->is_filtering) | ||
1029 | feed->stop_filtering(feed); | ||
1030 | |||
1031 | spin_lock_irq(&dvbdmx->lock); | ||
1032 | f = dvbdmxfeed->filter; | ||
1033 | |||
1034 | if (f == dvbdmxfilter) { | ||
1035 | dvbdmxfeed->filter = dvbdmxfilter->next; | ||
1036 | } else { | ||
1037 | while (f->next != dvbdmxfilter) | ||
1038 | f = f->next; | ||
1039 | f->next = f->next->next; | ||
1040 | } | ||
1041 | |||
1042 | dvbdmxfilter->state = DMX_STATE_FREE; | ||
1043 | spin_unlock_irq(&dvbdmx->lock); | ||
1044 | mutex_unlock(&dvbdmx->mutex); | ||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1048 | static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, | ||
1049 | struct dmx_section_feed **feed, | ||
1050 | dmx_section_cb callback) | ||
1051 | { | ||
1052 | struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; | ||
1053 | struct dvb_demux_feed *dvbdmxfeed; | ||
1054 | |||
1055 | if (mutex_lock_interruptible(&dvbdmx->mutex)) | ||
1056 | return -ERESTARTSYS; | ||
1057 | |||
1058 | if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) { | ||
1059 | mutex_unlock(&dvbdmx->mutex); | ||
1060 | return -EBUSY; | ||
1061 | } | ||
1062 | |||
1063 | dvbdmxfeed->type = DMX_TYPE_SEC; | ||
1064 | dvbdmxfeed->cb.sec = callback; | ||
1065 | dvbdmxfeed->demux = dvbdmx; | ||
1066 | dvbdmxfeed->pid = 0xffff; | ||
1067 | dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; | ||
1068 | dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; | ||
1069 | dvbdmxfeed->feed.sec.tsfeedp = 0; | ||
1070 | dvbdmxfeed->filter = NULL; | ||
1071 | dvbdmxfeed->buffer = NULL; | ||
1072 | |||
1073 | (*feed) = &dvbdmxfeed->feed.sec; | ||
1074 | (*feed)->is_filtering = 0; | ||
1075 | (*feed)->parent = demux; | ||
1076 | (*feed)->priv = NULL; | ||
1077 | |||
1078 | (*feed)->set = dmx_section_feed_set; | ||
1079 | (*feed)->allocate_filter = dmx_section_feed_allocate_filter; | ||
1080 | (*feed)->start_filtering = dmx_section_feed_start_filtering; | ||
1081 | (*feed)->stop_filtering = dmx_section_feed_stop_filtering; | ||
1082 | (*feed)->release_filter = dmx_section_feed_release_filter; | ||
1083 | |||
1084 | mutex_unlock(&dvbdmx->mutex); | ||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | static int dvbdmx_release_section_feed(struct dmx_demux *demux, | ||
1089 | struct dmx_section_feed *feed) | ||
1090 | { | ||
1091 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
1092 | struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; | ||
1093 | |||
1094 | mutex_lock(&dvbdmx->mutex); | ||
1095 | |||
1096 | if (dvbdmxfeed->state == DMX_STATE_FREE) { | ||
1097 | mutex_unlock(&dvbdmx->mutex); | ||
1098 | return -EINVAL; | ||
1099 | } | ||
1100 | #ifndef NOBUFS | ||
1101 | vfree(dvbdmxfeed->buffer); | ||
1102 | dvbdmxfeed->buffer = NULL; | ||
1103 | #endif | ||
1104 | dvbdmxfeed->state = DMX_STATE_FREE; | ||
1105 | |||
1106 | dvb_demux_feed_del(dvbdmxfeed); | ||
1107 | |||
1108 | dvbdmxfeed->pid = 0xffff; | ||
1109 | |||
1110 | mutex_unlock(&dvbdmx->mutex); | ||
1111 | return 0; | ||
1112 | } | ||
1113 | |||
1114 | /****************************************************************************** | ||
1115 | * dvb_demux kernel data API calls | ||
1116 | ******************************************************************************/ | ||
1117 | |||
1118 | static int dvbdmx_open(struct dmx_demux *demux) | ||
1119 | { | ||
1120 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1121 | |||
1122 | if (dvbdemux->users >= MAX_DVB_DEMUX_USERS) | ||
1123 | return -EUSERS; | ||
1124 | |||
1125 | dvbdemux->users++; | ||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1129 | static int dvbdmx_close(struct dmx_demux *demux) | ||
1130 | { | ||
1131 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1132 | |||
1133 | if (dvbdemux->users == 0) | ||
1134 | return -ENODEV; | ||
1135 | |||
1136 | dvbdemux->users--; | ||
1137 | //FIXME: release any unneeded resources if users==0 | ||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t count) | ||
1142 | { | ||
1143 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1144 | void *p; | ||
1145 | |||
1146 | if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE)) | ||
1147 | return -EINVAL; | ||
1148 | |||
1149 | p = memdup_user(buf, count); | ||
1150 | if (IS_ERR(p)) | ||
1151 | return PTR_ERR(p); | ||
1152 | if (mutex_lock_interruptible(&dvbdemux->mutex)) { | ||
1153 | kfree(p); | ||
1154 | return -ERESTARTSYS; | ||
1155 | } | ||
1156 | dvb_dmx_swfilter(dvbdemux, p, count); | ||
1157 | kfree(p); | ||
1158 | mutex_unlock(&dvbdemux->mutex); | ||
1159 | |||
1160 | if (signal_pending(current)) | ||
1161 | return -EINTR; | ||
1162 | return count; | ||
1163 | } | ||
1164 | |||
1165 | static int dvbdmx_add_frontend(struct dmx_demux *demux, | ||
1166 | struct dmx_frontend *frontend) | ||
1167 | { | ||
1168 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1169 | struct list_head *head = &dvbdemux->frontend_list; | ||
1170 | |||
1171 | list_add(&(frontend->connectivity_list), head); | ||
1172 | |||
1173 | return 0; | ||
1174 | } | ||
1175 | |||
1176 | static int dvbdmx_remove_frontend(struct dmx_demux *demux, | ||
1177 | struct dmx_frontend *frontend) | ||
1178 | { | ||
1179 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1180 | struct list_head *pos, *n, *head = &dvbdemux->frontend_list; | ||
1181 | |||
1182 | list_for_each_safe(pos, n, head) { | ||
1183 | if (DMX_FE_ENTRY(pos) == frontend) { | ||
1184 | list_del(pos); | ||
1185 | return 0; | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | return -ENODEV; | ||
1190 | } | ||
1191 | |||
1192 | static struct list_head *dvbdmx_get_frontends(struct dmx_demux *demux) | ||
1193 | { | ||
1194 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1195 | |||
1196 | if (list_empty(&dvbdemux->frontend_list)) | ||
1197 | return NULL; | ||
1198 | |||
1199 | return &dvbdemux->frontend_list; | ||
1200 | } | ||
1201 | |||
1202 | static int dvbdmx_connect_frontend(struct dmx_demux *demux, | ||
1203 | struct dmx_frontend *frontend) | ||
1204 | { | ||
1205 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1206 | |||
1207 | if (demux->frontend) | ||
1208 | return -EINVAL; | ||
1209 | |||
1210 | mutex_lock(&dvbdemux->mutex); | ||
1211 | |||
1212 | demux->frontend = frontend; | ||
1213 | mutex_unlock(&dvbdemux->mutex); | ||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | static int dvbdmx_disconnect_frontend(struct dmx_demux *demux) | ||
1218 | { | ||
1219 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1220 | |||
1221 | mutex_lock(&dvbdemux->mutex); | ||
1222 | |||
1223 | demux->frontend = NULL; | ||
1224 | mutex_unlock(&dvbdemux->mutex); | ||
1225 | return 0; | ||
1226 | } | ||
1227 | |||
1228 | static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids) | ||
1229 | { | ||
1230 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1231 | |||
1232 | memcpy(pids, dvbdemux->pids, 5 * sizeof(u16)); | ||
1233 | return 0; | ||
1234 | } | ||
1235 | |||
1236 | int dvb_dmx_init(struct dvb_demux *dvbdemux) | ||
1237 | { | ||
1238 | int i; | ||
1239 | struct dmx_demux *dmx = &dvbdemux->dmx; | ||
1240 | |||
1241 | dvbdemux->cnt_storage = NULL; | ||
1242 | dvbdemux->users = 0; | ||
1243 | dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter)); | ||
1244 | |||
1245 | if (!dvbdemux->filter) | ||
1246 | return -ENOMEM; | ||
1247 | |||
1248 | dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed)); | ||
1249 | if (!dvbdemux->feed) { | ||
1250 | vfree(dvbdemux->filter); | ||
1251 | dvbdemux->filter = NULL; | ||
1252 | return -ENOMEM; | ||
1253 | } | ||
1254 | for (i = 0; i < dvbdemux->filternum; i++) { | ||
1255 | dvbdemux->filter[i].state = DMX_STATE_FREE; | ||
1256 | dvbdemux->filter[i].index = i; | ||
1257 | } | ||
1258 | for (i = 0; i < dvbdemux->feednum; i++) { | ||
1259 | dvbdemux->feed[i].state = DMX_STATE_FREE; | ||
1260 | dvbdemux->feed[i].index = i; | ||
1261 | } | ||
1262 | |||
1263 | dvbdemux->cnt_storage = vmalloc(MAX_PID + 1); | ||
1264 | if (!dvbdemux->cnt_storage) | ||
1265 | printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n"); | ||
1266 | |||
1267 | INIT_LIST_HEAD(&dvbdemux->frontend_list); | ||
1268 | |||
1269 | for (i = 0; i < DMX_TS_PES_OTHER; i++) { | ||
1270 | dvbdemux->pesfilter[i] = NULL; | ||
1271 | dvbdemux->pids[i] = 0xffff; | ||
1272 | } | ||
1273 | |||
1274 | INIT_LIST_HEAD(&dvbdemux->feed_list); | ||
1275 | |||
1276 | dvbdemux->playing = 0; | ||
1277 | dvbdemux->recording = 0; | ||
1278 | dvbdemux->tsbufp = 0; | ||
1279 | |||
1280 | if (!dvbdemux->check_crc32) | ||
1281 | dvbdemux->check_crc32 = dvb_dmx_crc32; | ||
1282 | |||
1283 | if (!dvbdemux->memcopy) | ||
1284 | dvbdemux->memcopy = dvb_dmx_memcopy; | ||
1285 | |||
1286 | dmx->frontend = NULL; | ||
1287 | dmx->priv = dvbdemux; | ||
1288 | dmx->open = dvbdmx_open; | ||
1289 | dmx->close = dvbdmx_close; | ||
1290 | dmx->write = dvbdmx_write; | ||
1291 | dmx->allocate_ts_feed = dvbdmx_allocate_ts_feed; | ||
1292 | dmx->release_ts_feed = dvbdmx_release_ts_feed; | ||
1293 | dmx->allocate_section_feed = dvbdmx_allocate_section_feed; | ||
1294 | dmx->release_section_feed = dvbdmx_release_section_feed; | ||
1295 | |||
1296 | dmx->add_frontend = dvbdmx_add_frontend; | ||
1297 | dmx->remove_frontend = dvbdmx_remove_frontend; | ||
1298 | dmx->get_frontends = dvbdmx_get_frontends; | ||
1299 | dmx->connect_frontend = dvbdmx_connect_frontend; | ||
1300 | dmx->disconnect_frontend = dvbdmx_disconnect_frontend; | ||
1301 | dmx->get_pes_pids = dvbdmx_get_pes_pids; | ||
1302 | |||
1303 | mutex_init(&dvbdemux->mutex); | ||
1304 | spin_lock_init(&dvbdemux->lock); | ||
1305 | |||
1306 | return 0; | ||
1307 | } | ||
1308 | |||
1309 | EXPORT_SYMBOL(dvb_dmx_init); | ||
1310 | |||
1311 | void dvb_dmx_release(struct dvb_demux *dvbdemux) | ||
1312 | { | ||
1313 | vfree(dvbdemux->cnt_storage); | ||
1314 | vfree(dvbdemux->filter); | ||
1315 | vfree(dvbdemux->feed); | ||
1316 | } | ||
1317 | |||
1318 | EXPORT_SYMBOL(dvb_dmx_release); | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h deleted file mode 100644 index fa7188a253aa..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_demux.h +++ /dev/null | |||
@@ -1,151 +0,0 @@ | |||
1 | /* | ||
2 | * dvb_demux.h: DVB kernel demux API | ||
3 | * | ||
4 | * Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler | ||
5 | * for convergence integrated media GmbH | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public License | ||
9 | * as published by the Free Software Foundation; either version 2.1 | ||
10 | * of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef _DVB_DEMUX_H_ | ||
24 | #define _DVB_DEMUX_H_ | ||
25 | |||
26 | #include <linux/time.h> | ||
27 | #include <linux/timer.h> | ||
28 | #include <linux/spinlock.h> | ||
29 | #include <linux/mutex.h> | ||
30 | |||
31 | #include "demux.h" | ||
32 | |||
33 | #define DMX_TYPE_TS 0 | ||
34 | #define DMX_TYPE_SEC 1 | ||
35 | #define DMX_TYPE_PES 2 | ||
36 | |||
37 | #define DMX_STATE_FREE 0 | ||
38 | #define DMX_STATE_ALLOCATED 1 | ||
39 | #define DMX_STATE_SET 2 | ||
40 | #define DMX_STATE_READY 3 | ||
41 | #define DMX_STATE_GO 4 | ||
42 | |||
43 | #define DVB_DEMUX_MASK_MAX 18 | ||
44 | |||
45 | #define MAX_PID 0x1fff | ||
46 | |||
47 | #define SPEED_PKTS_INTERVAL 50000 | ||
48 | |||
49 | struct dvb_demux_filter { | ||
50 | struct dmx_section_filter filter; | ||
51 | u8 maskandmode[DMX_MAX_FILTER_SIZE]; | ||
52 | u8 maskandnotmode[DMX_MAX_FILTER_SIZE]; | ||
53 | int doneq; | ||
54 | |||
55 | struct dvb_demux_filter *next; | ||
56 | struct dvb_demux_feed *feed; | ||
57 | int index; | ||
58 | int state; | ||
59 | int type; | ||
60 | |||
61 | u16 hw_handle; | ||
62 | struct timer_list timer; | ||
63 | }; | ||
64 | |||
65 | #define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head) | ||
66 | |||
67 | struct dvb_demux_feed { | ||
68 | union { | ||
69 | struct dmx_ts_feed ts; | ||
70 | struct dmx_section_feed sec; | ||
71 | } feed; | ||
72 | |||
73 | union { | ||
74 | dmx_ts_cb ts; | ||
75 | dmx_section_cb sec; | ||
76 | } cb; | ||
77 | |||
78 | struct dvb_demux *demux; | ||
79 | void *priv; | ||
80 | int type; | ||
81 | int state; | ||
82 | u16 pid; | ||
83 | u8 *buffer; | ||
84 | int buffer_size; | ||
85 | |||
86 | struct timespec timeout; | ||
87 | struct dvb_demux_filter *filter; | ||
88 | |||
89 | int ts_type; | ||
90 | enum dmx_ts_pes pes_type; | ||
91 | |||
92 | int cc; | ||
93 | int pusi_seen; /* prevents feeding of garbage from previous section */ | ||
94 | |||
95 | u16 peslen; | ||
96 | |||
97 | struct list_head list_head; | ||
98 | unsigned int index; /* a unique index for each feed (can be used as hardware pid filter index) */ | ||
99 | }; | ||
100 | |||
101 | struct dvb_demux { | ||
102 | struct dmx_demux dmx; | ||
103 | void *priv; | ||
104 | int filternum; | ||
105 | int feednum; | ||
106 | int (*start_feed)(struct dvb_demux_feed *feed); | ||
107 | int (*stop_feed)(struct dvb_demux_feed *feed); | ||
108 | int (*write_to_decoder)(struct dvb_demux_feed *feed, | ||
109 | const u8 *buf, size_t len); | ||
110 | u32 (*check_crc32)(struct dvb_demux_feed *feed, | ||
111 | const u8 *buf, size_t len); | ||
112 | void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst, | ||
113 | const u8 *src, size_t len); | ||
114 | |||
115 | int users; | ||
116 | #define MAX_DVB_DEMUX_USERS 10 | ||
117 | struct dvb_demux_filter *filter; | ||
118 | struct dvb_demux_feed *feed; | ||
119 | |||
120 | struct list_head frontend_list; | ||
121 | |||
122 | struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER]; | ||
123 | u16 pids[DMX_TS_PES_OTHER]; | ||
124 | int playing; | ||
125 | int recording; | ||
126 | |||
127 | #define DMX_MAX_PID 0x2000 | ||
128 | struct list_head feed_list; | ||
129 | u8 tsbuf[204]; | ||
130 | int tsbufp; | ||
131 | |||
132 | struct mutex mutex; | ||
133 | spinlock_t lock; | ||
134 | |||
135 | uint8_t *cnt_storage; /* for TS continuity check */ | ||
136 | |||
137 | struct timespec speed_last_time; /* for TS speed check */ | ||
138 | uint32_t speed_pkts_cnt; /* for TS speed check */ | ||
139 | }; | ||
140 | |||
141 | int dvb_dmx_init(struct dvb_demux *dvbdemux); | ||
142 | void dvb_dmx_release(struct dvb_demux *dvbdemux); | ||
143 | void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, | ||
144 | size_t count); | ||
145 | void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count); | ||
146 | void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, | ||
147 | size_t count); | ||
148 | void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, | ||
149 | size_t count); | ||
150 | |||
151 | #endif /* _DVB_DEMUX_H_ */ | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c deleted file mode 100644 index 772003fb1821..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_filter.c +++ /dev/null | |||
@@ -1,603 +0,0 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <linux/string.h> | ||
4 | #include "dvb_filter.h" | ||
5 | |||
6 | #if 0 | ||
7 | static unsigned int bitrates[3][16] = | ||
8 | {{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, | ||
9 | {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, | ||
10 | {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}}; | ||
11 | #endif | ||
12 | |||
13 | static u32 freq[4] = {480, 441, 320, 0}; | ||
14 | |||
15 | static unsigned int ac3_bitrates[32] = | ||
16 | {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640, | ||
17 | 0,0,0,0,0,0,0,0,0,0,0,0,0}; | ||
18 | |||
19 | static u32 ac3_frames[3][32] = | ||
20 | {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024, | ||
21 | 1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0}, | ||
22 | {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114, | ||
23 | 1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0}, | ||
24 | {96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344, | ||
25 | 1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}}; | ||
26 | |||
27 | |||
28 | |||
29 | #if 0 | ||
30 | static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, | ||
31 | void (*pes_write)(u8 *buf, int count, void *data), | ||
32 | void *priv) | ||
33 | { | ||
34 | dvb_filter_ipack_init(pa, IPACKS, pes_write); | ||
35 | dvb_filter_ipack_init(pv, IPACKS, pes_write); | ||
36 | pa->pid = pida; | ||
37 | pv->pid = pidv; | ||
38 | pa->data = priv; | ||
39 | pv->data = priv; | ||
40 | } | ||
41 | #endif | ||
42 | |||
43 | #if 0 | ||
44 | static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188) | ||
45 | { | ||
46 | u8 off = 0; | ||
47 | |||
48 | if (!buf || !p ){ | ||
49 | printk("NULL POINTER IDIOT\n"); | ||
50 | return; | ||
51 | } | ||
52 | if (buf[1]&PAY_START) { | ||
53 | if (p->plength == MMAX_PLENGTH-6 && p->found>6){ | ||
54 | p->plength = p->found-6; | ||
55 | p->found = 0; | ||
56 | send_ipack(p); | ||
57 | dvb_filter_ipack_reset(p); | ||
58 | } | ||
59 | } | ||
60 | if (buf[3] & ADAPT_FIELD) { // adaptation field? | ||
61 | off = buf[4] + 1; | ||
62 | if (off+4 > 187) return; | ||
63 | } | ||
64 | dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p); | ||
65 | } | ||
66 | #endif | ||
67 | |||
68 | #if 0 | ||
69 | /* needs 5 byte input, returns picture coding type*/ | ||
70 | static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, int pr) | ||
71 | { | ||
72 | u8 pct; | ||
73 | |||
74 | if (pr) printk( "Pic header: "); | ||
75 | pic->temporal_reference[field] = (( headr[0] << 2 ) | | ||
76 | (headr[1] & 0x03) )& 0x03ff; | ||
77 | if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]); | ||
78 | |||
79 | pct = ( headr[1] >> 2 ) & 0x07; | ||
80 | pic->picture_coding_type[field] = pct; | ||
81 | if (pr) { | ||
82 | switch(pct){ | ||
83 | case I_FRAME: | ||
84 | printk( " I-FRAME"); | ||
85 | break; | ||
86 | case B_FRAME: | ||
87 | printk( " B-FRAME"); | ||
88 | break; | ||
89 | case P_FRAME: | ||
90 | printk( " P-FRAME"); | ||
91 | break; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | |||
96 | pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) | | ||
97 | ( (headr[3] & 0x1F) << 11) ) & 0xffff; | ||
98 | |||
99 | if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay); | ||
100 | |||
101 | pic->picture_header_parameter = ( headr[3] & 0xe0 ) | | ||
102 | ((headr[4] & 0x80) >> 3); | ||
103 | |||
104 | if ( pct == B_FRAME ){ | ||
105 | pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f; | ||
106 | } | ||
107 | if (pr) printk( " pic head param: 0x%x", | ||
108 | pic->picture_header_parameter); | ||
109 | |||
110 | return pct; | ||
111 | } | ||
112 | #endif | ||
113 | |||
114 | #if 0 | ||
115 | /* needs 4 byte input */ | ||
116 | static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr) | ||
117 | { | ||
118 | if (pr) printk("GOP header: "); | ||
119 | |||
120 | pic->time_code = (( headr[0] << 17 ) | ( headr[1] << 9) | | ||
121 | ( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff; | ||
122 | |||
123 | if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F, | ||
124 | ((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F), | ||
125 | ((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F)); | ||
126 | |||
127 | if ( ( headr[3] & 0x40 ) != 0 ){ | ||
128 | pic->closed_gop = 1; | ||
129 | } else { | ||
130 | pic->closed_gop = 0; | ||
131 | } | ||
132 | if (pr) printk("closed: %d", pic->closed_gop); | ||
133 | |||
134 | if ( ( headr[3] & 0x20 ) != 0 ){ | ||
135 | pic->broken_link = 1; | ||
136 | } else { | ||
137 | pic->broken_link = 0; | ||
138 | } | ||
139 | if (pr) printk(" broken: %d\n", pic->broken_link); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | #endif | ||
144 | |||
145 | #if 0 | ||
146 | /* needs 8 byte input */ | ||
147 | static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr) | ||
148 | { | ||
149 | int sw; | ||
150 | int form = -1; | ||
151 | |||
152 | if (pr) printk("Reading sequence header\n"); | ||
153 | |||
154 | vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4); | ||
155 | vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]); | ||
156 | |||
157 | sw = (int)((headr[3]&0xF0) >> 4) ; | ||
158 | |||
159 | switch( sw ){ | ||
160 | case 1: | ||
161 | if (pr) | ||
162 | printk("Videostream: ASPECT: 1:1"); | ||
163 | vi->aspect_ratio = 100; | ||
164 | break; | ||
165 | case 2: | ||
166 | if (pr) | ||
167 | printk("Videostream: ASPECT: 4:3"); | ||
168 | vi->aspect_ratio = 133; | ||
169 | break; | ||
170 | case 3: | ||
171 | if (pr) | ||
172 | printk("Videostream: ASPECT: 16:9"); | ||
173 | vi->aspect_ratio = 177; | ||
174 | break; | ||
175 | case 4: | ||
176 | if (pr) | ||
177 | printk("Videostream: ASPECT: 2.21:1"); | ||
178 | vi->aspect_ratio = 221; | ||
179 | break; | ||
180 | |||
181 | case 5 ... 15: | ||
182 | if (pr) | ||
183 | printk("Videostream: ASPECT: reserved"); | ||
184 | vi->aspect_ratio = 0; | ||
185 | break; | ||
186 | |||
187 | default: | ||
188 | vi->aspect_ratio = 0; | ||
189 | return -1; | ||
190 | } | ||
191 | |||
192 | if (pr) | ||
193 | printk(" Size = %dx%d",vi->horizontal_size,vi->vertical_size); | ||
194 | |||
195 | sw = (int)(headr[3]&0x0F); | ||
196 | |||
197 | switch ( sw ) { | ||
198 | case 1: | ||
199 | if (pr) | ||
200 | printk(" FRate: 23.976 fps"); | ||
201 | vi->framerate = 23976; | ||
202 | form = -1; | ||
203 | break; | ||
204 | case 2: | ||
205 | if (pr) | ||
206 | printk(" FRate: 24 fps"); | ||
207 | vi->framerate = 24000; | ||
208 | form = -1; | ||
209 | break; | ||
210 | case 3: | ||
211 | if (pr) | ||
212 | printk(" FRate: 25 fps"); | ||
213 | vi->framerate = 25000; | ||
214 | form = VIDEO_MODE_PAL; | ||
215 | break; | ||
216 | case 4: | ||
217 | if (pr) | ||
218 | printk(" FRate: 29.97 fps"); | ||
219 | vi->framerate = 29970; | ||
220 | form = VIDEO_MODE_NTSC; | ||
221 | break; | ||
222 | case 5: | ||
223 | if (pr) | ||
224 | printk(" FRate: 30 fps"); | ||
225 | vi->framerate = 30000; | ||
226 | form = VIDEO_MODE_NTSC; | ||
227 | break; | ||
228 | case 6: | ||
229 | if (pr) | ||
230 | printk(" FRate: 50 fps"); | ||
231 | vi->framerate = 50000; | ||
232 | form = VIDEO_MODE_PAL; | ||
233 | break; | ||
234 | case 7: | ||
235 | if (pr) | ||
236 | printk(" FRate: 60 fps"); | ||
237 | vi->framerate = 60000; | ||
238 | form = VIDEO_MODE_NTSC; | ||
239 | break; | ||
240 | } | ||
241 | |||
242 | vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03); | ||
243 | |||
244 | vi->vbv_buffer_size | ||
245 | = (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5); | ||
246 | |||
247 | if (pr){ | ||
248 | printk(" BRate: %d Mbit/s",4*(vi->bit_rate)/10000); | ||
249 | printk(" vbvbuffer %d",16*1024*(vi->vbv_buffer_size)); | ||
250 | printk("\n"); | ||
251 | } | ||
252 | |||
253 | vi->video_format = form; | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | #endif | ||
258 | |||
259 | |||
260 | #if 0 | ||
261 | static int get_vinfo(u8 *mbuf, int count, struct dvb_video_info *vi, int pr) | ||
262 | { | ||
263 | u8 *headr; | ||
264 | int found = 0; | ||
265 | int c = 0; | ||
266 | |||
267 | while (found < 4 && c+4 < count){ | ||
268 | u8 *b; | ||
269 | |||
270 | b = mbuf+c; | ||
271 | if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01 | ||
272 | && b[3] == 0xb3) found = 4; | ||
273 | else { | ||
274 | c++; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | if (! found) return -1; | ||
279 | c += 4; | ||
280 | if (c+12 >= count) return -1; | ||
281 | headr = mbuf+c; | ||
282 | if (read_sequence_header(headr, vi, pr) < 0) return -1; | ||
283 | vi->off = c-4; | ||
284 | return 0; | ||
285 | } | ||
286 | #endif | ||
287 | |||
288 | |||
289 | #if 0 | ||
290 | static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr) | ||
291 | { | ||
292 | u8 *headr; | ||
293 | int found = 0; | ||
294 | int c = 0; | ||
295 | int fr = 0; | ||
296 | |||
297 | while (found < 2 && c < count){ | ||
298 | u8 b[2]; | ||
299 | memcpy( b, mbuf+c, 2); | ||
300 | |||
301 | if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8) | ||
302 | found = 2; | ||
303 | else { | ||
304 | c++; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | if (!found) return -1; | ||
309 | |||
310 | if (c+3 >= count) return -1; | ||
311 | headr = mbuf+c; | ||
312 | |||
313 | ai->layer = (headr[1] & 0x06) >> 1; | ||
314 | |||
315 | if (pr) | ||
316 | printk("Audiostream: Layer: %d", 4-ai->layer); | ||
317 | |||
318 | |||
319 | ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000; | ||
320 | |||
321 | if (pr){ | ||
322 | if (ai->bit_rate == 0) | ||
323 | printk(" Bit rate: free"); | ||
324 | else if (ai->bit_rate == 0xf) | ||
325 | printk(" BRate: reserved"); | ||
326 | else | ||
327 | printk(" BRate: %d kb/s", ai->bit_rate/1000); | ||
328 | } | ||
329 | |||
330 | fr = (headr[2] & 0x0c ) >> 2; | ||
331 | ai->frequency = freq[fr]*100; | ||
332 | if (pr){ | ||
333 | if (ai->frequency == 3) | ||
334 | printk(" Freq: reserved\n"); | ||
335 | else | ||
336 | printk(" Freq: %d kHz\n",ai->frequency); | ||
337 | |||
338 | } | ||
339 | ai->off = c; | ||
340 | return 0; | ||
341 | } | ||
342 | #endif | ||
343 | |||
344 | |||
345 | int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr) | ||
346 | { | ||
347 | u8 *headr; | ||
348 | int found = 0; | ||
349 | int c = 0; | ||
350 | u8 frame = 0; | ||
351 | int fr = 0; | ||
352 | |||
353 | while ( !found && c < count){ | ||
354 | u8 *b = mbuf+c; | ||
355 | |||
356 | if ( b[0] == 0x0b && b[1] == 0x77 ) | ||
357 | found = 1; | ||
358 | else { | ||
359 | c++; | ||
360 | } | ||
361 | } | ||
362 | |||
363 | if (!found) return -1; | ||
364 | if (pr) | ||
365 | printk("Audiostream: AC3"); | ||
366 | |||
367 | ai->off = c; | ||
368 | if (c+5 >= count) return -1; | ||
369 | |||
370 | ai->layer = 0; // 0 for AC3 | ||
371 | headr = mbuf+c+2; | ||
372 | |||
373 | frame = (headr[2]&0x3f); | ||
374 | ai->bit_rate = ac3_bitrates[frame >> 1]*1000; | ||
375 | |||
376 | if (pr) | ||
377 | printk(" BRate: %d kb/s", (int) ai->bit_rate/1000); | ||
378 | |||
379 | ai->frequency = (headr[2] & 0xc0 ) >> 6; | ||
380 | fr = (headr[2] & 0xc0 ) >> 6; | ||
381 | ai->frequency = freq[fr]*100; | ||
382 | if (pr) printk (" Freq: %d Hz\n", (int) ai->frequency); | ||
383 | |||
384 | |||
385 | ai->framesize = ac3_frames[fr][frame >> 1]; | ||
386 | if ((frame & 1) && (fr == 1)) ai->framesize++; | ||
387 | ai->framesize = ai->framesize << 1; | ||
388 | if (pr) printk (" Framesize %d\n",(int) ai->framesize); | ||
389 | |||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | EXPORT_SYMBOL(dvb_filter_get_ac3info); | ||
394 | |||
395 | |||
396 | #if 0 | ||
397 | static u8 *skip_pes_header(u8 **bufp) | ||
398 | { | ||
399 | u8 *inbuf = *bufp; | ||
400 | u8 *buf = inbuf; | ||
401 | u8 *pts = NULL; | ||
402 | int skip = 0; | ||
403 | |||
404 | static const int mpeg1_skip_table[16] = { | ||
405 | 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff, | ||
406 | 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff | ||
407 | }; | ||
408 | |||
409 | |||
410 | if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */ | ||
411 | if (buf[7] & PTS_ONLY) | ||
412 | pts = buf+9; | ||
413 | else pts = NULL; | ||
414 | buf = inbuf + 9 + inbuf[8]; | ||
415 | } else { /* mpeg1 */ | ||
416 | for (buf = inbuf + 6; *buf == 0xff; buf++) | ||
417 | if (buf == inbuf + 6 + 16) { | ||
418 | break; | ||
419 | } | ||
420 | if ((*buf & 0xc0) == 0x40) | ||
421 | buf += 2; | ||
422 | skip = mpeg1_skip_table [*buf >> 4]; | ||
423 | if (skip == 5 || skip == 10) pts = buf; | ||
424 | else pts = NULL; | ||
425 | |||
426 | buf += mpeg1_skip_table [*buf >> 4]; | ||
427 | } | ||
428 | |||
429 | *bufp = buf; | ||
430 | return pts; | ||
431 | } | ||
432 | #endif | ||
433 | |||
434 | #if 0 | ||
435 | static void initialize_quant_matrix( u32 *matrix ) | ||
436 | { | ||
437 | int i; | ||
438 | |||
439 | matrix[0] = 0x08101013; | ||
440 | matrix[1] = 0x10131616; | ||
441 | matrix[2] = 0x16161616; | ||
442 | matrix[3] = 0x1a181a1b; | ||
443 | matrix[4] = 0x1b1b1a1a; | ||
444 | matrix[5] = 0x1a1a1b1b; | ||
445 | matrix[6] = 0x1b1d1d1d; | ||
446 | matrix[7] = 0x2222221d; | ||
447 | matrix[8] = 0x1d1d1b1b; | ||
448 | matrix[9] = 0x1d1d2020; | ||
449 | matrix[10] = 0x22222526; | ||
450 | matrix[11] = 0x25232322; | ||
451 | matrix[12] = 0x23262628; | ||
452 | matrix[13] = 0x28283030; | ||
453 | matrix[14] = 0x2e2e3838; | ||
454 | matrix[15] = 0x3a454553; | ||
455 | |||
456 | for ( i = 16 ; i < 32 ; i++ ) | ||
457 | matrix[i] = 0x10101010; | ||
458 | } | ||
459 | #endif | ||
460 | |||
461 | #if 0 | ||
462 | static void initialize_mpg_picture(struct mpg_picture *pic) | ||
463 | { | ||
464 | int i; | ||
465 | |||
466 | /* set MPEG1 */ | ||
467 | pic->mpeg1_flag = 1; | ||
468 | pic->profile_and_level = 0x4A ; /* MP@LL */ | ||
469 | pic->progressive_sequence = 1; | ||
470 | pic->low_delay = 0; | ||
471 | |||
472 | pic->sequence_display_extension_flag = 0; | ||
473 | for ( i = 0 ; i < 4 ; i++ ){ | ||
474 | pic->frame_centre_horizontal_offset[i] = 0; | ||
475 | pic->frame_centre_vertical_offset[i] = 0; | ||
476 | } | ||
477 | pic->last_frame_centre_horizontal_offset = 0; | ||
478 | pic->last_frame_centre_vertical_offset = 0; | ||
479 | |||
480 | pic->picture_display_extension_flag[0] = 0; | ||
481 | pic->picture_display_extension_flag[1] = 0; | ||
482 | pic->sequence_header_flag = 0; | ||
483 | pic->gop_flag = 0; | ||
484 | pic->sequence_end_flag = 0; | ||
485 | } | ||
486 | #endif | ||
487 | |||
488 | #if 0 | ||
489 | static void mpg_set_picture_parameter( int32_t field_type, struct mpg_picture *pic ) | ||
490 | { | ||
491 | int16_t last_h_offset; | ||
492 | int16_t last_v_offset; | ||
493 | |||
494 | int16_t *p_h_offset; | ||
495 | int16_t *p_v_offset; | ||
496 | |||
497 | if ( pic->mpeg1_flag ){ | ||
498 | pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE; | ||
499 | pic->top_field_first = 0; | ||
500 | pic->repeat_first_field = 0; | ||
501 | pic->progressive_frame = 1; | ||
502 | pic->picture_coding_parameter = 0x000010; | ||
503 | } | ||
504 | |||
505 | /* Reset flag */ | ||
506 | pic->picture_display_extension_flag[field_type] = 0; | ||
507 | |||
508 | last_h_offset = pic->last_frame_centre_horizontal_offset; | ||
509 | last_v_offset = pic->last_frame_centre_vertical_offset; | ||
510 | if ( field_type == FIRST_FIELD ){ | ||
511 | p_h_offset = pic->frame_centre_horizontal_offset; | ||
512 | p_v_offset = pic->frame_centre_vertical_offset; | ||
513 | *p_h_offset = last_h_offset; | ||
514 | *(p_h_offset + 1) = last_h_offset; | ||
515 | *(p_h_offset + 2) = last_h_offset; | ||
516 | *p_v_offset = last_v_offset; | ||
517 | *(p_v_offset + 1) = last_v_offset; | ||
518 | *(p_v_offset + 2) = last_v_offset; | ||
519 | } else { | ||
520 | pic->frame_centre_horizontal_offset[3] = last_h_offset; | ||
521 | pic->frame_centre_vertical_offset[3] = last_v_offset; | ||
522 | } | ||
523 | } | ||
524 | #endif | ||
525 | |||
526 | #if 0 | ||
527 | static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_type) | ||
528 | { | ||
529 | pic->picture_header = 0; | ||
530 | pic->sequence_header_data | ||
531 | = ( INIT_HORIZONTAL_SIZE << 20 ) | ||
532 | | ( INIT_VERTICAL_SIZE << 8 ) | ||
533 | | ( INIT_ASPECT_RATIO << 4 ) | ||
534 | | ( INIT_FRAME_RATE ); | ||
535 | pic->mpeg1_flag = 0; | ||
536 | pic->vinfo.horizontal_size | ||
537 | = INIT_DISP_HORIZONTAL_SIZE; | ||
538 | pic->vinfo.vertical_size | ||
539 | = INIT_DISP_VERTICAL_SIZE; | ||
540 | pic->picture_display_extension_flag[field_type] | ||
541 | = 0; | ||
542 | pic->pts_flag[field_type] = 0; | ||
543 | |||
544 | pic->sequence_gop_header = 0; | ||
545 | pic->picture_header = 0; | ||
546 | pic->sequence_header_flag = 0; | ||
547 | pic->gop_flag = 0; | ||
548 | pic->sequence_end_flag = 0; | ||
549 | pic->sequence_display_extension_flag = 0; | ||
550 | pic->last_frame_centre_horizontal_offset = 0; | ||
551 | pic->last_frame_centre_vertical_offset = 0; | ||
552 | pic->channel = chan; | ||
553 | } | ||
554 | #endif | ||
555 | |||
556 | void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid, | ||
557 | dvb_filter_pes2ts_cb_t *cb, void *priv) | ||
558 | { | ||
559 | unsigned char *buf=p2ts->buf; | ||
560 | |||
561 | buf[0]=0x47; | ||
562 | buf[1]=(pid>>8); | ||
563 | buf[2]=pid&0xff; | ||
564 | p2ts->cc=0; | ||
565 | p2ts->cb=cb; | ||
566 | p2ts->priv=priv; | ||
567 | } | ||
568 | EXPORT_SYMBOL(dvb_filter_pes2ts_init); | ||
569 | |||
570 | int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes, | ||
571 | int len, int payload_start) | ||
572 | { | ||
573 | unsigned char *buf=p2ts->buf; | ||
574 | int ret=0, rest; | ||
575 | |||
576 | //len=6+((pes[4]<<8)|pes[5]); | ||
577 | |||
578 | if (payload_start) | ||
579 | buf[1]|=0x40; | ||
580 | else | ||
581 | buf[1]&=~0x40; | ||
582 | while (len>=184) { | ||
583 | buf[3]=0x10|((p2ts->cc++)&0x0f); | ||
584 | memcpy(buf+4, pes, 184); | ||
585 | if ((ret=p2ts->cb(p2ts->priv, buf))) | ||
586 | return ret; | ||
587 | len-=184; pes+=184; | ||
588 | buf[1]&=~0x40; | ||
589 | } | ||
590 | if (!len) | ||
591 | return 0; | ||
592 | buf[3]=0x30|((p2ts->cc++)&0x0f); | ||
593 | rest=183-len; | ||
594 | if (rest) { | ||
595 | buf[5]=0x00; | ||
596 | if (rest-1) | ||
597 | memset(buf+6, 0xff, rest-1); | ||
598 | } | ||
599 | buf[4]=rest; | ||
600 | memcpy(buf+5+rest, pes, len); | ||
601 | return p2ts->cb(p2ts->priv, buf); | ||
602 | } | ||
603 | EXPORT_SYMBOL(dvb_filter_pes2ts); | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_filter.h b/drivers/media/dvb/dvb-core/dvb_filter.h deleted file mode 100644 index 375e3be184b1..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_filter.h +++ /dev/null | |||
@@ -1,246 +0,0 @@ | |||
1 | /* | ||
2 | * dvb_filter.h | ||
3 | * | ||
4 | * Copyright (C) 2003 Convergence GmbH | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public License | ||
8 | * as published by the Free Software Foundation; either version 2.1 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef _DVB_FILTER_H_ | ||
22 | #define _DVB_FILTER_H_ | ||
23 | |||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #include "demux.h" | ||
27 | |||
28 | typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *); | ||
29 | |||
30 | struct dvb_filter_pes2ts { | ||
31 | unsigned char buf[188]; | ||
32 | unsigned char cc; | ||
33 | dvb_filter_pes2ts_cb_t *cb; | ||
34 | void *priv; | ||
35 | }; | ||
36 | |||
37 | void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid, | ||
38 | dvb_filter_pes2ts_cb_t *cb, void *priv); | ||
39 | |||
40 | int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes, | ||
41 | int len, int payload_start); | ||
42 | |||
43 | |||
44 | #define PROG_STREAM_MAP 0xBC | ||
45 | #define PRIVATE_STREAM1 0xBD | ||
46 | #define PADDING_STREAM 0xBE | ||
47 | #define PRIVATE_STREAM2 0xBF | ||
48 | #define AUDIO_STREAM_S 0xC0 | ||
49 | #define AUDIO_STREAM_E 0xDF | ||
50 | #define VIDEO_STREAM_S 0xE0 | ||
51 | #define VIDEO_STREAM_E 0xEF | ||
52 | #define ECM_STREAM 0xF0 | ||
53 | #define EMM_STREAM 0xF1 | ||
54 | #define DSM_CC_STREAM 0xF2 | ||
55 | #define ISO13522_STREAM 0xF3 | ||
56 | #define PROG_STREAM_DIR 0xFF | ||
57 | |||
58 | #define DVB_PICTURE_START 0x00 | ||
59 | #define DVB_USER_START 0xb2 | ||
60 | #define DVB_SEQUENCE_HEADER 0xb3 | ||
61 | #define DVB_SEQUENCE_ERROR 0xb4 | ||
62 | #define DVB_EXTENSION_START 0xb5 | ||
63 | #define DVB_SEQUENCE_END 0xb7 | ||
64 | #define DVB_GOP_START 0xb8 | ||
65 | #define DVB_EXCEPT_SLICE 0xb0 | ||
66 | |||
67 | #define SEQUENCE_EXTENSION 0x01 | ||
68 | #define SEQUENCE_DISPLAY_EXTENSION 0x02 | ||
69 | #define PICTURE_CODING_EXTENSION 0x08 | ||
70 | #define QUANT_MATRIX_EXTENSION 0x03 | ||
71 | #define PICTURE_DISPLAY_EXTENSION 0x07 | ||
72 | |||
73 | #define I_FRAME 0x01 | ||
74 | #define B_FRAME 0x02 | ||
75 | #define P_FRAME 0x03 | ||
76 | |||
77 | /* Initialize sequence_data */ | ||
78 | #define INIT_HORIZONTAL_SIZE 720 | ||
79 | #define INIT_VERTICAL_SIZE 576 | ||
80 | #define INIT_ASPECT_RATIO 0x02 | ||
81 | #define INIT_FRAME_RATE 0x03 | ||
82 | #define INIT_DISP_HORIZONTAL_SIZE 540 | ||
83 | #define INIT_DISP_VERTICAL_SIZE 576 | ||
84 | |||
85 | |||
86 | //flags2 | ||
87 | #define PTS_DTS_FLAGS 0xC0 | ||
88 | #define ESCR_FLAG 0x20 | ||
89 | #define ES_RATE_FLAG 0x10 | ||
90 | #define DSM_TRICK_FLAG 0x08 | ||
91 | #define ADD_CPY_FLAG 0x04 | ||
92 | #define PES_CRC_FLAG 0x02 | ||
93 | #define PES_EXT_FLAG 0x01 | ||
94 | |||
95 | //pts_dts flags | ||
96 | #define PTS_ONLY 0x80 | ||
97 | #define PTS_DTS 0xC0 | ||
98 | |||
99 | #define TS_SIZE 188 | ||
100 | #define TRANS_ERROR 0x80 | ||
101 | #define PAY_START 0x40 | ||
102 | #define TRANS_PRIO 0x20 | ||
103 | #define PID_MASK_HI 0x1F | ||
104 | //flags | ||
105 | #define TRANS_SCRMBL1 0x80 | ||
106 | #define TRANS_SCRMBL2 0x40 | ||
107 | #define ADAPT_FIELD 0x20 | ||
108 | #define PAYLOAD 0x10 | ||
109 | #define COUNT_MASK 0x0F | ||
110 | |||
111 | // adaptation flags | ||
112 | #define DISCON_IND 0x80 | ||
113 | #define RAND_ACC_IND 0x40 | ||
114 | #define ES_PRI_IND 0x20 | ||
115 | #define PCR_FLAG 0x10 | ||
116 | #define OPCR_FLAG 0x08 | ||
117 | #define SPLICE_FLAG 0x04 | ||
118 | #define TRANS_PRIV 0x02 | ||
119 | #define ADAP_EXT_FLAG 0x01 | ||
120 | |||
121 | // adaptation extension flags | ||
122 | #define LTW_FLAG 0x80 | ||
123 | #define PIECE_RATE 0x40 | ||
124 | #define SEAM_SPLICE 0x20 | ||
125 | |||
126 | |||
127 | #define MAX_PLENGTH 0xFFFF | ||
128 | #define MMAX_PLENGTH (256*MAX_PLENGTH) | ||
129 | |||
130 | #ifndef IPACKS | ||
131 | #define IPACKS 2048 | ||
132 | #endif | ||
133 | |||
134 | struct ipack { | ||
135 | int size; | ||
136 | int found; | ||
137 | u8 *buf; | ||
138 | u8 cid; | ||
139 | u32 plength; | ||
140 | u8 plen[2]; | ||
141 | u8 flag1; | ||
142 | u8 flag2; | ||
143 | u8 hlength; | ||
144 | u8 pts[5]; | ||
145 | u16 *pid; | ||
146 | int mpeg; | ||
147 | u8 check; | ||
148 | int which; | ||
149 | int done; | ||
150 | void *data; | ||
151 | void (*func)(u8 *buf, int size, void *priv); | ||
152 | int count; | ||
153 | int repack_subids; | ||
154 | }; | ||
155 | |||
156 | struct dvb_video_info { | ||
157 | u32 horizontal_size; | ||
158 | u32 vertical_size; | ||
159 | u32 aspect_ratio; | ||
160 | u32 framerate; | ||
161 | u32 video_format; | ||
162 | u32 bit_rate; | ||
163 | u32 comp_bit_rate; | ||
164 | u32 vbv_buffer_size; | ||
165 | s16 vbv_delay; | ||
166 | u32 CSPF; | ||
167 | u32 off; | ||
168 | }; | ||
169 | |||
170 | #define OFF_SIZE 4 | ||
171 | #define FIRST_FIELD 0 | ||
172 | #define SECOND_FIELD 1 | ||
173 | #define VIDEO_FRAME_PICTURE 0x03 | ||
174 | |||
175 | struct mpg_picture { | ||
176 | int channel; | ||
177 | struct dvb_video_info vinfo; | ||
178 | u32 *sequence_gop_header; | ||
179 | u32 *picture_header; | ||
180 | s32 time_code; | ||
181 | int low_delay; | ||
182 | int closed_gop; | ||
183 | int broken_link; | ||
184 | int sequence_header_flag; | ||
185 | int gop_flag; | ||
186 | int sequence_end_flag; | ||
187 | |||
188 | u8 profile_and_level; | ||
189 | s32 picture_coding_parameter; | ||
190 | u32 matrix[32]; | ||
191 | s8 matrix_change_flag; | ||
192 | |||
193 | u8 picture_header_parameter; | ||
194 | /* bit 0 - 2: bwd f code | ||
195 | bit 3 : fpb vector | ||
196 | bit 4 - 6: fwd f code | ||
197 | bit 7 : fpf vector */ | ||
198 | |||
199 | int mpeg1_flag; | ||
200 | int progressive_sequence; | ||
201 | int sequence_display_extension_flag; | ||
202 | u32 sequence_header_data; | ||
203 | s16 last_frame_centre_horizontal_offset; | ||
204 | s16 last_frame_centre_vertical_offset; | ||
205 | |||
206 | u32 pts[2]; /* [0] 1st field, [1] 2nd field */ | ||
207 | int top_field_first; | ||
208 | int repeat_first_field; | ||
209 | int progressive_frame; | ||
210 | int bank; | ||
211 | int forward_bank; | ||
212 | int backward_bank; | ||
213 | int compress; | ||
214 | s16 frame_centre_horizontal_offset[OFF_SIZE]; | ||
215 | /* [0-2] 1st field, [3] 2nd field */ | ||
216 | s16 frame_centre_vertical_offset[OFF_SIZE]; | ||
217 | /* [0-2] 1st field, [3] 2nd field */ | ||
218 | s16 temporal_reference[2]; | ||
219 | /* [0] 1st field, [1] 2nd field */ | ||
220 | |||
221 | s8 picture_coding_type[2]; | ||
222 | /* [0] 1st field, [1] 2nd field */ | ||
223 | s8 picture_structure[2]; | ||
224 | /* [0] 1st field, [1] 2nd field */ | ||
225 | s8 picture_display_extension_flag[2]; | ||
226 | /* [0] 1st field, [1] 2nd field */ | ||
227 | /* picture_display_extenion() 0:no 1:exit*/ | ||
228 | s8 pts_flag[2]; | ||
229 | /* [0] 1st field, [1] 2nd field */ | ||
230 | }; | ||
231 | |||
232 | struct dvb_audio_info { | ||
233 | int layer; | ||
234 | u32 bit_rate; | ||
235 | u32 frequency; | ||
236 | u32 mode; | ||
237 | u32 mode_extension ; | ||
238 | u32 emphasis; | ||
239 | u32 framesize; | ||
240 | u32 off; | ||
241 | }; | ||
242 | |||
243 | int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr); | ||
244 | |||
245 | |||
246 | #endif | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c deleted file mode 100644 index 12e5eb1fff76..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ /dev/null | |||
@@ -1,2553 +0,0 @@ | |||
1 | /* | ||
2 | * dvb_frontend.c: DVB frontend tuning interface/thread | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 1999-2001 Ralph Metzler | ||
6 | * Marcus Metzler | ||
7 | * Holger Waechtler | ||
8 | * for convergence integrated media GmbH | ||
9 | * | ||
10 | * Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup) | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
25 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
26 | */ | ||
27 | |||
28 | /* Enables DVBv3 compatibility bits at the headers */ | ||
29 | #define __DVB_CORE__ | ||
30 | |||
31 | #include <linux/string.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/wait.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/poll.h> | ||
37 | #include <linux/semaphore.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/list.h> | ||
40 | #include <linux/freezer.h> | ||
41 | #include <linux/jiffies.h> | ||
42 | #include <linux/kthread.h> | ||
43 | #include <asm/processor.h> | ||
44 | |||
45 | #include "dvb_frontend.h" | ||
46 | #include "dvbdev.h" | ||
47 | #include <linux/dvb/version.h> | ||
48 | |||
49 | static int dvb_frontend_debug; | ||
50 | static int dvb_shutdown_timeout; | ||
51 | static int dvb_force_auto_inversion; | ||
52 | static int dvb_override_tune_delay; | ||
53 | static int dvb_powerdown_on_sleep = 1; | ||
54 | static int dvb_mfe_wait_time = 5; | ||
55 | |||
56 | module_param_named(frontend_debug, dvb_frontend_debug, int, 0644); | ||
57 | MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off)."); | ||
58 | module_param(dvb_shutdown_timeout, int, 0644); | ||
59 | MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware"); | ||
60 | module_param(dvb_force_auto_inversion, int, 0644); | ||
61 | MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always"); | ||
62 | module_param(dvb_override_tune_delay, int, 0644); | ||
63 | MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); | ||
64 | module_param(dvb_powerdown_on_sleep, int, 0644); | ||
65 | MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)"); | ||
66 | module_param(dvb_mfe_wait_time, int, 0644); | ||
67 | MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)"); | ||
68 | |||
69 | #define dprintk if (dvb_frontend_debug) printk | ||
70 | |||
71 | #define FESTATE_IDLE 1 | ||
72 | #define FESTATE_RETUNE 2 | ||
73 | #define FESTATE_TUNING_FAST 4 | ||
74 | #define FESTATE_TUNING_SLOW 8 | ||
75 | #define FESTATE_TUNED 16 | ||
76 | #define FESTATE_ZIGZAG_FAST 32 | ||
77 | #define FESTATE_ZIGZAG_SLOW 64 | ||
78 | #define FESTATE_DISEQC 128 | ||
79 | #define FESTATE_ERROR 256 | ||
80 | #define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC) | ||
81 | #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST) | ||
82 | #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW) | ||
83 | #define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW) | ||
84 | |||
85 | #define FE_ALGO_HW 1 | ||
86 | /* | ||
87 | * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling. | ||
88 | * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune. | ||
89 | * FESTATE_TUNING_FAST. Tuning parameters have been supplied and fast zigzag scan is in progress. | ||
90 | * FESTATE_TUNING_SLOW. Tuning parameters have been supplied. Fast zigzag failed, so we're trying again, but slower. | ||
91 | * FESTATE_TUNED. The frontend has successfully locked on. | ||
92 | * FESTATE_ZIGZAG_FAST. The lock has been lost, and a fast zigzag has been initiated to try and regain it. | ||
93 | * FESTATE_ZIGZAG_SLOW. The lock has been lost. Fast zigzag has been failed, so we're trying again, but slower. | ||
94 | * FESTATE_DISEQC. A DISEQC command has just been issued. | ||
95 | * FESTATE_WAITFORLOCK. When we're waiting for a lock. | ||
96 | * FESTATE_SEARCHING_FAST. When we're searching for a signal using a fast zigzag scan. | ||
97 | * FESTATE_SEARCHING_SLOW. When we're searching for a signal using a slow zigzag scan. | ||
98 | * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. | ||
99 | */ | ||
100 | |||
101 | #define DVB_FE_NO_EXIT 0 | ||
102 | #define DVB_FE_NORMAL_EXIT 1 | ||
103 | #define DVB_FE_DEVICE_REMOVED 2 | ||
104 | |||
105 | static DEFINE_MUTEX(frontend_mutex); | ||
106 | |||
107 | struct dvb_frontend_private { | ||
108 | |||
109 | /* thread/frontend values */ | ||
110 | struct dvb_device *dvbdev; | ||
111 | struct dvb_frontend_parameters parameters_out; | ||
112 | struct dvb_fe_events events; | ||
113 | struct semaphore sem; | ||
114 | struct list_head list_head; | ||
115 | wait_queue_head_t wait_queue; | ||
116 | struct task_struct *thread; | ||
117 | unsigned long release_jiffies; | ||
118 | unsigned int exit; | ||
119 | unsigned int wakeup; | ||
120 | fe_status_t status; | ||
121 | unsigned long tune_mode_flags; | ||
122 | unsigned int delay; | ||
123 | unsigned int reinitialise; | ||
124 | int tone; | ||
125 | int voltage; | ||
126 | |||
127 | /* swzigzag values */ | ||
128 | unsigned int state; | ||
129 | unsigned int bending; | ||
130 | int lnb_drift; | ||
131 | unsigned int inversion; | ||
132 | unsigned int auto_step; | ||
133 | unsigned int auto_sub_step; | ||
134 | unsigned int started_auto_step; | ||
135 | unsigned int min_delay; | ||
136 | unsigned int max_drift; | ||
137 | unsigned int step_size; | ||
138 | int quality; | ||
139 | unsigned int check_wrapped; | ||
140 | enum dvbfe_search algo_status; | ||
141 | }; | ||
142 | |||
143 | static void dvb_frontend_wakeup(struct dvb_frontend *fe); | ||
144 | static int dtv_get_frontend(struct dvb_frontend *fe, | ||
145 | struct dvb_frontend_parameters *p_out); | ||
146 | static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, | ||
147 | struct dvb_frontend_parameters *p); | ||
148 | |||
149 | static bool has_get_frontend(struct dvb_frontend *fe) | ||
150 | { | ||
151 | return fe->ops.get_frontend != NULL; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Due to DVBv3 API calls, a delivery system should be mapped into one of | ||
156 | * the 4 DVBv3 delivery systems (FE_QPSK, FE_QAM, FE_OFDM or FE_ATSC), | ||
157 | * otherwise, a DVBv3 call will fail. | ||
158 | */ | ||
159 | enum dvbv3_emulation_type { | ||
160 | DVBV3_UNKNOWN, | ||
161 | DVBV3_QPSK, | ||
162 | DVBV3_QAM, | ||
163 | DVBV3_OFDM, | ||
164 | DVBV3_ATSC, | ||
165 | }; | ||
166 | |||
167 | static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system) | ||
168 | { | ||
169 | switch (delivery_system) { | ||
170 | case SYS_DVBC_ANNEX_A: | ||
171 | case SYS_DVBC_ANNEX_C: | ||
172 | return DVBV3_QAM; | ||
173 | case SYS_DVBS: | ||
174 | case SYS_DVBS2: | ||
175 | case SYS_TURBO: | ||
176 | case SYS_ISDBS: | ||
177 | case SYS_DSS: | ||
178 | return DVBV3_QPSK; | ||
179 | case SYS_DVBT: | ||
180 | case SYS_DVBT2: | ||
181 | case SYS_ISDBT: | ||
182 | case SYS_DTMB: | ||
183 | return DVBV3_OFDM; | ||
184 | case SYS_ATSC: | ||
185 | case SYS_ATSCMH: | ||
186 | case SYS_DVBC_ANNEX_B: | ||
187 | return DVBV3_ATSC; | ||
188 | case SYS_UNDEFINED: | ||
189 | case SYS_ISDBC: | ||
190 | case SYS_DVBH: | ||
191 | case SYS_DAB: | ||
192 | default: | ||
193 | /* | ||
194 | * Doesn't know how to emulate those types and/or | ||
195 | * there's no frontend driver from this type yet | ||
196 | * with some emulation code, so, we're not sure yet how | ||
197 | * to handle them, or they're not compatible with a DVBv3 call. | ||
198 | */ | ||
199 | return DVBV3_UNKNOWN; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) | ||
204 | { | ||
205 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
206 | struct dvb_fe_events *events = &fepriv->events; | ||
207 | struct dvb_frontend_event *e; | ||
208 | int wp; | ||
209 | |||
210 | dprintk ("%s\n", __func__); | ||
211 | |||
212 | if ((status & FE_HAS_LOCK) && has_get_frontend(fe)) | ||
213 | dtv_get_frontend(fe, &fepriv->parameters_out); | ||
214 | |||
215 | mutex_lock(&events->mtx); | ||
216 | |||
217 | wp = (events->eventw + 1) % MAX_EVENT; | ||
218 | if (wp == events->eventr) { | ||
219 | events->overflow = 1; | ||
220 | events->eventr = (events->eventr + 1) % MAX_EVENT; | ||
221 | } | ||
222 | |||
223 | e = &events->events[events->eventw]; | ||
224 | e->status = status; | ||
225 | e->parameters = fepriv->parameters_out; | ||
226 | |||
227 | events->eventw = wp; | ||
228 | |||
229 | mutex_unlock(&events->mtx); | ||
230 | |||
231 | wake_up_interruptible (&events->wait_queue); | ||
232 | } | ||
233 | |||
234 | static int dvb_frontend_get_event(struct dvb_frontend *fe, | ||
235 | struct dvb_frontend_event *event, int flags) | ||
236 | { | ||
237 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
238 | struct dvb_fe_events *events = &fepriv->events; | ||
239 | |||
240 | dprintk ("%s\n", __func__); | ||
241 | |||
242 | if (events->overflow) { | ||
243 | events->overflow = 0; | ||
244 | return -EOVERFLOW; | ||
245 | } | ||
246 | |||
247 | if (events->eventw == events->eventr) { | ||
248 | int ret; | ||
249 | |||
250 | if (flags & O_NONBLOCK) | ||
251 | return -EWOULDBLOCK; | ||
252 | |||
253 | up(&fepriv->sem); | ||
254 | |||
255 | ret = wait_event_interruptible (events->wait_queue, | ||
256 | events->eventw != events->eventr); | ||
257 | |||
258 | if (down_interruptible (&fepriv->sem)) | ||
259 | return -ERESTARTSYS; | ||
260 | |||
261 | if (ret < 0) | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | mutex_lock(&events->mtx); | ||
266 | *event = events->events[events->eventr]; | ||
267 | events->eventr = (events->eventr + 1) % MAX_EVENT; | ||
268 | mutex_unlock(&events->mtx); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static void dvb_frontend_clear_events(struct dvb_frontend *fe) | ||
274 | { | ||
275 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
276 | struct dvb_fe_events *events = &fepriv->events; | ||
277 | |||
278 | mutex_lock(&events->mtx); | ||
279 | events->eventr = events->eventw; | ||
280 | mutex_unlock(&events->mtx); | ||
281 | } | ||
282 | |||
283 | static void dvb_frontend_init(struct dvb_frontend *fe) | ||
284 | { | ||
285 | dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n", | ||
286 | fe->dvb->num, | ||
287 | fe->id, | ||
288 | fe->ops.info.name); | ||
289 | |||
290 | if (fe->ops.init) | ||
291 | fe->ops.init(fe); | ||
292 | if (fe->ops.tuner_ops.init) { | ||
293 | if (fe->ops.i2c_gate_ctrl) | ||
294 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
295 | fe->ops.tuner_ops.init(fe); | ||
296 | if (fe->ops.i2c_gate_ctrl) | ||
297 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | void dvb_frontend_reinitialise(struct dvb_frontend *fe) | ||
302 | { | ||
303 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
304 | |||
305 | fepriv->reinitialise = 1; | ||
306 | dvb_frontend_wakeup(fe); | ||
307 | } | ||
308 | EXPORT_SYMBOL(dvb_frontend_reinitialise); | ||
309 | |||
310 | static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked) | ||
311 | { | ||
312 | int q2; | ||
313 | |||
314 | dprintk ("%s\n", __func__); | ||
315 | |||
316 | if (locked) | ||
317 | (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256; | ||
318 | else | ||
319 | (fepriv->quality) = (fepriv->quality * 220 + 0) / 256; | ||
320 | |||
321 | q2 = fepriv->quality - 128; | ||
322 | q2 *= q2; | ||
323 | |||
324 | fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128); | ||
325 | } | ||
326 | |||
327 | /** | ||
328 | * Performs automatic twiddling of frontend parameters. | ||
329 | * | ||
330 | * @param fe The frontend concerned. | ||
331 | * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT | ||
332 | * @returns Number of complete iterations that have been performed. | ||
333 | */ | ||
334 | static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped) | ||
335 | { | ||
336 | int autoinversion; | ||
337 | int ready = 0; | ||
338 | int fe_set_err = 0; | ||
339 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
340 | struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp; | ||
341 | int original_inversion = c->inversion; | ||
342 | u32 original_frequency = c->frequency; | ||
343 | |||
344 | /* are we using autoinversion? */ | ||
345 | autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && | ||
346 | (c->inversion == INVERSION_AUTO)); | ||
347 | |||
348 | /* setup parameters correctly */ | ||
349 | while(!ready) { | ||
350 | /* calculate the lnb_drift */ | ||
351 | fepriv->lnb_drift = fepriv->auto_step * fepriv->step_size; | ||
352 | |||
353 | /* wrap the auto_step if we've exceeded the maximum drift */ | ||
354 | if (fepriv->lnb_drift > fepriv->max_drift) { | ||
355 | fepriv->auto_step = 0; | ||
356 | fepriv->auto_sub_step = 0; | ||
357 | fepriv->lnb_drift = 0; | ||
358 | } | ||
359 | |||
360 | /* perform inversion and +/- zigzag */ | ||
361 | switch(fepriv->auto_sub_step) { | ||
362 | case 0: | ||
363 | /* try with the current inversion and current drift setting */ | ||
364 | ready = 1; | ||
365 | break; | ||
366 | |||
367 | case 1: | ||
368 | if (!autoinversion) break; | ||
369 | |||
370 | fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF; | ||
371 | ready = 1; | ||
372 | break; | ||
373 | |||
374 | case 2: | ||
375 | if (fepriv->lnb_drift == 0) break; | ||
376 | |||
377 | fepriv->lnb_drift = -fepriv->lnb_drift; | ||
378 | ready = 1; | ||
379 | break; | ||
380 | |||
381 | case 3: | ||
382 | if (fepriv->lnb_drift == 0) break; | ||
383 | if (!autoinversion) break; | ||
384 | |||
385 | fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF; | ||
386 | fepriv->lnb_drift = -fepriv->lnb_drift; | ||
387 | ready = 1; | ||
388 | break; | ||
389 | |||
390 | default: | ||
391 | fepriv->auto_step++; | ||
392 | fepriv->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */ | ||
393 | break; | ||
394 | } | ||
395 | |||
396 | if (!ready) fepriv->auto_sub_step++; | ||
397 | } | ||
398 | |||
399 | /* if this attempt would hit where we started, indicate a complete | ||
400 | * iteration has occurred */ | ||
401 | if ((fepriv->auto_step == fepriv->started_auto_step) && | ||
402 | (fepriv->auto_sub_step == 0) && check_wrapped) { | ||
403 | return 1; | ||
404 | } | ||
405 | |||
406 | dprintk("%s: drift:%i inversion:%i auto_step:%i " | ||
407 | "auto_sub_step:%i started_auto_step:%i\n", | ||
408 | __func__, fepriv->lnb_drift, fepriv->inversion, | ||
409 | fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); | ||
410 | |||
411 | /* set the frontend itself */ | ||
412 | c->frequency += fepriv->lnb_drift; | ||
413 | if (autoinversion) | ||
414 | c->inversion = fepriv->inversion; | ||
415 | tmp = *c; | ||
416 | if (fe->ops.set_frontend) | ||
417 | fe_set_err = fe->ops.set_frontend(fe); | ||
418 | *c = tmp; | ||
419 | if (fe_set_err < 0) { | ||
420 | fepriv->state = FESTATE_ERROR; | ||
421 | return fe_set_err; | ||
422 | } | ||
423 | |||
424 | c->frequency = original_frequency; | ||
425 | c->inversion = original_inversion; | ||
426 | |||
427 | fepriv->auto_sub_step++; | ||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static void dvb_frontend_swzigzag(struct dvb_frontend *fe) | ||
432 | { | ||
433 | fe_status_t s = 0; | ||
434 | int retval = 0; | ||
435 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
436 | struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp; | ||
437 | |||
438 | /* if we've got no parameters, just keep idling */ | ||
439 | if (fepriv->state & FESTATE_IDLE) { | ||
440 | fepriv->delay = 3*HZ; | ||
441 | fepriv->quality = 0; | ||
442 | return; | ||
443 | } | ||
444 | |||
445 | /* in SCAN mode, we just set the frontend when asked and leave it alone */ | ||
446 | if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { | ||
447 | if (fepriv->state & FESTATE_RETUNE) { | ||
448 | tmp = *c; | ||
449 | if (fe->ops.set_frontend) | ||
450 | retval = fe->ops.set_frontend(fe); | ||
451 | *c = tmp; | ||
452 | if (retval < 0) | ||
453 | fepriv->state = FESTATE_ERROR; | ||
454 | else | ||
455 | fepriv->state = FESTATE_TUNED; | ||
456 | } | ||
457 | fepriv->delay = 3*HZ; | ||
458 | fepriv->quality = 0; | ||
459 | return; | ||
460 | } | ||
461 | |||
462 | /* get the frontend status */ | ||
463 | if (fepriv->state & FESTATE_RETUNE) { | ||
464 | s = 0; | ||
465 | } else { | ||
466 | if (fe->ops.read_status) | ||
467 | fe->ops.read_status(fe, &s); | ||
468 | if (s != fepriv->status) { | ||
469 | dvb_frontend_add_event(fe, s); | ||
470 | fepriv->status = s; | ||
471 | } | ||
472 | } | ||
473 | |||
474 | /* if we're not tuned, and we have a lock, move to the TUNED state */ | ||
475 | if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { | ||
476 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
477 | fepriv->state = FESTATE_TUNED; | ||
478 | |||
479 | /* if we're tuned, then we have determined the correct inversion */ | ||
480 | if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && | ||
481 | (c->inversion == INVERSION_AUTO)) { | ||
482 | c->inversion = fepriv->inversion; | ||
483 | } | ||
484 | return; | ||
485 | } | ||
486 | |||
487 | /* if we are tuned already, check we're still locked */ | ||
488 | if (fepriv->state & FESTATE_TUNED) { | ||
489 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
490 | |||
491 | /* we're tuned, and the lock is still good... */ | ||
492 | if (s & FE_HAS_LOCK) { | ||
493 | return; | ||
494 | } else { /* if we _WERE_ tuned, but now don't have a lock */ | ||
495 | fepriv->state = FESTATE_ZIGZAG_FAST; | ||
496 | fepriv->started_auto_step = fepriv->auto_step; | ||
497 | fepriv->check_wrapped = 0; | ||
498 | } | ||
499 | } | ||
500 | |||
501 | /* don't actually do anything if we're in the LOSTLOCK state, | ||
502 | * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ | ||
503 | if ((fepriv->state & FESTATE_LOSTLOCK) && | ||
504 | (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { | ||
505 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | /* don't do anything if we're in the DISEQC state, since this | ||
510 | * might be someone with a motorized dish controlled by DISEQC. | ||
511 | * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */ | ||
512 | if (fepriv->state & FESTATE_DISEQC) { | ||
513 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
514 | return; | ||
515 | } | ||
516 | |||
517 | /* if we're in the RETUNE state, set everything up for a brand | ||
518 | * new scan, keeping the current inversion setting, as the next | ||
519 | * tune is _very_ likely to require the same */ | ||
520 | if (fepriv->state & FESTATE_RETUNE) { | ||
521 | fepriv->lnb_drift = 0; | ||
522 | fepriv->auto_step = 0; | ||
523 | fepriv->auto_sub_step = 0; | ||
524 | fepriv->started_auto_step = 0; | ||
525 | fepriv->check_wrapped = 0; | ||
526 | } | ||
527 | |||
528 | /* fast zigzag. */ | ||
529 | if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) { | ||
530 | fepriv->delay = fepriv->min_delay; | ||
531 | |||
532 | /* perform a tune */ | ||
533 | retval = dvb_frontend_swzigzag_autotune(fe, | ||
534 | fepriv->check_wrapped); | ||
535 | if (retval < 0) { | ||
536 | return; | ||
537 | } else if (retval) { | ||
538 | /* OK, if we've run out of trials at the fast speed. | ||
539 | * Drop back to slow for the _next_ attempt */ | ||
540 | fepriv->state = FESTATE_SEARCHING_SLOW; | ||
541 | fepriv->started_auto_step = fepriv->auto_step; | ||
542 | return; | ||
543 | } | ||
544 | fepriv->check_wrapped = 1; | ||
545 | |||
546 | /* if we've just retuned, enter the ZIGZAG_FAST state. | ||
547 | * This ensures we cannot return from an | ||
548 | * FE_SET_FRONTEND ioctl before the first frontend tune | ||
549 | * occurs */ | ||
550 | if (fepriv->state & FESTATE_RETUNE) { | ||
551 | fepriv->state = FESTATE_TUNING_FAST; | ||
552 | } | ||
553 | } | ||
554 | |||
555 | /* slow zigzag */ | ||
556 | if (fepriv->state & FESTATE_SEARCHING_SLOW) { | ||
557 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
558 | |||
559 | /* Note: don't bother checking for wrapping; we stay in this | ||
560 | * state until we get a lock */ | ||
561 | dvb_frontend_swzigzag_autotune(fe, 0); | ||
562 | } | ||
563 | } | ||
564 | |||
565 | static int dvb_frontend_is_exiting(struct dvb_frontend *fe) | ||
566 | { | ||
567 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
568 | |||
569 | if (fepriv->exit != DVB_FE_NO_EXIT) | ||
570 | return 1; | ||
571 | |||
572 | if (fepriv->dvbdev->writers == 1) | ||
573 | if (time_after_eq(jiffies, fepriv->release_jiffies + | ||
574 | dvb_shutdown_timeout * HZ)) | ||
575 | return 1; | ||
576 | |||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | static int dvb_frontend_should_wakeup(struct dvb_frontend *fe) | ||
581 | { | ||
582 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
583 | |||
584 | if (fepriv->wakeup) { | ||
585 | fepriv->wakeup = 0; | ||
586 | return 1; | ||
587 | } | ||
588 | return dvb_frontend_is_exiting(fe); | ||
589 | } | ||
590 | |||
591 | static void dvb_frontend_wakeup(struct dvb_frontend *fe) | ||
592 | { | ||
593 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
594 | |||
595 | fepriv->wakeup = 1; | ||
596 | wake_up_interruptible(&fepriv->wait_queue); | ||
597 | } | ||
598 | |||
599 | static int dvb_frontend_thread(void *data) | ||
600 | { | ||
601 | struct dvb_frontend *fe = data; | ||
602 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
603 | fe_status_t s; | ||
604 | enum dvbfe_algo algo; | ||
605 | |||
606 | bool re_tune = false; | ||
607 | |||
608 | dprintk("%s\n", __func__); | ||
609 | |||
610 | fepriv->check_wrapped = 0; | ||
611 | fepriv->quality = 0; | ||
612 | fepriv->delay = 3*HZ; | ||
613 | fepriv->status = 0; | ||
614 | fepriv->wakeup = 0; | ||
615 | fepriv->reinitialise = 0; | ||
616 | |||
617 | dvb_frontend_init(fe); | ||
618 | |||
619 | set_freezable(); | ||
620 | while (1) { | ||
621 | up(&fepriv->sem); /* is locked when we enter the thread... */ | ||
622 | restart: | ||
623 | wait_event_interruptible_timeout(fepriv->wait_queue, | ||
624 | dvb_frontend_should_wakeup(fe) || kthread_should_stop() | ||
625 | || freezing(current), | ||
626 | fepriv->delay); | ||
627 | |||
628 | if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { | ||
629 | /* got signal or quitting */ | ||
630 | fepriv->exit = DVB_FE_NORMAL_EXIT; | ||
631 | break; | ||
632 | } | ||
633 | |||
634 | if (try_to_freeze()) | ||
635 | goto restart; | ||
636 | |||
637 | if (down_interruptible(&fepriv->sem)) | ||
638 | break; | ||
639 | |||
640 | if (fepriv->reinitialise) { | ||
641 | dvb_frontend_init(fe); | ||
642 | if (fe->ops.set_tone && fepriv->tone != -1) | ||
643 | fe->ops.set_tone(fe, fepriv->tone); | ||
644 | if (fe->ops.set_voltage && fepriv->voltage != -1) | ||
645 | fe->ops.set_voltage(fe, fepriv->voltage); | ||
646 | fepriv->reinitialise = 0; | ||
647 | } | ||
648 | |||
649 | /* do an iteration of the tuning loop */ | ||
650 | if (fe->ops.get_frontend_algo) { | ||
651 | algo = fe->ops.get_frontend_algo(fe); | ||
652 | switch (algo) { | ||
653 | case DVBFE_ALGO_HW: | ||
654 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__); | ||
655 | |||
656 | if (fepriv->state & FESTATE_RETUNE) { | ||
657 | dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); | ||
658 | re_tune = true; | ||
659 | fepriv->state = FESTATE_TUNED; | ||
660 | } else { | ||
661 | re_tune = false; | ||
662 | } | ||
663 | |||
664 | if (fe->ops.tune) | ||
665 | fe->ops.tune(fe, re_tune, fepriv->tune_mode_flags, &fepriv->delay, &s); | ||
666 | |||
667 | if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { | ||
668 | dprintk("%s: state changed, adding current state\n", __func__); | ||
669 | dvb_frontend_add_event(fe, s); | ||
670 | fepriv->status = s; | ||
671 | } | ||
672 | break; | ||
673 | case DVBFE_ALGO_SW: | ||
674 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__); | ||
675 | dvb_frontend_swzigzag(fe); | ||
676 | break; | ||
677 | case DVBFE_ALGO_CUSTOM: | ||
678 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state); | ||
679 | if (fepriv->state & FESTATE_RETUNE) { | ||
680 | dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__); | ||
681 | fepriv->state = FESTATE_TUNED; | ||
682 | } | ||
683 | /* Case where we are going to search for a carrier | ||
684 | * User asked us to retune again for some reason, possibly | ||
685 | * requesting a search with a new set of parameters | ||
686 | */ | ||
687 | if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) { | ||
688 | if (fe->ops.search) { | ||
689 | fepriv->algo_status = fe->ops.search(fe); | ||
690 | /* We did do a search as was requested, the flags are | ||
691 | * now unset as well and has the flags wrt to search. | ||
692 | */ | ||
693 | } else { | ||
694 | fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN; | ||
695 | } | ||
696 | } | ||
697 | /* Track the carrier if the search was successful */ | ||
698 | if (fepriv->algo_status != DVBFE_ALGO_SEARCH_SUCCESS) { | ||
699 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | ||
700 | fepriv->delay = HZ / 2; | ||
701 | } | ||
702 | dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); | ||
703 | fe->ops.read_status(fe, &s); | ||
704 | if (s != fepriv->status) { | ||
705 | dvb_frontend_add_event(fe, s); /* update event list */ | ||
706 | fepriv->status = s; | ||
707 | if (!(s & FE_HAS_LOCK)) { | ||
708 | fepriv->delay = HZ / 10; | ||
709 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | ||
710 | } else { | ||
711 | fepriv->delay = 60 * HZ; | ||
712 | } | ||
713 | } | ||
714 | break; | ||
715 | default: | ||
716 | dprintk("%s: UNDEFINED ALGO !\n", __func__); | ||
717 | break; | ||
718 | } | ||
719 | } else { | ||
720 | dvb_frontend_swzigzag(fe); | ||
721 | } | ||
722 | } | ||
723 | |||
724 | if (dvb_powerdown_on_sleep) { | ||
725 | if (fe->ops.set_voltage) | ||
726 | fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); | ||
727 | if (fe->ops.tuner_ops.sleep) { | ||
728 | if (fe->ops.i2c_gate_ctrl) | ||
729 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
730 | fe->ops.tuner_ops.sleep(fe); | ||
731 | if (fe->ops.i2c_gate_ctrl) | ||
732 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
733 | } | ||
734 | if (fe->ops.sleep) | ||
735 | fe->ops.sleep(fe); | ||
736 | } | ||
737 | |||
738 | fepriv->thread = NULL; | ||
739 | if (kthread_should_stop()) | ||
740 | fepriv->exit = DVB_FE_DEVICE_REMOVED; | ||
741 | else | ||
742 | fepriv->exit = DVB_FE_NO_EXIT; | ||
743 | mb(); | ||
744 | |||
745 | dvb_frontend_wakeup(fe); | ||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | static void dvb_frontend_stop(struct dvb_frontend *fe) | ||
750 | { | ||
751 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
752 | |||
753 | dprintk ("%s\n", __func__); | ||
754 | |||
755 | fepriv->exit = DVB_FE_NORMAL_EXIT; | ||
756 | mb(); | ||
757 | |||
758 | if (!fepriv->thread) | ||
759 | return; | ||
760 | |||
761 | kthread_stop(fepriv->thread); | ||
762 | |||
763 | sema_init(&fepriv->sem, 1); | ||
764 | fepriv->state = FESTATE_IDLE; | ||
765 | |||
766 | /* paranoia check in case a signal arrived */ | ||
767 | if (fepriv->thread) | ||
768 | printk("dvb_frontend_stop: warning: thread %p won't exit\n", | ||
769 | fepriv->thread); | ||
770 | } | ||
771 | |||
772 | s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime) | ||
773 | { | ||
774 | return ((curtime.tv_usec < lasttime.tv_usec) ? | ||
775 | 1000000 - lasttime.tv_usec + curtime.tv_usec : | ||
776 | curtime.tv_usec - lasttime.tv_usec); | ||
777 | } | ||
778 | EXPORT_SYMBOL(timeval_usec_diff); | ||
779 | |||
780 | static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec) | ||
781 | { | ||
782 | curtime->tv_usec += add_usec; | ||
783 | if (curtime->tv_usec >= 1000000) { | ||
784 | curtime->tv_usec -= 1000000; | ||
785 | curtime->tv_sec++; | ||
786 | } | ||
787 | } | ||
788 | |||
789 | /* | ||
790 | * Sleep until gettimeofday() > waketime + add_usec | ||
791 | * This needs to be as precise as possible, but as the delay is | ||
792 | * usually between 2ms and 32ms, it is done using a scheduled msleep | ||
793 | * followed by usleep (normally a busy-wait loop) for the remainder | ||
794 | */ | ||
795 | void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec) | ||
796 | { | ||
797 | struct timeval lasttime; | ||
798 | s32 delta, newdelta; | ||
799 | |||
800 | timeval_usec_add(waketime, add_usec); | ||
801 | |||
802 | do_gettimeofday(&lasttime); | ||
803 | delta = timeval_usec_diff(lasttime, *waketime); | ||
804 | if (delta > 2500) { | ||
805 | msleep((delta - 1500) / 1000); | ||
806 | do_gettimeofday(&lasttime); | ||
807 | newdelta = timeval_usec_diff(lasttime, *waketime); | ||
808 | delta = (newdelta > delta) ? 0 : newdelta; | ||
809 | } | ||
810 | if (delta > 0) | ||
811 | udelay(delta); | ||
812 | } | ||
813 | EXPORT_SYMBOL(dvb_frontend_sleep_until); | ||
814 | |||
815 | static int dvb_frontend_start(struct dvb_frontend *fe) | ||
816 | { | ||
817 | int ret; | ||
818 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
819 | struct task_struct *fe_thread; | ||
820 | |||
821 | dprintk ("%s\n", __func__); | ||
822 | |||
823 | if (fepriv->thread) { | ||
824 | if (fepriv->exit == DVB_FE_NO_EXIT) | ||
825 | return 0; | ||
826 | else | ||
827 | dvb_frontend_stop (fe); | ||
828 | } | ||
829 | |||
830 | if (signal_pending(current)) | ||
831 | return -EINTR; | ||
832 | if (down_interruptible (&fepriv->sem)) | ||
833 | return -EINTR; | ||
834 | |||
835 | fepriv->state = FESTATE_IDLE; | ||
836 | fepriv->exit = DVB_FE_NO_EXIT; | ||
837 | fepriv->thread = NULL; | ||
838 | mb(); | ||
839 | |||
840 | fe_thread = kthread_run(dvb_frontend_thread, fe, | ||
841 | "kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id); | ||
842 | if (IS_ERR(fe_thread)) { | ||
843 | ret = PTR_ERR(fe_thread); | ||
844 | printk("dvb_frontend_start: failed to start kthread (%d)\n", ret); | ||
845 | up(&fepriv->sem); | ||
846 | return ret; | ||
847 | } | ||
848 | fepriv->thread = fe_thread; | ||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe, | ||
853 | u32 *freq_min, u32 *freq_max) | ||
854 | { | ||
855 | *freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min); | ||
856 | |||
857 | if (fe->ops.info.frequency_max == 0) | ||
858 | *freq_max = fe->ops.tuner_ops.info.frequency_max; | ||
859 | else if (fe->ops.tuner_ops.info.frequency_max == 0) | ||
860 | *freq_max = fe->ops.info.frequency_max; | ||
861 | else | ||
862 | *freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max); | ||
863 | |||
864 | if (*freq_min == 0 || *freq_max == 0) | ||
865 | printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", | ||
866 | fe->dvb->num,fe->id); | ||
867 | } | ||
868 | |||
869 | static int dvb_frontend_check_parameters(struct dvb_frontend *fe) | ||
870 | { | ||
871 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
872 | u32 freq_min; | ||
873 | u32 freq_max; | ||
874 | |||
875 | /* range check: frequency */ | ||
876 | dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max); | ||
877 | if ((freq_min && c->frequency < freq_min) || | ||
878 | (freq_max && c->frequency > freq_max)) { | ||
879 | printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", | ||
880 | fe->dvb->num, fe->id, c->frequency, freq_min, freq_max); | ||
881 | return -EINVAL; | ||
882 | } | ||
883 | |||
884 | /* range check: symbol rate */ | ||
885 | switch (c->delivery_system) { | ||
886 | case SYS_DVBS: | ||
887 | case SYS_DVBS2: | ||
888 | case SYS_TURBO: | ||
889 | case SYS_DVBC_ANNEX_A: | ||
890 | case SYS_DVBC_ANNEX_C: | ||
891 | if ((fe->ops.info.symbol_rate_min && | ||
892 | c->symbol_rate < fe->ops.info.symbol_rate_min) || | ||
893 | (fe->ops.info.symbol_rate_max && | ||
894 | c->symbol_rate > fe->ops.info.symbol_rate_max)) { | ||
895 | printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", | ||
896 | fe->dvb->num, fe->id, c->symbol_rate, | ||
897 | fe->ops.info.symbol_rate_min, | ||
898 | fe->ops.info.symbol_rate_max); | ||
899 | return -EINVAL; | ||
900 | } | ||
901 | default: | ||
902 | break; | ||
903 | } | ||
904 | |||
905 | return 0; | ||
906 | } | ||
907 | |||
908 | static int dvb_frontend_clear_cache(struct dvb_frontend *fe) | ||
909 | { | ||
910 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
911 | int i; | ||
912 | u32 delsys; | ||
913 | |||
914 | delsys = c->delivery_system; | ||
915 | memset(c, 0, sizeof(struct dtv_frontend_properties)); | ||
916 | c->delivery_system = delsys; | ||
917 | |||
918 | c->state = DTV_CLEAR; | ||
919 | |||
920 | dprintk("%s() Clearing cache for delivery system %d\n", __func__, | ||
921 | c->delivery_system); | ||
922 | |||
923 | c->transmission_mode = TRANSMISSION_MODE_AUTO; | ||
924 | c->bandwidth_hz = 0; /* AUTO */ | ||
925 | c->guard_interval = GUARD_INTERVAL_AUTO; | ||
926 | c->hierarchy = HIERARCHY_AUTO; | ||
927 | c->symbol_rate = 0; | ||
928 | c->code_rate_HP = FEC_AUTO; | ||
929 | c->code_rate_LP = FEC_AUTO; | ||
930 | c->fec_inner = FEC_AUTO; | ||
931 | c->rolloff = ROLLOFF_AUTO; | ||
932 | c->voltage = SEC_VOLTAGE_OFF; | ||
933 | c->sectone = SEC_TONE_OFF; | ||
934 | c->pilot = PILOT_AUTO; | ||
935 | |||
936 | c->isdbt_partial_reception = 0; | ||
937 | c->isdbt_sb_mode = 0; | ||
938 | c->isdbt_sb_subchannel = 0; | ||
939 | c->isdbt_sb_segment_idx = 0; | ||
940 | c->isdbt_sb_segment_count = 0; | ||
941 | c->isdbt_layer_enabled = 0; | ||
942 | for (i = 0; i < 3; i++) { | ||
943 | c->layer[i].fec = FEC_AUTO; | ||
944 | c->layer[i].modulation = QAM_AUTO; | ||
945 | c->layer[i].interleaving = 0; | ||
946 | c->layer[i].segment_count = 0; | ||
947 | } | ||
948 | |||
949 | c->isdbs_ts_id = 0; | ||
950 | c->dvbt2_plp_id = 0; | ||
951 | |||
952 | switch (c->delivery_system) { | ||
953 | case SYS_DVBS: | ||
954 | case SYS_DVBS2: | ||
955 | case SYS_TURBO: | ||
956 | c->modulation = QPSK; /* implied for DVB-S in legacy API */ | ||
957 | c->rolloff = ROLLOFF_35;/* implied for DVB-S */ | ||
958 | break; | ||
959 | case SYS_ATSC: | ||
960 | c->modulation = VSB_8; | ||
961 | break; | ||
962 | default: | ||
963 | c->modulation = QAM_AUTO; | ||
964 | break; | ||
965 | } | ||
966 | |||
967 | return 0; | ||
968 | } | ||
969 | |||
970 | #define _DTV_CMD(n, s, b) \ | ||
971 | [n] = { \ | ||
972 | .name = #n, \ | ||
973 | .cmd = n, \ | ||
974 | .set = s,\ | ||
975 | .buffer = b \ | ||
976 | } | ||
977 | |||
978 | static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { | ||
979 | _DTV_CMD(DTV_TUNE, 1, 0), | ||
980 | _DTV_CMD(DTV_CLEAR, 1, 0), | ||
981 | |||
982 | /* Set */ | ||
983 | _DTV_CMD(DTV_FREQUENCY, 1, 0), | ||
984 | _DTV_CMD(DTV_BANDWIDTH_HZ, 1, 0), | ||
985 | _DTV_CMD(DTV_MODULATION, 1, 0), | ||
986 | _DTV_CMD(DTV_INVERSION, 1, 0), | ||
987 | _DTV_CMD(DTV_DISEQC_MASTER, 1, 1), | ||
988 | _DTV_CMD(DTV_SYMBOL_RATE, 1, 0), | ||
989 | _DTV_CMD(DTV_INNER_FEC, 1, 0), | ||
990 | _DTV_CMD(DTV_VOLTAGE, 1, 0), | ||
991 | _DTV_CMD(DTV_TONE, 1, 0), | ||
992 | _DTV_CMD(DTV_PILOT, 1, 0), | ||
993 | _DTV_CMD(DTV_ROLLOFF, 1, 0), | ||
994 | _DTV_CMD(DTV_DELIVERY_SYSTEM, 1, 0), | ||
995 | _DTV_CMD(DTV_HIERARCHY, 1, 0), | ||
996 | _DTV_CMD(DTV_CODE_RATE_HP, 1, 0), | ||
997 | _DTV_CMD(DTV_CODE_RATE_LP, 1, 0), | ||
998 | _DTV_CMD(DTV_GUARD_INTERVAL, 1, 0), | ||
999 | _DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0), | ||
1000 | _DTV_CMD(DTV_INTERLEAVING, 1, 0), | ||
1001 | |||
1002 | _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0), | ||
1003 | _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0), | ||
1004 | _DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 1, 0), | ||
1005 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 1, 0), | ||
1006 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 1, 0), | ||
1007 | _DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 1, 0), | ||
1008 | _DTV_CMD(DTV_ISDBT_LAYERA_FEC, 1, 0), | ||
1009 | _DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 1, 0), | ||
1010 | _DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 1, 0), | ||
1011 | _DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 1, 0), | ||
1012 | _DTV_CMD(DTV_ISDBT_LAYERB_FEC, 1, 0), | ||
1013 | _DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 1, 0), | ||
1014 | _DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 1, 0), | ||
1015 | _DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 1, 0), | ||
1016 | _DTV_CMD(DTV_ISDBT_LAYERC_FEC, 1, 0), | ||
1017 | _DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 1, 0), | ||
1018 | _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0), | ||
1019 | _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0), | ||
1020 | |||
1021 | _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0), | ||
1022 | _DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0), | ||
1023 | |||
1024 | /* Get */ | ||
1025 | _DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1), | ||
1026 | _DTV_CMD(DTV_API_VERSION, 0, 0), | ||
1027 | _DTV_CMD(DTV_CODE_RATE_HP, 0, 0), | ||
1028 | _DTV_CMD(DTV_CODE_RATE_LP, 0, 0), | ||
1029 | _DTV_CMD(DTV_GUARD_INTERVAL, 0, 0), | ||
1030 | _DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0), | ||
1031 | _DTV_CMD(DTV_HIERARCHY, 0, 0), | ||
1032 | _DTV_CMD(DTV_INTERLEAVING, 0, 0), | ||
1033 | |||
1034 | _DTV_CMD(DTV_ENUM_DELSYS, 0, 0), | ||
1035 | |||
1036 | _DTV_CMD(DTV_ATSCMH_PARADE_ID, 1, 0), | ||
1037 | _DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 1, 0), | ||
1038 | |||
1039 | _DTV_CMD(DTV_ATSCMH_FIC_VER, 0, 0), | ||
1040 | _DTV_CMD(DTV_ATSCMH_PARADE_ID, 0, 0), | ||
1041 | _DTV_CMD(DTV_ATSCMH_NOG, 0, 0), | ||
1042 | _DTV_CMD(DTV_ATSCMH_TNOG, 0, 0), | ||
1043 | _DTV_CMD(DTV_ATSCMH_SGN, 0, 0), | ||
1044 | _DTV_CMD(DTV_ATSCMH_PRC, 0, 0), | ||
1045 | _DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE, 0, 0), | ||
1046 | _DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 0, 0), | ||
1047 | _DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI, 0, 0), | ||
1048 | _DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC, 0, 0), | ||
1049 | _DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE, 0, 0), | ||
1050 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_A, 0, 0), | ||
1051 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0), | ||
1052 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0), | ||
1053 | _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0), | ||
1054 | }; | ||
1055 | |||
1056 | static void dtv_property_dump(struct dtv_property *tvp) | ||
1057 | { | ||
1058 | int i; | ||
1059 | |||
1060 | if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { | ||
1061 | printk(KERN_WARNING "%s: tvp.cmd = 0x%08x undefined\n", | ||
1062 | __func__, tvp->cmd); | ||
1063 | return; | ||
1064 | } | ||
1065 | |||
1066 | dprintk("%s() tvp.cmd = 0x%08x (%s)\n" | ||
1067 | ,__func__ | ||
1068 | ,tvp->cmd | ||
1069 | ,dtv_cmds[ tvp->cmd ].name); | ||
1070 | |||
1071 | if(dtv_cmds[ tvp->cmd ].buffer) { | ||
1072 | |||
1073 | dprintk("%s() tvp.u.buffer.len = 0x%02x\n" | ||
1074 | ,__func__ | ||
1075 | ,tvp->u.buffer.len); | ||
1076 | |||
1077 | for(i = 0; i < tvp->u.buffer.len; i++) | ||
1078 | dprintk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n" | ||
1079 | ,__func__ | ||
1080 | ,i | ||
1081 | ,tvp->u.buffer.data[i]); | ||
1082 | |||
1083 | } else | ||
1084 | dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data); | ||
1085 | } | ||
1086 | |||
1087 | /* Synchronise the legacy tuning parameters into the cache, so that demodulator | ||
1088 | * drivers can use a single set_frontend tuning function, regardless of whether | ||
1089 | * it's being used for the legacy or new API, reducing code and complexity. | ||
1090 | */ | ||
1091 | static int dtv_property_cache_sync(struct dvb_frontend *fe, | ||
1092 | struct dtv_frontend_properties *c, | ||
1093 | const struct dvb_frontend_parameters *p) | ||
1094 | { | ||
1095 | c->frequency = p->frequency; | ||
1096 | c->inversion = p->inversion; | ||
1097 | |||
1098 | switch (dvbv3_type(c->delivery_system)) { | ||
1099 | case DVBV3_QPSK: | ||
1100 | dprintk("%s() Preparing QPSK req\n", __func__); | ||
1101 | c->symbol_rate = p->u.qpsk.symbol_rate; | ||
1102 | c->fec_inner = p->u.qpsk.fec_inner; | ||
1103 | break; | ||
1104 | case DVBV3_QAM: | ||
1105 | dprintk("%s() Preparing QAM req\n", __func__); | ||
1106 | c->symbol_rate = p->u.qam.symbol_rate; | ||
1107 | c->fec_inner = p->u.qam.fec_inner; | ||
1108 | c->modulation = p->u.qam.modulation; | ||
1109 | break; | ||
1110 | case DVBV3_OFDM: | ||
1111 | dprintk("%s() Preparing OFDM req\n", __func__); | ||
1112 | switch (p->u.ofdm.bandwidth) { | ||
1113 | case BANDWIDTH_10_MHZ: | ||
1114 | c->bandwidth_hz = 10000000; | ||
1115 | break; | ||
1116 | case BANDWIDTH_8_MHZ: | ||
1117 | c->bandwidth_hz = 8000000; | ||
1118 | break; | ||
1119 | case BANDWIDTH_7_MHZ: | ||
1120 | c->bandwidth_hz = 7000000; | ||
1121 | break; | ||
1122 | case BANDWIDTH_6_MHZ: | ||
1123 | c->bandwidth_hz = 6000000; | ||
1124 | break; | ||
1125 | case BANDWIDTH_5_MHZ: | ||
1126 | c->bandwidth_hz = 5000000; | ||
1127 | break; | ||
1128 | case BANDWIDTH_1_712_MHZ: | ||
1129 | c->bandwidth_hz = 1712000; | ||
1130 | break; | ||
1131 | case BANDWIDTH_AUTO: | ||
1132 | c->bandwidth_hz = 0; | ||
1133 | } | ||
1134 | |||
1135 | c->code_rate_HP = p->u.ofdm.code_rate_HP; | ||
1136 | c->code_rate_LP = p->u.ofdm.code_rate_LP; | ||
1137 | c->modulation = p->u.ofdm.constellation; | ||
1138 | c->transmission_mode = p->u.ofdm.transmission_mode; | ||
1139 | c->guard_interval = p->u.ofdm.guard_interval; | ||
1140 | c->hierarchy = p->u.ofdm.hierarchy_information; | ||
1141 | break; | ||
1142 | case DVBV3_ATSC: | ||
1143 | dprintk("%s() Preparing ATSC req\n", __func__); | ||
1144 | c->modulation = p->u.vsb.modulation; | ||
1145 | if (c->delivery_system == SYS_ATSCMH) | ||
1146 | break; | ||
1147 | if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) | ||
1148 | c->delivery_system = SYS_ATSC; | ||
1149 | else | ||
1150 | c->delivery_system = SYS_DVBC_ANNEX_B; | ||
1151 | break; | ||
1152 | case DVBV3_UNKNOWN: | ||
1153 | printk(KERN_ERR | ||
1154 | "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", | ||
1155 | __func__, c->delivery_system); | ||
1156 | return -EINVAL; | ||
1157 | } | ||
1158 | |||
1159 | return 0; | ||
1160 | } | ||
1161 | |||
1162 | /* Ensure the cached values are set correctly in the frontend | ||
1163 | * legacy tuning structures, for the advanced tuning API. | ||
1164 | */ | ||
1165 | static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, | ||
1166 | struct dvb_frontend_parameters *p) | ||
1167 | { | ||
1168 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1169 | |||
1170 | p->frequency = c->frequency; | ||
1171 | p->inversion = c->inversion; | ||
1172 | |||
1173 | switch (dvbv3_type(c->delivery_system)) { | ||
1174 | case DVBV3_UNKNOWN: | ||
1175 | printk(KERN_ERR | ||
1176 | "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", | ||
1177 | __func__, c->delivery_system); | ||
1178 | return -EINVAL; | ||
1179 | case DVBV3_QPSK: | ||
1180 | dprintk("%s() Preparing QPSK req\n", __func__); | ||
1181 | p->u.qpsk.symbol_rate = c->symbol_rate; | ||
1182 | p->u.qpsk.fec_inner = c->fec_inner; | ||
1183 | break; | ||
1184 | case DVBV3_QAM: | ||
1185 | dprintk("%s() Preparing QAM req\n", __func__); | ||
1186 | p->u.qam.symbol_rate = c->symbol_rate; | ||
1187 | p->u.qam.fec_inner = c->fec_inner; | ||
1188 | p->u.qam.modulation = c->modulation; | ||
1189 | break; | ||
1190 | case DVBV3_OFDM: | ||
1191 | dprintk("%s() Preparing OFDM req\n", __func__); | ||
1192 | |||
1193 | switch (c->bandwidth_hz) { | ||
1194 | case 10000000: | ||
1195 | p->u.ofdm.bandwidth = BANDWIDTH_10_MHZ; | ||
1196 | break; | ||
1197 | case 8000000: | ||
1198 | p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | ||
1199 | break; | ||
1200 | case 7000000: | ||
1201 | p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; | ||
1202 | break; | ||
1203 | case 6000000: | ||
1204 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
1205 | break; | ||
1206 | case 5000000: | ||
1207 | p->u.ofdm.bandwidth = BANDWIDTH_5_MHZ; | ||
1208 | break; | ||
1209 | case 1712000: | ||
1210 | p->u.ofdm.bandwidth = BANDWIDTH_1_712_MHZ; | ||
1211 | break; | ||
1212 | case 0: | ||
1213 | default: | ||
1214 | p->u.ofdm.bandwidth = BANDWIDTH_AUTO; | ||
1215 | } | ||
1216 | p->u.ofdm.code_rate_HP = c->code_rate_HP; | ||
1217 | p->u.ofdm.code_rate_LP = c->code_rate_LP; | ||
1218 | p->u.ofdm.constellation = c->modulation; | ||
1219 | p->u.ofdm.transmission_mode = c->transmission_mode; | ||
1220 | p->u.ofdm.guard_interval = c->guard_interval; | ||
1221 | p->u.ofdm.hierarchy_information = c->hierarchy; | ||
1222 | break; | ||
1223 | case DVBV3_ATSC: | ||
1224 | dprintk("%s() Preparing VSB req\n", __func__); | ||
1225 | p->u.vsb.modulation = c->modulation; | ||
1226 | break; | ||
1227 | } | ||
1228 | return 0; | ||
1229 | } | ||
1230 | |||
1231 | /** | ||
1232 | * dtv_get_frontend - calls a callback for retrieving DTV parameters | ||
1233 | * @fe: struct dvb_frontend pointer | ||
1234 | * @c: struct dtv_frontend_properties pointer (DVBv5 cache) | ||
1235 | * @p_out struct dvb_frontend_parameters pointer (DVBv3 FE struct) | ||
1236 | * | ||
1237 | * This routine calls either the DVBv3 or DVBv5 get_frontend call. | ||
1238 | * If c is not null, it will update the DVBv5 cache struct pointed by it. | ||
1239 | * If p_out is not null, it will update the DVBv3 params pointed by it. | ||
1240 | */ | ||
1241 | static int dtv_get_frontend(struct dvb_frontend *fe, | ||
1242 | struct dvb_frontend_parameters *p_out) | ||
1243 | { | ||
1244 | int r; | ||
1245 | |||
1246 | if (fe->ops.get_frontend) { | ||
1247 | r = fe->ops.get_frontend(fe); | ||
1248 | if (unlikely(r < 0)) | ||
1249 | return r; | ||
1250 | if (p_out) | ||
1251 | dtv_property_legacy_params_sync(fe, p_out); | ||
1252 | return 0; | ||
1253 | } | ||
1254 | |||
1255 | /* As everything is in cache, get_frontend fops are always supported */ | ||
1256 | return 0; | ||
1257 | } | ||
1258 | |||
1259 | static int dvb_frontend_ioctl_legacy(struct file *file, | ||
1260 | unsigned int cmd, void *parg); | ||
1261 | static int dvb_frontend_ioctl_properties(struct file *file, | ||
1262 | unsigned int cmd, void *parg); | ||
1263 | |||
1264 | static int dtv_property_process_get(struct dvb_frontend *fe, | ||
1265 | const struct dtv_frontend_properties *c, | ||
1266 | struct dtv_property *tvp, | ||
1267 | struct file *file) | ||
1268 | { | ||
1269 | int r, ncaps; | ||
1270 | |||
1271 | switch(tvp->cmd) { | ||
1272 | case DTV_ENUM_DELSYS: | ||
1273 | ncaps = 0; | ||
1274 | while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { | ||
1275 | tvp->u.buffer.data[ncaps] = fe->ops.delsys[ncaps]; | ||
1276 | ncaps++; | ||
1277 | } | ||
1278 | tvp->u.buffer.len = ncaps; | ||
1279 | break; | ||
1280 | case DTV_FREQUENCY: | ||
1281 | tvp->u.data = c->frequency; | ||
1282 | break; | ||
1283 | case DTV_MODULATION: | ||
1284 | tvp->u.data = c->modulation; | ||
1285 | break; | ||
1286 | case DTV_BANDWIDTH_HZ: | ||
1287 | tvp->u.data = c->bandwidth_hz; | ||
1288 | break; | ||
1289 | case DTV_INVERSION: | ||
1290 | tvp->u.data = c->inversion; | ||
1291 | break; | ||
1292 | case DTV_SYMBOL_RATE: | ||
1293 | tvp->u.data = c->symbol_rate; | ||
1294 | break; | ||
1295 | case DTV_INNER_FEC: | ||
1296 | tvp->u.data = c->fec_inner; | ||
1297 | break; | ||
1298 | case DTV_PILOT: | ||
1299 | tvp->u.data = c->pilot; | ||
1300 | break; | ||
1301 | case DTV_ROLLOFF: | ||
1302 | tvp->u.data = c->rolloff; | ||
1303 | break; | ||
1304 | case DTV_DELIVERY_SYSTEM: | ||
1305 | tvp->u.data = c->delivery_system; | ||
1306 | break; | ||
1307 | case DTV_VOLTAGE: | ||
1308 | tvp->u.data = c->voltage; | ||
1309 | break; | ||
1310 | case DTV_TONE: | ||
1311 | tvp->u.data = c->sectone; | ||
1312 | break; | ||
1313 | case DTV_API_VERSION: | ||
1314 | tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR; | ||
1315 | break; | ||
1316 | case DTV_CODE_RATE_HP: | ||
1317 | tvp->u.data = c->code_rate_HP; | ||
1318 | break; | ||
1319 | case DTV_CODE_RATE_LP: | ||
1320 | tvp->u.data = c->code_rate_LP; | ||
1321 | break; | ||
1322 | case DTV_GUARD_INTERVAL: | ||
1323 | tvp->u.data = c->guard_interval; | ||
1324 | break; | ||
1325 | case DTV_TRANSMISSION_MODE: | ||
1326 | tvp->u.data = c->transmission_mode; | ||
1327 | break; | ||
1328 | case DTV_HIERARCHY: | ||
1329 | tvp->u.data = c->hierarchy; | ||
1330 | break; | ||
1331 | case DTV_INTERLEAVING: | ||
1332 | tvp->u.data = c->interleaving; | ||
1333 | break; | ||
1334 | |||
1335 | /* ISDB-T Support here */ | ||
1336 | case DTV_ISDBT_PARTIAL_RECEPTION: | ||
1337 | tvp->u.data = c->isdbt_partial_reception; | ||
1338 | break; | ||
1339 | case DTV_ISDBT_SOUND_BROADCASTING: | ||
1340 | tvp->u.data = c->isdbt_sb_mode; | ||
1341 | break; | ||
1342 | case DTV_ISDBT_SB_SUBCHANNEL_ID: | ||
1343 | tvp->u.data = c->isdbt_sb_subchannel; | ||
1344 | break; | ||
1345 | case DTV_ISDBT_SB_SEGMENT_IDX: | ||
1346 | tvp->u.data = c->isdbt_sb_segment_idx; | ||
1347 | break; | ||
1348 | case DTV_ISDBT_SB_SEGMENT_COUNT: | ||
1349 | tvp->u.data = c->isdbt_sb_segment_count; | ||
1350 | break; | ||
1351 | case DTV_ISDBT_LAYER_ENABLED: | ||
1352 | tvp->u.data = c->isdbt_layer_enabled; | ||
1353 | break; | ||
1354 | case DTV_ISDBT_LAYERA_FEC: | ||
1355 | tvp->u.data = c->layer[0].fec; | ||
1356 | break; | ||
1357 | case DTV_ISDBT_LAYERA_MODULATION: | ||
1358 | tvp->u.data = c->layer[0].modulation; | ||
1359 | break; | ||
1360 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: | ||
1361 | tvp->u.data = c->layer[0].segment_count; | ||
1362 | break; | ||
1363 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: | ||
1364 | tvp->u.data = c->layer[0].interleaving; | ||
1365 | break; | ||
1366 | case DTV_ISDBT_LAYERB_FEC: | ||
1367 | tvp->u.data = c->layer[1].fec; | ||
1368 | break; | ||
1369 | case DTV_ISDBT_LAYERB_MODULATION: | ||
1370 | tvp->u.data = c->layer[1].modulation; | ||
1371 | break; | ||
1372 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: | ||
1373 | tvp->u.data = c->layer[1].segment_count; | ||
1374 | break; | ||
1375 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: | ||
1376 | tvp->u.data = c->layer[1].interleaving; | ||
1377 | break; | ||
1378 | case DTV_ISDBT_LAYERC_FEC: | ||
1379 | tvp->u.data = c->layer[2].fec; | ||
1380 | break; | ||
1381 | case DTV_ISDBT_LAYERC_MODULATION: | ||
1382 | tvp->u.data = c->layer[2].modulation; | ||
1383 | break; | ||
1384 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: | ||
1385 | tvp->u.data = c->layer[2].segment_count; | ||
1386 | break; | ||
1387 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: | ||
1388 | tvp->u.data = c->layer[2].interleaving; | ||
1389 | break; | ||
1390 | case DTV_ISDBS_TS_ID: | ||
1391 | tvp->u.data = c->isdbs_ts_id; | ||
1392 | break; | ||
1393 | case DTV_DVBT2_PLP_ID: | ||
1394 | tvp->u.data = c->dvbt2_plp_id; | ||
1395 | break; | ||
1396 | |||
1397 | /* ATSC-MH */ | ||
1398 | case DTV_ATSCMH_FIC_VER: | ||
1399 | tvp->u.data = fe->dtv_property_cache.atscmh_fic_ver; | ||
1400 | break; | ||
1401 | case DTV_ATSCMH_PARADE_ID: | ||
1402 | tvp->u.data = fe->dtv_property_cache.atscmh_parade_id; | ||
1403 | break; | ||
1404 | case DTV_ATSCMH_NOG: | ||
1405 | tvp->u.data = fe->dtv_property_cache.atscmh_nog; | ||
1406 | break; | ||
1407 | case DTV_ATSCMH_TNOG: | ||
1408 | tvp->u.data = fe->dtv_property_cache.atscmh_tnog; | ||
1409 | break; | ||
1410 | case DTV_ATSCMH_SGN: | ||
1411 | tvp->u.data = fe->dtv_property_cache.atscmh_sgn; | ||
1412 | break; | ||
1413 | case DTV_ATSCMH_PRC: | ||
1414 | tvp->u.data = fe->dtv_property_cache.atscmh_prc; | ||
1415 | break; | ||
1416 | case DTV_ATSCMH_RS_FRAME_MODE: | ||
1417 | tvp->u.data = fe->dtv_property_cache.atscmh_rs_frame_mode; | ||
1418 | break; | ||
1419 | case DTV_ATSCMH_RS_FRAME_ENSEMBLE: | ||
1420 | tvp->u.data = fe->dtv_property_cache.atscmh_rs_frame_ensemble; | ||
1421 | break; | ||
1422 | case DTV_ATSCMH_RS_CODE_MODE_PRI: | ||
1423 | tvp->u.data = fe->dtv_property_cache.atscmh_rs_code_mode_pri; | ||
1424 | break; | ||
1425 | case DTV_ATSCMH_RS_CODE_MODE_SEC: | ||
1426 | tvp->u.data = fe->dtv_property_cache.atscmh_rs_code_mode_sec; | ||
1427 | break; | ||
1428 | case DTV_ATSCMH_SCCC_BLOCK_MODE: | ||
1429 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_block_mode; | ||
1430 | break; | ||
1431 | case DTV_ATSCMH_SCCC_CODE_MODE_A: | ||
1432 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_a; | ||
1433 | break; | ||
1434 | case DTV_ATSCMH_SCCC_CODE_MODE_B: | ||
1435 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_b; | ||
1436 | break; | ||
1437 | case DTV_ATSCMH_SCCC_CODE_MODE_C: | ||
1438 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_c; | ||
1439 | break; | ||
1440 | case DTV_ATSCMH_SCCC_CODE_MODE_D: | ||
1441 | tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_d; | ||
1442 | break; | ||
1443 | |||
1444 | default: | ||
1445 | return -EINVAL; | ||
1446 | } | ||
1447 | |||
1448 | /* Allow the frontend to override outgoing properties */ | ||
1449 | if (fe->ops.get_property) { | ||
1450 | r = fe->ops.get_property(fe, tvp); | ||
1451 | if (r < 0) | ||
1452 | return r; | ||
1453 | } | ||
1454 | |||
1455 | dtv_property_dump(tvp); | ||
1456 | |||
1457 | return 0; | ||
1458 | } | ||
1459 | |||
1460 | static int dtv_set_frontend(struct dvb_frontend *fe); | ||
1461 | |||
1462 | static bool is_dvbv3_delsys(u32 delsys) | ||
1463 | { | ||
1464 | bool status; | ||
1465 | |||
1466 | status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) || | ||
1467 | (delsys == SYS_DVBS) || (delsys == SYS_ATSC); | ||
1468 | |||
1469 | return status; | ||
1470 | } | ||
1471 | |||
1472 | static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) | ||
1473 | { | ||
1474 | int ncaps, i; | ||
1475 | u32 delsys = SYS_UNDEFINED; | ||
1476 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1477 | enum dvbv3_emulation_type type; | ||
1478 | |||
1479 | /* | ||
1480 | * It was reported that some old DVBv5 applications were | ||
1481 | * filling delivery_system with SYS_UNDEFINED. If this happens, | ||
1482 | * assume that the application wants to use the first supported | ||
1483 | * delivery system. | ||
1484 | */ | ||
1485 | if (c->delivery_system == SYS_UNDEFINED) | ||
1486 | c->delivery_system = fe->ops.delsys[0]; | ||
1487 | |||
1488 | if (desired_system == SYS_UNDEFINED) { | ||
1489 | /* | ||
1490 | * A DVBv3 call doesn't know what's the desired system. | ||
1491 | * Also, DVBv3 applications don't know that ops.info->type | ||
1492 | * could be changed, and they simply dies when it doesn't | ||
1493 | * match. | ||
1494 | * So, don't change the current delivery system, as it | ||
1495 | * may be trying to do the wrong thing, like setting an | ||
1496 | * ISDB-T frontend as DVB-T. Instead, find the closest | ||
1497 | * DVBv3 system that matches the delivery system. | ||
1498 | */ | ||
1499 | if (is_dvbv3_delsys(c->delivery_system)) { | ||
1500 | dprintk("%s() Using delivery system to %d\n", | ||
1501 | __func__, c->delivery_system); | ||
1502 | return 0; | ||
1503 | } | ||
1504 | type = dvbv3_type(c->delivery_system); | ||
1505 | switch (type) { | ||
1506 | case DVBV3_QPSK: | ||
1507 | desired_system = SYS_DVBS; | ||
1508 | break; | ||
1509 | case DVBV3_QAM: | ||
1510 | desired_system = SYS_DVBC_ANNEX_A; | ||
1511 | break; | ||
1512 | case DVBV3_ATSC: | ||
1513 | desired_system = SYS_ATSC; | ||
1514 | break; | ||
1515 | case DVBV3_OFDM: | ||
1516 | desired_system = SYS_DVBT; | ||
1517 | break; | ||
1518 | default: | ||
1519 | dprintk("%s(): This frontend doesn't support DVBv3 calls\n", | ||
1520 | __func__); | ||
1521 | return -EINVAL; | ||
1522 | } | ||
1523 | /* | ||
1524 | * Get a delivery system that is compatible with DVBv3 | ||
1525 | * NOTE: in order for this to work with softwares like Kaffeine that | ||
1526 | * uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to | ||
1527 | * DVB-S, drivers that support both should put the SYS_DVBS entry | ||
1528 | * before the SYS_DVBS2, otherwise it won't switch back to DVB-S. | ||
1529 | * The real fix is that userspace applications should not use DVBv3 | ||
1530 | * and not trust on calling FE_SET_FRONTEND to switch the delivery | ||
1531 | * system. | ||
1532 | */ | ||
1533 | ncaps = 0; | ||
1534 | while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { | ||
1535 | if (fe->ops.delsys[ncaps] == desired_system) { | ||
1536 | delsys = desired_system; | ||
1537 | break; | ||
1538 | } | ||
1539 | ncaps++; | ||
1540 | } | ||
1541 | if (delsys == SYS_UNDEFINED) { | ||
1542 | dprintk("%s() Couldn't find a delivery system that matches %d\n", | ||
1543 | __func__, desired_system); | ||
1544 | } | ||
1545 | } else { | ||
1546 | /* | ||
1547 | * This is a DVBv5 call. So, it likely knows the supported | ||
1548 | * delivery systems. | ||
1549 | */ | ||
1550 | |||
1551 | /* Check if the desired delivery system is supported */ | ||
1552 | ncaps = 0; | ||
1553 | while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { | ||
1554 | if (fe->ops.delsys[ncaps] == desired_system) { | ||
1555 | c->delivery_system = desired_system; | ||
1556 | dprintk("%s() Changing delivery system to %d\n", | ||
1557 | __func__, desired_system); | ||
1558 | return 0; | ||
1559 | } | ||
1560 | ncaps++; | ||
1561 | } | ||
1562 | type = dvbv3_type(desired_system); | ||
1563 | |||
1564 | /* | ||
1565 | * The delivery system is not supported. See if it can be | ||
1566 | * emulated. | ||
1567 | * The emulation only works if the desired system is one of the | ||
1568 | * DVBv3 delivery systems | ||
1569 | */ | ||
1570 | if (!is_dvbv3_delsys(desired_system)) { | ||
1571 | dprintk("%s() can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n", | ||
1572 | __func__); | ||
1573 | return -EINVAL; | ||
1574 | } | ||
1575 | |||
1576 | /* | ||
1577 | * Get the last non-DVBv3 delivery system that has the same type | ||
1578 | * of the desired system | ||
1579 | */ | ||
1580 | ncaps = 0; | ||
1581 | while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { | ||
1582 | if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) && | ||
1583 | !is_dvbv3_delsys(fe->ops.delsys[ncaps])) | ||
1584 | delsys = fe->ops.delsys[ncaps]; | ||
1585 | ncaps++; | ||
1586 | } | ||
1587 | /* There's nothing compatible with the desired delivery system */ | ||
1588 | if (delsys == SYS_UNDEFINED) { | ||
1589 | dprintk("%s() Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n", | ||
1590 | __func__); | ||
1591 | return -EINVAL; | ||
1592 | } | ||
1593 | } | ||
1594 | |||
1595 | c->delivery_system = delsys; | ||
1596 | |||
1597 | /* | ||
1598 | * The DVBv3 or DVBv5 call is requesting a different system. So, | ||
1599 | * emulation is needed. | ||
1600 | * | ||
1601 | * Emulate newer delivery systems like ISDBT, DVBT and DTMB | ||
1602 | * for older DVBv5 applications. The emulation will try to use | ||
1603 | * the auto mode for most things, and will assume that the desired | ||
1604 | * delivery system is the last one at the ops.delsys[] array | ||
1605 | */ | ||
1606 | dprintk("%s() Using delivery system %d emulated as if it were a %d\n", | ||
1607 | __func__, delsys, desired_system); | ||
1608 | |||
1609 | /* | ||
1610 | * For now, handles ISDB-T calls. More code may be needed here for the | ||
1611 | * other emulated stuff | ||
1612 | */ | ||
1613 | if (type == DVBV3_OFDM) { | ||
1614 | if (c->delivery_system == SYS_ISDBT) { | ||
1615 | dprintk("%s() Using defaults for SYS_ISDBT\n", | ||
1616 | __func__); | ||
1617 | if (!c->bandwidth_hz) | ||
1618 | c->bandwidth_hz = 6000000; | ||
1619 | |||
1620 | c->isdbt_partial_reception = 0; | ||
1621 | c->isdbt_sb_mode = 0; | ||
1622 | c->isdbt_sb_subchannel = 0; | ||
1623 | c->isdbt_sb_segment_idx = 0; | ||
1624 | c->isdbt_sb_segment_count = 0; | ||
1625 | c->isdbt_layer_enabled = 0; | ||
1626 | for (i = 0; i < 3; i++) { | ||
1627 | c->layer[i].fec = FEC_AUTO; | ||
1628 | c->layer[i].modulation = QAM_AUTO; | ||
1629 | c->layer[i].interleaving = 0; | ||
1630 | c->layer[i].segment_count = 0; | ||
1631 | } | ||
1632 | } | ||
1633 | } | ||
1634 | dprintk("change delivery system on cache to %d\n", c->delivery_system); | ||
1635 | |||
1636 | return 0; | ||
1637 | } | ||
1638 | |||
1639 | static int dtv_property_process_set(struct dvb_frontend *fe, | ||
1640 | struct dtv_property *tvp, | ||
1641 | struct file *file) | ||
1642 | { | ||
1643 | int r = 0; | ||
1644 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1645 | |||
1646 | /* Allow the frontend to validate incoming properties */ | ||
1647 | if (fe->ops.set_property) { | ||
1648 | r = fe->ops.set_property(fe, tvp); | ||
1649 | if (r < 0) | ||
1650 | return r; | ||
1651 | } | ||
1652 | |||
1653 | switch(tvp->cmd) { | ||
1654 | case DTV_CLEAR: | ||
1655 | /* | ||
1656 | * Reset a cache of data specific to the frontend here. This does | ||
1657 | * not effect hardware. | ||
1658 | */ | ||
1659 | dvb_frontend_clear_cache(fe); | ||
1660 | break; | ||
1661 | case DTV_TUNE: | ||
1662 | /* interpret the cache of data, build either a traditional frontend | ||
1663 | * tunerequest so we can pass validation in the FE_SET_FRONTEND | ||
1664 | * ioctl. | ||
1665 | */ | ||
1666 | c->state = tvp->cmd; | ||
1667 | dprintk("%s() Finalised property cache\n", __func__); | ||
1668 | |||
1669 | r = dtv_set_frontend(fe); | ||
1670 | break; | ||
1671 | case DTV_FREQUENCY: | ||
1672 | c->frequency = tvp->u.data; | ||
1673 | break; | ||
1674 | case DTV_MODULATION: | ||
1675 | c->modulation = tvp->u.data; | ||
1676 | break; | ||
1677 | case DTV_BANDWIDTH_HZ: | ||
1678 | c->bandwidth_hz = tvp->u.data; | ||
1679 | break; | ||
1680 | case DTV_INVERSION: | ||
1681 | c->inversion = tvp->u.data; | ||
1682 | break; | ||
1683 | case DTV_SYMBOL_RATE: | ||
1684 | c->symbol_rate = tvp->u.data; | ||
1685 | break; | ||
1686 | case DTV_INNER_FEC: | ||
1687 | c->fec_inner = tvp->u.data; | ||
1688 | break; | ||
1689 | case DTV_PILOT: | ||
1690 | c->pilot = tvp->u.data; | ||
1691 | break; | ||
1692 | case DTV_ROLLOFF: | ||
1693 | c->rolloff = tvp->u.data; | ||
1694 | break; | ||
1695 | case DTV_DELIVERY_SYSTEM: | ||
1696 | r = set_delivery_system(fe, tvp->u.data); | ||
1697 | break; | ||
1698 | case DTV_VOLTAGE: | ||
1699 | c->voltage = tvp->u.data; | ||
1700 | r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE, | ||
1701 | (void *)c->voltage); | ||
1702 | break; | ||
1703 | case DTV_TONE: | ||
1704 | c->sectone = tvp->u.data; | ||
1705 | r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE, | ||
1706 | (void *)c->sectone); | ||
1707 | break; | ||
1708 | case DTV_CODE_RATE_HP: | ||
1709 | c->code_rate_HP = tvp->u.data; | ||
1710 | break; | ||
1711 | case DTV_CODE_RATE_LP: | ||
1712 | c->code_rate_LP = tvp->u.data; | ||
1713 | break; | ||
1714 | case DTV_GUARD_INTERVAL: | ||
1715 | c->guard_interval = tvp->u.data; | ||
1716 | break; | ||
1717 | case DTV_TRANSMISSION_MODE: | ||
1718 | c->transmission_mode = tvp->u.data; | ||
1719 | break; | ||
1720 | case DTV_HIERARCHY: | ||
1721 | c->hierarchy = tvp->u.data; | ||
1722 | break; | ||
1723 | case DTV_INTERLEAVING: | ||
1724 | c->interleaving = tvp->u.data; | ||
1725 | break; | ||
1726 | |||
1727 | /* ISDB-T Support here */ | ||
1728 | case DTV_ISDBT_PARTIAL_RECEPTION: | ||
1729 | c->isdbt_partial_reception = tvp->u.data; | ||
1730 | break; | ||
1731 | case DTV_ISDBT_SOUND_BROADCASTING: | ||
1732 | c->isdbt_sb_mode = tvp->u.data; | ||
1733 | break; | ||
1734 | case DTV_ISDBT_SB_SUBCHANNEL_ID: | ||
1735 | c->isdbt_sb_subchannel = tvp->u.data; | ||
1736 | break; | ||
1737 | case DTV_ISDBT_SB_SEGMENT_IDX: | ||
1738 | c->isdbt_sb_segment_idx = tvp->u.data; | ||
1739 | break; | ||
1740 | case DTV_ISDBT_SB_SEGMENT_COUNT: | ||
1741 | c->isdbt_sb_segment_count = tvp->u.data; | ||
1742 | break; | ||
1743 | case DTV_ISDBT_LAYER_ENABLED: | ||
1744 | c->isdbt_layer_enabled = tvp->u.data; | ||
1745 | break; | ||
1746 | case DTV_ISDBT_LAYERA_FEC: | ||
1747 | c->layer[0].fec = tvp->u.data; | ||
1748 | break; | ||
1749 | case DTV_ISDBT_LAYERA_MODULATION: | ||
1750 | c->layer[0].modulation = tvp->u.data; | ||
1751 | break; | ||
1752 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: | ||
1753 | c->layer[0].segment_count = tvp->u.data; | ||
1754 | break; | ||
1755 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: | ||
1756 | c->layer[0].interleaving = tvp->u.data; | ||
1757 | break; | ||
1758 | case DTV_ISDBT_LAYERB_FEC: | ||
1759 | c->layer[1].fec = tvp->u.data; | ||
1760 | break; | ||
1761 | case DTV_ISDBT_LAYERB_MODULATION: | ||
1762 | c->layer[1].modulation = tvp->u.data; | ||
1763 | break; | ||
1764 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: | ||
1765 | c->layer[1].segment_count = tvp->u.data; | ||
1766 | break; | ||
1767 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: | ||
1768 | c->layer[1].interleaving = tvp->u.data; | ||
1769 | break; | ||
1770 | case DTV_ISDBT_LAYERC_FEC: | ||
1771 | c->layer[2].fec = tvp->u.data; | ||
1772 | break; | ||
1773 | case DTV_ISDBT_LAYERC_MODULATION: | ||
1774 | c->layer[2].modulation = tvp->u.data; | ||
1775 | break; | ||
1776 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: | ||
1777 | c->layer[2].segment_count = tvp->u.data; | ||
1778 | break; | ||
1779 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: | ||
1780 | c->layer[2].interleaving = tvp->u.data; | ||
1781 | break; | ||
1782 | case DTV_ISDBS_TS_ID: | ||
1783 | c->isdbs_ts_id = tvp->u.data; | ||
1784 | break; | ||
1785 | case DTV_DVBT2_PLP_ID: | ||
1786 | c->dvbt2_plp_id = tvp->u.data; | ||
1787 | break; | ||
1788 | |||
1789 | /* ATSC-MH */ | ||
1790 | case DTV_ATSCMH_PARADE_ID: | ||
1791 | fe->dtv_property_cache.atscmh_parade_id = tvp->u.data; | ||
1792 | break; | ||
1793 | case DTV_ATSCMH_RS_FRAME_ENSEMBLE: | ||
1794 | fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data; | ||
1795 | break; | ||
1796 | |||
1797 | default: | ||
1798 | return -EINVAL; | ||
1799 | } | ||
1800 | |||
1801 | return r; | ||
1802 | } | ||
1803 | |||
1804 | static int dvb_frontend_ioctl(struct file *file, | ||
1805 | unsigned int cmd, void *parg) | ||
1806 | { | ||
1807 | struct dvb_device *dvbdev = file->private_data; | ||
1808 | struct dvb_frontend *fe = dvbdev->priv; | ||
1809 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1810 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1811 | int err = -EOPNOTSUPP; | ||
1812 | |||
1813 | dprintk("%s (%d)\n", __func__, _IOC_NR(cmd)); | ||
1814 | |||
1815 | if (fepriv->exit != DVB_FE_NO_EXIT) | ||
1816 | return -ENODEV; | ||
1817 | |||
1818 | if ((file->f_flags & O_ACCMODE) == O_RDONLY && | ||
1819 | (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT || | ||
1820 | cmd == FE_DISEQC_RECV_SLAVE_REPLY)) | ||
1821 | return -EPERM; | ||
1822 | |||
1823 | if (down_interruptible (&fepriv->sem)) | ||
1824 | return -ERESTARTSYS; | ||
1825 | |||
1826 | if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) | ||
1827 | err = dvb_frontend_ioctl_properties(file, cmd, parg); | ||
1828 | else { | ||
1829 | c->state = DTV_UNDEFINED; | ||
1830 | err = dvb_frontend_ioctl_legacy(file, cmd, parg); | ||
1831 | } | ||
1832 | |||
1833 | up(&fepriv->sem); | ||
1834 | return err; | ||
1835 | } | ||
1836 | |||
1837 | static int dvb_frontend_ioctl_properties(struct file *file, | ||
1838 | unsigned int cmd, void *parg) | ||
1839 | { | ||
1840 | struct dvb_device *dvbdev = file->private_data; | ||
1841 | struct dvb_frontend *fe = dvbdev->priv; | ||
1842 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1843 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1844 | int err = 0; | ||
1845 | |||
1846 | struct dtv_properties *tvps = NULL; | ||
1847 | struct dtv_property *tvp = NULL; | ||
1848 | int i; | ||
1849 | |||
1850 | dprintk("%s\n", __func__); | ||
1851 | |||
1852 | if(cmd == FE_SET_PROPERTY) { | ||
1853 | tvps = (struct dtv_properties __user *)parg; | ||
1854 | |||
1855 | dprintk("%s() properties.num = %d\n", __func__, tvps->num); | ||
1856 | dprintk("%s() properties.props = %p\n", __func__, tvps->props); | ||
1857 | |||
1858 | /* Put an arbitrary limit on the number of messages that can | ||
1859 | * be sent at once */ | ||
1860 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) | ||
1861 | return -EINVAL; | ||
1862 | |||
1863 | tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); | ||
1864 | if (!tvp) { | ||
1865 | err = -ENOMEM; | ||
1866 | goto out; | ||
1867 | } | ||
1868 | |||
1869 | if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { | ||
1870 | err = -EFAULT; | ||
1871 | goto out; | ||
1872 | } | ||
1873 | |||
1874 | for (i = 0; i < tvps->num; i++) { | ||
1875 | err = dtv_property_process_set(fe, tvp + i, file); | ||
1876 | if (err < 0) | ||
1877 | goto out; | ||
1878 | (tvp + i)->result = err; | ||
1879 | } | ||
1880 | |||
1881 | if (c->state == DTV_TUNE) | ||
1882 | dprintk("%s() Property cache is full, tuning\n", __func__); | ||
1883 | |||
1884 | } else | ||
1885 | if(cmd == FE_GET_PROPERTY) { | ||
1886 | tvps = (struct dtv_properties __user *)parg; | ||
1887 | |||
1888 | dprintk("%s() properties.num = %d\n", __func__, tvps->num); | ||
1889 | dprintk("%s() properties.props = %p\n", __func__, tvps->props); | ||
1890 | |||
1891 | /* Put an arbitrary limit on the number of messages that can | ||
1892 | * be sent at once */ | ||
1893 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) | ||
1894 | return -EINVAL; | ||
1895 | |||
1896 | tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); | ||
1897 | if (!tvp) { | ||
1898 | err = -ENOMEM; | ||
1899 | goto out; | ||
1900 | } | ||
1901 | |||
1902 | if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { | ||
1903 | err = -EFAULT; | ||
1904 | goto out; | ||
1905 | } | ||
1906 | |||
1907 | /* | ||
1908 | * Fills the cache out struct with the cache contents, plus | ||
1909 | * the data retrieved from get_frontend, if the frontend | ||
1910 | * is not idle. Otherwise, returns the cached content | ||
1911 | */ | ||
1912 | if (fepriv->state != FESTATE_IDLE) { | ||
1913 | err = dtv_get_frontend(fe, NULL); | ||
1914 | if (err < 0) | ||
1915 | goto out; | ||
1916 | } | ||
1917 | for (i = 0; i < tvps->num; i++) { | ||
1918 | err = dtv_property_process_get(fe, c, tvp + i, file); | ||
1919 | if (err < 0) | ||
1920 | goto out; | ||
1921 | (tvp + i)->result = err; | ||
1922 | } | ||
1923 | |||
1924 | if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { | ||
1925 | err = -EFAULT; | ||
1926 | goto out; | ||
1927 | } | ||
1928 | |||
1929 | } else | ||
1930 | err = -EOPNOTSUPP; | ||
1931 | |||
1932 | out: | ||
1933 | kfree(tvp); | ||
1934 | return err; | ||
1935 | } | ||
1936 | |||
1937 | static int dtv_set_frontend(struct dvb_frontend *fe) | ||
1938 | { | ||
1939 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1940 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1941 | struct dvb_frontend_tune_settings fetunesettings; | ||
1942 | u32 rolloff = 0; | ||
1943 | |||
1944 | if (dvb_frontend_check_parameters(fe) < 0) | ||
1945 | return -EINVAL; | ||
1946 | |||
1947 | /* | ||
1948 | * Initialize output parameters to match the values given by | ||
1949 | * the user. FE_SET_FRONTEND triggers an initial frontend event | ||
1950 | * with status = 0, which copies output parameters to userspace. | ||
1951 | */ | ||
1952 | dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); | ||
1953 | |||
1954 | /* | ||
1955 | * Be sure that the bandwidth will be filled for all | ||
1956 | * non-satellite systems, as tuners need to know what | ||
1957 | * low pass/Nyquist half filter should be applied, in | ||
1958 | * order to avoid inter-channel noise. | ||
1959 | * | ||
1960 | * ISDB-T and DVB-T/T2 already sets bandwidth. | ||
1961 | * ATSC and DVB-C don't set, so, the core should fill it. | ||
1962 | * | ||
1963 | * On DVB-C Annex A and C, the bandwidth is a function of | ||
1964 | * the roll-off and symbol rate. Annex B defines different | ||
1965 | * roll-off factors depending on the modulation. Fortunately, | ||
1966 | * Annex B is only used with 6MHz, so there's no need to | ||
1967 | * calculate it. | ||
1968 | * | ||
1969 | * While not officially supported, a side effect of handling it at | ||
1970 | * the cache level is that a program could retrieve the bandwidth | ||
1971 | * via DTV_BANDWIDTH_HZ, which may be useful for test programs. | ||
1972 | */ | ||
1973 | switch (c->delivery_system) { | ||
1974 | case SYS_ATSC: | ||
1975 | case SYS_DVBC_ANNEX_B: | ||
1976 | c->bandwidth_hz = 6000000; | ||
1977 | break; | ||
1978 | case SYS_DVBC_ANNEX_A: | ||
1979 | rolloff = 115; | ||
1980 | break; | ||
1981 | case SYS_DVBC_ANNEX_C: | ||
1982 | rolloff = 113; | ||
1983 | break; | ||
1984 | default: | ||
1985 | break; | ||
1986 | } | ||
1987 | if (rolloff) | ||
1988 | c->bandwidth_hz = (c->symbol_rate * rolloff) / 100; | ||
1989 | |||
1990 | /* force auto frequency inversion if requested */ | ||
1991 | if (dvb_force_auto_inversion) | ||
1992 | c->inversion = INVERSION_AUTO; | ||
1993 | |||
1994 | /* | ||
1995 | * without hierarchical coding code_rate_LP is irrelevant, | ||
1996 | * so we tolerate the otherwise invalid FEC_NONE setting | ||
1997 | */ | ||
1998 | if (c->hierarchy == HIERARCHY_NONE && c->code_rate_LP == FEC_NONE) | ||
1999 | c->code_rate_LP = FEC_AUTO; | ||
2000 | |||
2001 | /* get frontend-specific tuning settings */ | ||
2002 | memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); | ||
2003 | if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) { | ||
2004 | fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000; | ||
2005 | fepriv->max_drift = fetunesettings.max_drift; | ||
2006 | fepriv->step_size = fetunesettings.step_size; | ||
2007 | } else { | ||
2008 | /* default values */ | ||
2009 | switch (c->delivery_system) { | ||
2010 | case SYS_DVBS: | ||
2011 | case SYS_DVBS2: | ||
2012 | case SYS_ISDBS: | ||
2013 | case SYS_TURBO: | ||
2014 | case SYS_DVBC_ANNEX_A: | ||
2015 | case SYS_DVBC_ANNEX_C: | ||
2016 | fepriv->min_delay = HZ / 20; | ||
2017 | fepriv->step_size = c->symbol_rate / 16000; | ||
2018 | fepriv->max_drift = c->symbol_rate / 2000; | ||
2019 | break; | ||
2020 | case SYS_DVBT: | ||
2021 | case SYS_DVBT2: | ||
2022 | case SYS_ISDBT: | ||
2023 | case SYS_DTMB: | ||
2024 | fepriv->min_delay = HZ / 20; | ||
2025 | fepriv->step_size = fe->ops.info.frequency_stepsize * 2; | ||
2026 | fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; | ||
2027 | break; | ||
2028 | default: | ||
2029 | /* | ||
2030 | * FIXME: This sounds wrong! if freqency_stepsize is | ||
2031 | * defined by the frontend, why not use it??? | ||
2032 | */ | ||
2033 | fepriv->min_delay = HZ / 20; | ||
2034 | fepriv->step_size = 0; /* no zigzag */ | ||
2035 | fepriv->max_drift = 0; | ||
2036 | break; | ||
2037 | } | ||
2038 | } | ||
2039 | if (dvb_override_tune_delay > 0) | ||
2040 | fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000; | ||
2041 | |||
2042 | fepriv->state = FESTATE_RETUNE; | ||
2043 | |||
2044 | /* Request the search algorithm to search */ | ||
2045 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | ||
2046 | |||
2047 | dvb_frontend_clear_events(fe); | ||
2048 | dvb_frontend_add_event(fe, 0); | ||
2049 | dvb_frontend_wakeup(fe); | ||
2050 | fepriv->status = 0; | ||
2051 | |||
2052 | return 0; | ||
2053 | } | ||
2054 | |||
2055 | |||
2056 | static int dvb_frontend_ioctl_legacy(struct file *file, | ||
2057 | unsigned int cmd, void *parg) | ||
2058 | { | ||
2059 | struct dvb_device *dvbdev = file->private_data; | ||
2060 | struct dvb_frontend *fe = dvbdev->priv; | ||
2061 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2062 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
2063 | int err = -EOPNOTSUPP; | ||
2064 | |||
2065 | switch (cmd) { | ||
2066 | case FE_GET_INFO: { | ||
2067 | struct dvb_frontend_info* info = parg; | ||
2068 | |||
2069 | memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); | ||
2070 | dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max); | ||
2071 | |||
2072 | /* | ||
2073 | * Associate the 4 delivery systems supported by DVBv3 | ||
2074 | * API with their DVBv5 counterpart. For the other standards, | ||
2075 | * use the closest type, assuming that it would hopefully | ||
2076 | * work with a DVBv3 application. | ||
2077 | * It should be noticed that, on multi-frontend devices with | ||
2078 | * different types (terrestrial and cable, for example), | ||
2079 | * a pure DVBv3 application won't be able to use all delivery | ||
2080 | * systems. Yet, changing the DVBv5 cache to the other delivery | ||
2081 | * system should be enough for making it work. | ||
2082 | */ | ||
2083 | switch (dvbv3_type(c->delivery_system)) { | ||
2084 | case DVBV3_QPSK: | ||
2085 | info->type = FE_QPSK; | ||
2086 | break; | ||
2087 | case DVBV3_ATSC: | ||
2088 | info->type = FE_ATSC; | ||
2089 | break; | ||
2090 | case DVBV3_QAM: | ||
2091 | info->type = FE_QAM; | ||
2092 | break; | ||
2093 | case DVBV3_OFDM: | ||
2094 | info->type = FE_OFDM; | ||
2095 | break; | ||
2096 | default: | ||
2097 | printk(KERN_ERR | ||
2098 | "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", | ||
2099 | __func__, c->delivery_system); | ||
2100 | fe->ops.info.type = FE_OFDM; | ||
2101 | } | ||
2102 | dprintk("current delivery system on cache: %d, V3 type: %d\n", | ||
2103 | c->delivery_system, fe->ops.info.type); | ||
2104 | |||
2105 | /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't | ||
2106 | * do it, it is done for it. */ | ||
2107 | info->caps |= FE_CAN_INVERSION_AUTO; | ||
2108 | err = 0; | ||
2109 | break; | ||
2110 | } | ||
2111 | |||
2112 | case FE_READ_STATUS: { | ||
2113 | fe_status_t* status = parg; | ||
2114 | |||
2115 | /* if retune was requested but hasn't occurred yet, prevent | ||
2116 | * that user get signal state from previous tuning */ | ||
2117 | if (fepriv->state == FESTATE_RETUNE || | ||
2118 | fepriv->state == FESTATE_ERROR) { | ||
2119 | err=0; | ||
2120 | *status = 0; | ||
2121 | break; | ||
2122 | } | ||
2123 | |||
2124 | if (fe->ops.read_status) | ||
2125 | err = fe->ops.read_status(fe, status); | ||
2126 | break; | ||
2127 | } | ||
2128 | case FE_READ_BER: | ||
2129 | if (fe->ops.read_ber) | ||
2130 | err = fe->ops.read_ber(fe, (__u32*) parg); | ||
2131 | break; | ||
2132 | |||
2133 | case FE_READ_SIGNAL_STRENGTH: | ||
2134 | if (fe->ops.read_signal_strength) | ||
2135 | err = fe->ops.read_signal_strength(fe, (__u16*) parg); | ||
2136 | break; | ||
2137 | |||
2138 | case FE_READ_SNR: | ||
2139 | if (fe->ops.read_snr) | ||
2140 | err = fe->ops.read_snr(fe, (__u16*) parg); | ||
2141 | break; | ||
2142 | |||
2143 | case FE_READ_UNCORRECTED_BLOCKS: | ||
2144 | if (fe->ops.read_ucblocks) | ||
2145 | err = fe->ops.read_ucblocks(fe, (__u32*) parg); | ||
2146 | break; | ||
2147 | |||
2148 | |||
2149 | case FE_DISEQC_RESET_OVERLOAD: | ||
2150 | if (fe->ops.diseqc_reset_overload) { | ||
2151 | err = fe->ops.diseqc_reset_overload(fe); | ||
2152 | fepriv->state = FESTATE_DISEQC; | ||
2153 | fepriv->status = 0; | ||
2154 | } | ||
2155 | break; | ||
2156 | |||
2157 | case FE_DISEQC_SEND_MASTER_CMD: | ||
2158 | if (fe->ops.diseqc_send_master_cmd) { | ||
2159 | err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg); | ||
2160 | fepriv->state = FESTATE_DISEQC; | ||
2161 | fepriv->status = 0; | ||
2162 | } | ||
2163 | break; | ||
2164 | |||
2165 | case FE_DISEQC_SEND_BURST: | ||
2166 | if (fe->ops.diseqc_send_burst) { | ||
2167 | err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg); | ||
2168 | fepriv->state = FESTATE_DISEQC; | ||
2169 | fepriv->status = 0; | ||
2170 | } | ||
2171 | break; | ||
2172 | |||
2173 | case FE_SET_TONE: | ||
2174 | if (fe->ops.set_tone) { | ||
2175 | err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg); | ||
2176 | fepriv->tone = (fe_sec_tone_mode_t) parg; | ||
2177 | fepriv->state = FESTATE_DISEQC; | ||
2178 | fepriv->status = 0; | ||
2179 | } | ||
2180 | break; | ||
2181 | |||
2182 | case FE_SET_VOLTAGE: | ||
2183 | if (fe->ops.set_voltage) { | ||
2184 | err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg); | ||
2185 | fepriv->voltage = (fe_sec_voltage_t) parg; | ||
2186 | fepriv->state = FESTATE_DISEQC; | ||
2187 | fepriv->status = 0; | ||
2188 | } | ||
2189 | break; | ||
2190 | |||
2191 | case FE_DISHNETWORK_SEND_LEGACY_CMD: | ||
2192 | if (fe->ops.dishnetwork_send_legacy_command) { | ||
2193 | err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg); | ||
2194 | fepriv->state = FESTATE_DISEQC; | ||
2195 | fepriv->status = 0; | ||
2196 | } else if (fe->ops.set_voltage) { | ||
2197 | /* | ||
2198 | * NOTE: This is a fallback condition. Some frontends | ||
2199 | * (stv0299 for instance) take longer than 8msec to | ||
2200 | * respond to a set_voltage command. Those switches | ||
2201 | * need custom routines to switch properly. For all | ||
2202 | * other frontends, the following should work ok. | ||
2203 | * Dish network legacy switches (as used by Dish500) | ||
2204 | * are controlled by sending 9-bit command words | ||
2205 | * spaced 8msec apart. | ||
2206 | * the actual command word is switch/port dependent | ||
2207 | * so it is up to the userspace application to send | ||
2208 | * the right command. | ||
2209 | * The command must always start with a '0' after | ||
2210 | * initialization, so parg is 8 bits and does not | ||
2211 | * include the initialization or start bit | ||
2212 | */ | ||
2213 | unsigned long swcmd = ((unsigned long) parg) << 1; | ||
2214 | struct timeval nexttime; | ||
2215 | struct timeval tv[10]; | ||
2216 | int i; | ||
2217 | u8 last = 1; | ||
2218 | if (dvb_frontend_debug) | ||
2219 | printk("%s switch command: 0x%04lx\n", __func__, swcmd); | ||
2220 | do_gettimeofday(&nexttime); | ||
2221 | if (dvb_frontend_debug) | ||
2222 | memcpy(&tv[0], &nexttime, sizeof(struct timeval)); | ||
2223 | /* before sending a command, initialize by sending | ||
2224 | * a 32ms 18V to the switch | ||
2225 | */ | ||
2226 | fe->ops.set_voltage(fe, SEC_VOLTAGE_18); | ||
2227 | dvb_frontend_sleep_until(&nexttime, 32000); | ||
2228 | |||
2229 | for (i = 0; i < 9; i++) { | ||
2230 | if (dvb_frontend_debug) | ||
2231 | do_gettimeofday(&tv[i + 1]); | ||
2232 | if ((swcmd & 0x01) != last) { | ||
2233 | /* set voltage to (last ? 13V : 18V) */ | ||
2234 | fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); | ||
2235 | last = (last) ? 0 : 1; | ||
2236 | } | ||
2237 | swcmd = swcmd >> 1; | ||
2238 | if (i != 8) | ||
2239 | dvb_frontend_sleep_until(&nexttime, 8000); | ||
2240 | } | ||
2241 | if (dvb_frontend_debug) { | ||
2242 | printk("%s(%d): switch delay (should be 32k followed by all 8k\n", | ||
2243 | __func__, fe->dvb->num); | ||
2244 | for (i = 1; i < 10; i++) | ||
2245 | printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i])); | ||
2246 | } | ||
2247 | err = 0; | ||
2248 | fepriv->state = FESTATE_DISEQC; | ||
2249 | fepriv->status = 0; | ||
2250 | } | ||
2251 | break; | ||
2252 | |||
2253 | case FE_DISEQC_RECV_SLAVE_REPLY: | ||
2254 | if (fe->ops.diseqc_recv_slave_reply) | ||
2255 | err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg); | ||
2256 | break; | ||
2257 | |||
2258 | case FE_ENABLE_HIGH_LNB_VOLTAGE: | ||
2259 | if (fe->ops.enable_high_lnb_voltage) | ||
2260 | err = fe->ops.enable_high_lnb_voltage(fe, (long) parg); | ||
2261 | break; | ||
2262 | |||
2263 | case FE_SET_FRONTEND: | ||
2264 | err = set_delivery_system(fe, SYS_UNDEFINED); | ||
2265 | if (err) | ||
2266 | break; | ||
2267 | |||
2268 | err = dtv_property_cache_sync(fe, c, parg); | ||
2269 | if (err) | ||
2270 | break; | ||
2271 | err = dtv_set_frontend(fe); | ||
2272 | break; | ||
2273 | case FE_GET_EVENT: | ||
2274 | err = dvb_frontend_get_event (fe, parg, file->f_flags); | ||
2275 | break; | ||
2276 | |||
2277 | case FE_GET_FRONTEND: | ||
2278 | err = dtv_get_frontend(fe, parg); | ||
2279 | break; | ||
2280 | |||
2281 | case FE_SET_FRONTEND_TUNE_MODE: | ||
2282 | fepriv->tune_mode_flags = (unsigned long) parg; | ||
2283 | err = 0; | ||
2284 | break; | ||
2285 | }; | ||
2286 | |||
2287 | return err; | ||
2288 | } | ||
2289 | |||
2290 | |||
2291 | static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait) | ||
2292 | { | ||
2293 | struct dvb_device *dvbdev = file->private_data; | ||
2294 | struct dvb_frontend *fe = dvbdev->priv; | ||
2295 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2296 | |||
2297 | dprintk ("%s\n", __func__); | ||
2298 | |||
2299 | poll_wait (file, &fepriv->events.wait_queue, wait); | ||
2300 | |||
2301 | if (fepriv->events.eventw != fepriv->events.eventr) | ||
2302 | return (POLLIN | POLLRDNORM | POLLPRI); | ||
2303 | |||
2304 | return 0; | ||
2305 | } | ||
2306 | |||
2307 | static int dvb_frontend_open(struct inode *inode, struct file *file) | ||
2308 | { | ||
2309 | struct dvb_device *dvbdev = file->private_data; | ||
2310 | struct dvb_frontend *fe = dvbdev->priv; | ||
2311 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2312 | struct dvb_adapter *adapter = fe->dvb; | ||
2313 | int ret; | ||
2314 | |||
2315 | dprintk ("%s\n", __func__); | ||
2316 | if (fepriv->exit == DVB_FE_DEVICE_REMOVED) | ||
2317 | return -ENODEV; | ||
2318 | |||
2319 | if (adapter->mfe_shared) { | ||
2320 | mutex_lock (&adapter->mfe_lock); | ||
2321 | |||
2322 | if (adapter->mfe_dvbdev == NULL) | ||
2323 | adapter->mfe_dvbdev = dvbdev; | ||
2324 | |||
2325 | else if (adapter->mfe_dvbdev != dvbdev) { | ||
2326 | struct dvb_device | ||
2327 | *mfedev = adapter->mfe_dvbdev; | ||
2328 | struct dvb_frontend | ||
2329 | *mfe = mfedev->priv; | ||
2330 | struct dvb_frontend_private | ||
2331 | *mfepriv = mfe->frontend_priv; | ||
2332 | int mferetry = (dvb_mfe_wait_time << 1); | ||
2333 | |||
2334 | mutex_unlock (&adapter->mfe_lock); | ||
2335 | while (mferetry-- && (mfedev->users != -1 || | ||
2336 | mfepriv->thread != NULL)) { | ||
2337 | if(msleep_interruptible(500)) { | ||
2338 | if(signal_pending(current)) | ||
2339 | return -EINTR; | ||
2340 | } | ||
2341 | } | ||
2342 | |||
2343 | mutex_lock (&adapter->mfe_lock); | ||
2344 | if(adapter->mfe_dvbdev != dvbdev) { | ||
2345 | mfedev = adapter->mfe_dvbdev; | ||
2346 | mfe = mfedev->priv; | ||
2347 | mfepriv = mfe->frontend_priv; | ||
2348 | if (mfedev->users != -1 || | ||
2349 | mfepriv->thread != NULL) { | ||
2350 | mutex_unlock (&adapter->mfe_lock); | ||
2351 | return -EBUSY; | ||
2352 | } | ||
2353 | adapter->mfe_dvbdev = dvbdev; | ||
2354 | } | ||
2355 | } | ||
2356 | } | ||
2357 | |||
2358 | if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) { | ||
2359 | if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0) | ||
2360 | goto err0; | ||
2361 | |||
2362 | /* If we took control of the bus, we need to force | ||
2363 | reinitialization. This is because many ts_bus_ctrl() | ||
2364 | functions strobe the RESET pin on the demod, and if the | ||
2365 | frontend thread already exists then the dvb_init() routine | ||
2366 | won't get called (which is what usually does initial | ||
2367 | register configuration). */ | ||
2368 | fepriv->reinitialise = 1; | ||
2369 | } | ||
2370 | |||
2371 | if ((ret = dvb_generic_open (inode, file)) < 0) | ||
2372 | goto err1; | ||
2373 | |||
2374 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
2375 | /* normal tune mode when opened R/W */ | ||
2376 | fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; | ||
2377 | fepriv->tone = -1; | ||
2378 | fepriv->voltage = -1; | ||
2379 | |||
2380 | ret = dvb_frontend_start (fe); | ||
2381 | if (ret) | ||
2382 | goto err2; | ||
2383 | |||
2384 | /* empty event queue */ | ||
2385 | fepriv->events.eventr = fepriv->events.eventw = 0; | ||
2386 | } | ||
2387 | |||
2388 | if (adapter->mfe_shared) | ||
2389 | mutex_unlock (&adapter->mfe_lock); | ||
2390 | return ret; | ||
2391 | |||
2392 | err2: | ||
2393 | dvb_generic_release(inode, file); | ||
2394 | err1: | ||
2395 | if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) | ||
2396 | fe->ops.ts_bus_ctrl(fe, 0); | ||
2397 | err0: | ||
2398 | if (adapter->mfe_shared) | ||
2399 | mutex_unlock (&adapter->mfe_lock); | ||
2400 | return ret; | ||
2401 | } | ||
2402 | |||
2403 | static int dvb_frontend_release(struct inode *inode, struct file *file) | ||
2404 | { | ||
2405 | struct dvb_device *dvbdev = file->private_data; | ||
2406 | struct dvb_frontend *fe = dvbdev->priv; | ||
2407 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2408 | int ret; | ||
2409 | |||
2410 | dprintk ("%s\n", __func__); | ||
2411 | |||
2412 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
2413 | fepriv->release_jiffies = jiffies; | ||
2414 | mb(); | ||
2415 | } | ||
2416 | |||
2417 | ret = dvb_generic_release (inode, file); | ||
2418 | |||
2419 | if (dvbdev->users == -1) { | ||
2420 | wake_up(&fepriv->wait_queue); | ||
2421 | if (fepriv->exit != DVB_FE_NO_EXIT) { | ||
2422 | fops_put(file->f_op); | ||
2423 | file->f_op = NULL; | ||
2424 | wake_up(&dvbdev->wait_queue); | ||
2425 | } | ||
2426 | if (fe->ops.ts_bus_ctrl) | ||
2427 | fe->ops.ts_bus_ctrl(fe, 0); | ||
2428 | } | ||
2429 | |||
2430 | return ret; | ||
2431 | } | ||
2432 | |||
2433 | static const struct file_operations dvb_frontend_fops = { | ||
2434 | .owner = THIS_MODULE, | ||
2435 | .unlocked_ioctl = dvb_generic_ioctl, | ||
2436 | .poll = dvb_frontend_poll, | ||
2437 | .open = dvb_frontend_open, | ||
2438 | .release = dvb_frontend_release, | ||
2439 | .llseek = noop_llseek, | ||
2440 | }; | ||
2441 | |||
2442 | int dvb_register_frontend(struct dvb_adapter* dvb, | ||
2443 | struct dvb_frontend* fe) | ||
2444 | { | ||
2445 | struct dvb_frontend_private *fepriv; | ||
2446 | static const struct dvb_device dvbdev_template = { | ||
2447 | .users = ~0, | ||
2448 | .writers = 1, | ||
2449 | .readers = (~0)-1, | ||
2450 | .fops = &dvb_frontend_fops, | ||
2451 | .kernel_ioctl = dvb_frontend_ioctl | ||
2452 | }; | ||
2453 | |||
2454 | dprintk ("%s\n", __func__); | ||
2455 | |||
2456 | if (mutex_lock_interruptible(&frontend_mutex)) | ||
2457 | return -ERESTARTSYS; | ||
2458 | |||
2459 | fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL); | ||
2460 | if (fe->frontend_priv == NULL) { | ||
2461 | mutex_unlock(&frontend_mutex); | ||
2462 | return -ENOMEM; | ||
2463 | } | ||
2464 | fepriv = fe->frontend_priv; | ||
2465 | |||
2466 | sema_init(&fepriv->sem, 1); | ||
2467 | init_waitqueue_head (&fepriv->wait_queue); | ||
2468 | init_waitqueue_head (&fepriv->events.wait_queue); | ||
2469 | mutex_init(&fepriv->events.mtx); | ||
2470 | fe->dvb = dvb; | ||
2471 | fepriv->inversion = INVERSION_OFF; | ||
2472 | |||
2473 | printk ("DVB: registering adapter %i frontend %i (%s)...\n", | ||
2474 | fe->dvb->num, | ||
2475 | fe->id, | ||
2476 | fe->ops.info.name); | ||
2477 | |||
2478 | dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, | ||
2479 | fe, DVB_DEVICE_FRONTEND); | ||
2480 | |||
2481 | /* | ||
2482 | * Initialize the cache to the proper values according with the | ||
2483 | * first supported delivery system (ops->delsys[0]) | ||
2484 | */ | ||
2485 | |||
2486 | fe->dtv_property_cache.delivery_system = fe->ops.delsys[0]; | ||
2487 | dvb_frontend_clear_cache(fe); | ||
2488 | |||
2489 | mutex_unlock(&frontend_mutex); | ||
2490 | return 0; | ||
2491 | } | ||
2492 | EXPORT_SYMBOL(dvb_register_frontend); | ||
2493 | |||
2494 | int dvb_unregister_frontend(struct dvb_frontend* fe) | ||
2495 | { | ||
2496 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2497 | dprintk ("%s\n", __func__); | ||
2498 | |||
2499 | mutex_lock(&frontend_mutex); | ||
2500 | dvb_frontend_stop (fe); | ||
2501 | mutex_unlock(&frontend_mutex); | ||
2502 | |||
2503 | if (fepriv->dvbdev->users < -1) | ||
2504 | wait_event(fepriv->dvbdev->wait_queue, | ||
2505 | fepriv->dvbdev->users==-1); | ||
2506 | |||
2507 | mutex_lock(&frontend_mutex); | ||
2508 | dvb_unregister_device (fepriv->dvbdev); | ||
2509 | |||
2510 | /* fe is invalid now */ | ||
2511 | kfree(fepriv); | ||
2512 | mutex_unlock(&frontend_mutex); | ||
2513 | return 0; | ||
2514 | } | ||
2515 | EXPORT_SYMBOL(dvb_unregister_frontend); | ||
2516 | |||
2517 | #ifdef CONFIG_MEDIA_ATTACH | ||
2518 | void dvb_frontend_detach(struct dvb_frontend* fe) | ||
2519 | { | ||
2520 | void *ptr; | ||
2521 | |||
2522 | if (fe->ops.release_sec) { | ||
2523 | fe->ops.release_sec(fe); | ||
2524 | symbol_put_addr(fe->ops.release_sec); | ||
2525 | } | ||
2526 | if (fe->ops.tuner_ops.release) { | ||
2527 | fe->ops.tuner_ops.release(fe); | ||
2528 | symbol_put_addr(fe->ops.tuner_ops.release); | ||
2529 | } | ||
2530 | if (fe->ops.analog_ops.release) { | ||
2531 | fe->ops.analog_ops.release(fe); | ||
2532 | symbol_put_addr(fe->ops.analog_ops.release); | ||
2533 | } | ||
2534 | ptr = (void*)fe->ops.release; | ||
2535 | if (ptr) { | ||
2536 | fe->ops.release(fe); | ||
2537 | symbol_put_addr(ptr); | ||
2538 | } | ||
2539 | } | ||
2540 | #else | ||
2541 | void dvb_frontend_detach(struct dvb_frontend* fe) | ||
2542 | { | ||
2543 | if (fe->ops.release_sec) | ||
2544 | fe->ops.release_sec(fe); | ||
2545 | if (fe->ops.tuner_ops.release) | ||
2546 | fe->ops.tuner_ops.release(fe); | ||
2547 | if (fe->ops.analog_ops.release) | ||
2548 | fe->ops.analog_ops.release(fe); | ||
2549 | if (fe->ops.release) | ||
2550 | fe->ops.release(fe); | ||
2551 | } | ||
2552 | #endif | ||
2553 | EXPORT_SYMBOL(dvb_frontend_detach); | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h deleted file mode 100644 index de410cc94fbb..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ /dev/null | |||
@@ -1,425 +0,0 @@ | |||
1 | /* | ||
2 | * dvb_frontend.h | ||
3 | * | ||
4 | * Copyright (C) 2001 convergence integrated media GmbH | ||
5 | * Copyright (C) 2004 convergence GmbH | ||
6 | * | ||
7 | * Written by Ralph Metzler | ||
8 | * Overhauled by Holger Waechtler | ||
9 | * Kernel I2C stuff by Michael Hunold <hunold@convergence.de> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU Lesser General Public License | ||
13 | * as published by the Free Software Foundation; either version 2.1 | ||
14 | * of the License, or (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | |||
22 | * You should have received a copy of the GNU Lesser General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #ifndef _DVB_FRONTEND_H_ | ||
29 | #define _DVB_FRONTEND_H_ | ||
30 | |||
31 | #include <linux/types.h> | ||
32 | #include <linux/sched.h> | ||
33 | #include <linux/ioctl.h> | ||
34 | #include <linux/i2c.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/delay.h> | ||
38 | #include <linux/mutex.h> | ||
39 | #include <linux/slab.h> | ||
40 | |||
41 | #include <linux/dvb/frontend.h> | ||
42 | |||
43 | #include "dvbdev.h" | ||
44 | |||
45 | /* | ||
46 | * Maximum number of Delivery systems per frontend. It | ||
47 | * should be smaller or equal to 32 | ||
48 | */ | ||
49 | #define MAX_DELSYS 8 | ||
50 | |||
51 | struct dvb_frontend_tune_settings { | ||
52 | int min_delay_ms; | ||
53 | int step_size; | ||
54 | int max_drift; | ||
55 | }; | ||
56 | |||
57 | struct dvb_frontend; | ||
58 | |||
59 | struct dvb_tuner_info { | ||
60 | char name[128]; | ||
61 | |||
62 | u32 frequency_min; | ||
63 | u32 frequency_max; | ||
64 | u32 frequency_step; | ||
65 | |||
66 | u32 bandwidth_min; | ||
67 | u32 bandwidth_max; | ||
68 | u32 bandwidth_step; | ||
69 | }; | ||
70 | |||
71 | struct analog_parameters { | ||
72 | unsigned int frequency; | ||
73 | unsigned int mode; | ||
74 | unsigned int audmode; | ||
75 | u64 std; | ||
76 | }; | ||
77 | |||
78 | enum dvbfe_modcod { | ||
79 | DVBFE_MODCOD_DUMMY_PLFRAME = 0, | ||
80 | DVBFE_MODCOD_QPSK_1_4, | ||
81 | DVBFE_MODCOD_QPSK_1_3, | ||
82 | DVBFE_MODCOD_QPSK_2_5, | ||
83 | DVBFE_MODCOD_QPSK_1_2, | ||
84 | DVBFE_MODCOD_QPSK_3_5, | ||
85 | DVBFE_MODCOD_QPSK_2_3, | ||
86 | DVBFE_MODCOD_QPSK_3_4, | ||
87 | DVBFE_MODCOD_QPSK_4_5, | ||
88 | DVBFE_MODCOD_QPSK_5_6, | ||
89 | DVBFE_MODCOD_QPSK_8_9, | ||
90 | DVBFE_MODCOD_QPSK_9_10, | ||
91 | DVBFE_MODCOD_8PSK_3_5, | ||
92 | DVBFE_MODCOD_8PSK_2_3, | ||
93 | DVBFE_MODCOD_8PSK_3_4, | ||
94 | DVBFE_MODCOD_8PSK_5_6, | ||
95 | DVBFE_MODCOD_8PSK_8_9, | ||
96 | DVBFE_MODCOD_8PSK_9_10, | ||
97 | DVBFE_MODCOD_16APSK_2_3, | ||
98 | DVBFE_MODCOD_16APSK_3_4, | ||
99 | DVBFE_MODCOD_16APSK_4_5, | ||
100 | DVBFE_MODCOD_16APSK_5_6, | ||
101 | DVBFE_MODCOD_16APSK_8_9, | ||
102 | DVBFE_MODCOD_16APSK_9_10, | ||
103 | DVBFE_MODCOD_32APSK_3_4, | ||
104 | DVBFE_MODCOD_32APSK_4_5, | ||
105 | DVBFE_MODCOD_32APSK_5_6, | ||
106 | DVBFE_MODCOD_32APSK_8_9, | ||
107 | DVBFE_MODCOD_32APSK_9_10, | ||
108 | DVBFE_MODCOD_RESERVED_1, | ||
109 | DVBFE_MODCOD_BPSK_1_3, | ||
110 | DVBFE_MODCOD_BPSK_1_4, | ||
111 | DVBFE_MODCOD_RESERVED_2 | ||
112 | }; | ||
113 | |||
114 | enum tuner_param { | ||
115 | DVBFE_TUNER_FREQUENCY = (1 << 0), | ||
116 | DVBFE_TUNER_TUNERSTEP = (1 << 1), | ||
117 | DVBFE_TUNER_IFFREQ = (1 << 2), | ||
118 | DVBFE_TUNER_BANDWIDTH = (1 << 3), | ||
119 | DVBFE_TUNER_REFCLOCK = (1 << 4), | ||
120 | DVBFE_TUNER_IQSENSE = (1 << 5), | ||
121 | DVBFE_TUNER_DUMMY = (1 << 31) | ||
122 | }; | ||
123 | |||
124 | /* | ||
125 | * ALGO_HW: (Hardware Algorithm) | ||
126 | * ---------------------------------------------------------------- | ||
127 | * Devices that support this algorithm do everything in hardware | ||
128 | * and no software support is needed to handle them. | ||
129 | * Requesting these devices to LOCK is the only thing required, | ||
130 | * device is supposed to do everything in the hardware. | ||
131 | * | ||
132 | * ALGO_SW: (Software Algorithm) | ||
133 | * ---------------------------------------------------------------- | ||
134 | * These are dumb devices, that require software to do everything | ||
135 | * | ||
136 | * ALGO_CUSTOM: (Customizable Agorithm) | ||
137 | * ---------------------------------------------------------------- | ||
138 | * Devices having this algorithm can be customized to have specific | ||
139 | * algorithms in the frontend driver, rather than simply doing a | ||
140 | * software zig-zag. In this case the zigzag maybe hardware assisted | ||
141 | * or it maybe completely done in hardware. In all cases, usage of | ||
142 | * this algorithm, in conjunction with the search and track | ||
143 | * callbacks, utilizes the driver specific algorithm. | ||
144 | * | ||
145 | * ALGO_RECOVERY: (Recovery Algorithm) | ||
146 | * ---------------------------------------------------------------- | ||
147 | * These devices have AUTO recovery capabilities from LOCK failure | ||
148 | */ | ||
149 | enum dvbfe_algo { | ||
150 | DVBFE_ALGO_HW = (1 << 0), | ||
151 | DVBFE_ALGO_SW = (1 << 1), | ||
152 | DVBFE_ALGO_CUSTOM = (1 << 2), | ||
153 | DVBFE_ALGO_RECOVERY = (1 << 31) | ||
154 | }; | ||
155 | |||
156 | struct tuner_state { | ||
157 | u32 frequency; | ||
158 | u32 tunerstep; | ||
159 | u32 ifreq; | ||
160 | u32 bandwidth; | ||
161 | u32 iqsense; | ||
162 | u32 refclock; | ||
163 | }; | ||
164 | |||
165 | /* | ||
166 | * search callback possible return status | ||
167 | * | ||
168 | * DVBFE_ALGO_SEARCH_SUCCESS | ||
169 | * The frontend search algorithm completed and returned successfully | ||
170 | * | ||
171 | * DVBFE_ALGO_SEARCH_ASLEEP | ||
172 | * The frontend search algorithm is sleeping | ||
173 | * | ||
174 | * DVBFE_ALGO_SEARCH_FAILED | ||
175 | * The frontend search for a signal failed | ||
176 | * | ||
177 | * DVBFE_ALGO_SEARCH_INVALID | ||
178 | * The frontend search algorith was probably supplied with invalid | ||
179 | * parameters and the search is an invalid one | ||
180 | * | ||
181 | * DVBFE_ALGO_SEARCH_ERROR | ||
182 | * The frontend search algorithm failed due to some error | ||
183 | * | ||
184 | * DVBFE_ALGO_SEARCH_AGAIN | ||
185 | * The frontend search algorithm was requested to search again | ||
186 | */ | ||
187 | enum dvbfe_search { | ||
188 | DVBFE_ALGO_SEARCH_SUCCESS = (1 << 0), | ||
189 | DVBFE_ALGO_SEARCH_ASLEEP = (1 << 1), | ||
190 | DVBFE_ALGO_SEARCH_FAILED = (1 << 2), | ||
191 | DVBFE_ALGO_SEARCH_INVALID = (1 << 3), | ||
192 | DVBFE_ALGO_SEARCH_AGAIN = (1 << 4), | ||
193 | DVBFE_ALGO_SEARCH_ERROR = (1 << 31), | ||
194 | }; | ||
195 | |||
196 | |||
197 | struct dvb_tuner_ops { | ||
198 | |||
199 | struct dvb_tuner_info info; | ||
200 | |||
201 | int (*release)(struct dvb_frontend *fe); | ||
202 | int (*init)(struct dvb_frontend *fe); | ||
203 | int (*sleep)(struct dvb_frontend *fe); | ||
204 | |||
205 | /** This is for simple PLLs - set all parameters in one go. */ | ||
206 | int (*set_params)(struct dvb_frontend *fe); | ||
207 | int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p); | ||
208 | |||
209 | /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */ | ||
210 | int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len); | ||
211 | |||
212 | /** This is to allow setting tuner-specific configs */ | ||
213 | int (*set_config)(struct dvb_frontend *fe, void *priv_cfg); | ||
214 | |||
215 | int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency); | ||
216 | int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth); | ||
217 | int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency); | ||
218 | |||
219 | #define TUNER_STATUS_LOCKED 1 | ||
220 | #define TUNER_STATUS_STEREO 2 | ||
221 | int (*get_status)(struct dvb_frontend *fe, u32 *status); | ||
222 | int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength); | ||
223 | int (*get_afc)(struct dvb_frontend *fe, s32 *afc); | ||
224 | |||
225 | /** These are provided separately from set_params in order to facilitate silicon | ||
226 | * tuners which require sophisticated tuning loops, controlling each parameter separately. */ | ||
227 | int (*set_frequency)(struct dvb_frontend *fe, u32 frequency); | ||
228 | int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth); | ||
229 | |||
230 | /* | ||
231 | * These are provided separately from set_params in order to facilitate silicon | ||
232 | * tuners which require sophisticated tuning loops, controlling each parameter separately. | ||
233 | */ | ||
234 | int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state); | ||
235 | int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state); | ||
236 | }; | ||
237 | |||
238 | struct analog_demod_info { | ||
239 | char *name; | ||
240 | }; | ||
241 | |||
242 | struct analog_demod_ops { | ||
243 | |||
244 | struct analog_demod_info info; | ||
245 | |||
246 | void (*set_params)(struct dvb_frontend *fe, | ||
247 | struct analog_parameters *params); | ||
248 | int (*has_signal)(struct dvb_frontend *fe); | ||
249 | int (*get_afc)(struct dvb_frontend *fe); | ||
250 | void (*tuner_status)(struct dvb_frontend *fe); | ||
251 | void (*standby)(struct dvb_frontend *fe); | ||
252 | void (*release)(struct dvb_frontend *fe); | ||
253 | int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable); | ||
254 | |||
255 | /** This is to allow setting tuner-specific configuration */ | ||
256 | int (*set_config)(struct dvb_frontend *fe, void *priv_cfg); | ||
257 | }; | ||
258 | |||
259 | struct dtv_frontend_properties; | ||
260 | |||
261 | struct dvb_frontend_ops { | ||
262 | |||
263 | struct dvb_frontend_info info; | ||
264 | |||
265 | u8 delsys[MAX_DELSYS]; | ||
266 | |||
267 | void (*release)(struct dvb_frontend* fe); | ||
268 | void (*release_sec)(struct dvb_frontend* fe); | ||
269 | |||
270 | int (*init)(struct dvb_frontend* fe); | ||
271 | int (*sleep)(struct dvb_frontend* fe); | ||
272 | |||
273 | int (*write)(struct dvb_frontend* fe, const u8 buf[], int len); | ||
274 | |||
275 | /* if this is set, it overrides the default swzigzag */ | ||
276 | int (*tune)(struct dvb_frontend* fe, | ||
277 | bool re_tune, | ||
278 | unsigned int mode_flags, | ||
279 | unsigned int *delay, | ||
280 | fe_status_t *status); | ||
281 | /* get frontend tuning algorithm from the module */ | ||
282 | enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe); | ||
283 | |||
284 | /* these two are only used for the swzigzag code */ | ||
285 | int (*set_frontend)(struct dvb_frontend *fe); | ||
286 | int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); | ||
287 | |||
288 | int (*get_frontend)(struct dvb_frontend *fe); | ||
289 | |||
290 | int (*read_status)(struct dvb_frontend* fe, fe_status_t* status); | ||
291 | int (*read_ber)(struct dvb_frontend* fe, u32* ber); | ||
292 | int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength); | ||
293 | int (*read_snr)(struct dvb_frontend* fe, u16* snr); | ||
294 | int (*read_ucblocks)(struct dvb_frontend* fe, u32* ucblocks); | ||
295 | |||
296 | int (*diseqc_reset_overload)(struct dvb_frontend* fe); | ||
297 | int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd); | ||
298 | int (*diseqc_recv_slave_reply)(struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply); | ||
299 | int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd); | ||
300 | int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone); | ||
301 | int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); | ||
302 | int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg); | ||
303 | int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd); | ||
304 | int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable); | ||
305 | int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire); | ||
306 | |||
307 | /* These callbacks are for devices that implement their own | ||
308 | * tuning algorithms, rather than a simple swzigzag | ||
309 | */ | ||
310 | enum dvbfe_search (*search)(struct dvb_frontend *fe); | ||
311 | |||
312 | struct dvb_tuner_ops tuner_ops; | ||
313 | struct analog_demod_ops analog_ops; | ||
314 | |||
315 | int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); | ||
316 | int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); | ||
317 | }; | ||
318 | |||
319 | #ifdef __DVB_CORE__ | ||
320 | #define MAX_EVENT 8 | ||
321 | |||
322 | struct dvb_fe_events { | ||
323 | struct dvb_frontend_event events[MAX_EVENT]; | ||
324 | int eventw; | ||
325 | int eventr; | ||
326 | int overflow; | ||
327 | wait_queue_head_t wait_queue; | ||
328 | struct mutex mtx; | ||
329 | }; | ||
330 | #endif | ||
331 | |||
332 | struct dtv_frontend_properties { | ||
333 | |||
334 | /* Cache State */ | ||
335 | u32 state; | ||
336 | |||
337 | u32 frequency; | ||
338 | fe_modulation_t modulation; | ||
339 | |||
340 | fe_sec_voltage_t voltage; | ||
341 | fe_sec_tone_mode_t sectone; | ||
342 | fe_spectral_inversion_t inversion; | ||
343 | fe_code_rate_t fec_inner; | ||
344 | fe_transmit_mode_t transmission_mode; | ||
345 | u32 bandwidth_hz; /* 0 = AUTO */ | ||
346 | fe_guard_interval_t guard_interval; | ||
347 | fe_hierarchy_t hierarchy; | ||
348 | u32 symbol_rate; | ||
349 | fe_code_rate_t code_rate_HP; | ||
350 | fe_code_rate_t code_rate_LP; | ||
351 | |||
352 | fe_pilot_t pilot; | ||
353 | fe_rolloff_t rolloff; | ||
354 | |||
355 | fe_delivery_system_t delivery_system; | ||
356 | |||
357 | enum fe_interleaving interleaving; | ||
358 | |||
359 | /* ISDB-T specifics */ | ||
360 | u8 isdbt_partial_reception; | ||
361 | u8 isdbt_sb_mode; | ||
362 | u8 isdbt_sb_subchannel; | ||
363 | u32 isdbt_sb_segment_idx; | ||
364 | u32 isdbt_sb_segment_count; | ||
365 | u8 isdbt_layer_enabled; | ||
366 | struct { | ||
367 | u8 segment_count; | ||
368 | fe_code_rate_t fec; | ||
369 | fe_modulation_t modulation; | ||
370 | u8 interleaving; | ||
371 | } layer[3]; | ||
372 | |||
373 | /* ISDB-T specifics */ | ||
374 | u32 isdbs_ts_id; | ||
375 | |||
376 | /* DVB-T2 specifics */ | ||
377 | u32 dvbt2_plp_id; | ||
378 | |||
379 | /* ATSC-MH specifics */ | ||
380 | u8 atscmh_fic_ver; | ||
381 | u8 atscmh_parade_id; | ||
382 | u8 atscmh_nog; | ||
383 | u8 atscmh_tnog; | ||
384 | u8 atscmh_sgn; | ||
385 | u8 atscmh_prc; | ||
386 | |||
387 | u8 atscmh_rs_frame_mode; | ||
388 | u8 atscmh_rs_frame_ensemble; | ||
389 | u8 atscmh_rs_code_mode_pri; | ||
390 | u8 atscmh_rs_code_mode_sec; | ||
391 | u8 atscmh_sccc_block_mode; | ||
392 | u8 atscmh_sccc_code_mode_a; | ||
393 | u8 atscmh_sccc_code_mode_b; | ||
394 | u8 atscmh_sccc_code_mode_c; | ||
395 | u8 atscmh_sccc_code_mode_d; | ||
396 | }; | ||
397 | |||
398 | struct dvb_frontend { | ||
399 | struct dvb_frontend_ops ops; | ||
400 | struct dvb_adapter *dvb; | ||
401 | void *demodulator_priv; | ||
402 | void *tuner_priv; | ||
403 | void *frontend_priv; | ||
404 | void *sec_priv; | ||
405 | void *analog_demod_priv; | ||
406 | struct dtv_frontend_properties dtv_property_cache; | ||
407 | #define DVB_FRONTEND_COMPONENT_TUNER 0 | ||
408 | #define DVB_FRONTEND_COMPONENT_DEMOD 1 | ||
409 | int (*callback)(void *adapter_priv, int component, int cmd, int arg); | ||
410 | int id; | ||
411 | }; | ||
412 | |||
413 | extern int dvb_register_frontend(struct dvb_adapter *dvb, | ||
414 | struct dvb_frontend *fe); | ||
415 | |||
416 | extern int dvb_unregister_frontend(struct dvb_frontend *fe); | ||
417 | |||
418 | extern void dvb_frontend_detach(struct dvb_frontend *fe); | ||
419 | |||
420 | extern void dvb_frontend_reinitialise(struct dvb_frontend *fe); | ||
421 | |||
422 | extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec); | ||
423 | extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime); | ||
424 | |||
425 | #endif | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb/dvb-core/dvb_math.c deleted file mode 100644 index beb7c93aa6cb..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_math.c +++ /dev/null | |||
@@ -1,145 +0,0 @@ | |||
1 | /* | ||
2 | * dvb-math provides some complex fixed-point math | ||
3 | * operations shared between the dvb related stuff | ||
4 | * | ||
5 | * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com) | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as | ||
9 | * published by the Free Software Foundation; either version 2.1 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/bitops.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <asm/bug.h> | ||
26 | #include "dvb_math.h" | ||
27 | |||
28 | static const unsigned short logtable[256] = { | ||
29 | 0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7, | ||
30 | 0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508, | ||
31 | 0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6, | ||
32 | 0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37, | ||
33 | 0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f, | ||
34 | 0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41, | ||
35 | 0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1, | ||
36 | 0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142, | ||
37 | 0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68, | ||
38 | 0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355, | ||
39 | 0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c, | ||
40 | 0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490, | ||
41 | 0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3, | ||
42 | 0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507, | ||
43 | 0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe, | ||
44 | 0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca, | ||
45 | 0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c, | ||
46 | 0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7, | ||
47 | 0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c, | ||
48 | 0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c, | ||
49 | 0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a, | ||
50 | 0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065, | ||
51 | 0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730, | ||
52 | 0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc, | ||
53 | 0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469, | ||
54 | 0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9, | ||
55 | 0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c, | ||
56 | 0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765, | ||
57 | 0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83, | ||
58 | 0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387, | ||
59 | 0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973, | ||
60 | 0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47 | ||
61 | }; | ||
62 | |||
63 | unsigned int intlog2(u32 value) | ||
64 | { | ||
65 | /** | ||
66 | * returns: log2(value) * 2^24 | ||
67 | * wrong result if value = 0 (log2(0) is undefined) | ||
68 | */ | ||
69 | unsigned int msb; | ||
70 | unsigned int logentry; | ||
71 | unsigned int significand; | ||
72 | unsigned int interpolation; | ||
73 | |||
74 | if (unlikely(value == 0)) { | ||
75 | WARN_ON(1); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | /* first detect the msb (count begins at 0) */ | ||
80 | msb = fls(value) - 1; | ||
81 | |||
82 | /** | ||
83 | * now we use a logtable after the following method: | ||
84 | * | ||
85 | * log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24 | ||
86 | * where x = msb and therefore 1 <= y < 2 | ||
87 | * first y is determined by shifting the value left | ||
88 | * so that msb is bit 31 | ||
89 | * 0x00231f56 -> 0x8C7D5800 | ||
90 | * the result is y * 2^31 -> "significand" | ||
91 | * then the highest 9 bits are used for a table lookup | ||
92 | * the highest bit is discarded because it's always set | ||
93 | * the highest nine bits in our example are 100011000 | ||
94 | * so we would use the entry 0x18 | ||
95 | */ | ||
96 | significand = value << (31 - msb); | ||
97 | logentry = (significand >> 23) & 0xff; | ||
98 | |||
99 | /** | ||
100 | * last step we do is interpolation because of the | ||
101 | * limitations of the log table the error is that part of | ||
102 | * the significand which isn't used for lookup then we | ||
103 | * compute the ratio between the error and the next table entry | ||
104 | * and interpolate it between the log table entry used and the | ||
105 | * next one the biggest error possible is 0x7fffff | ||
106 | * (in our example it's 0x7D5800) | ||
107 | * needed value for next table entry is 0x800000 | ||
108 | * so the interpolation is | ||
109 | * (error / 0x800000) * (logtable_next - logtable_current) | ||
110 | * in the implementation the division is moved to the end for | ||
111 | * better accuracy there is also an overflow correction if | ||
112 | * logtable_next is 256 | ||
113 | */ | ||
114 | interpolation = ((significand & 0x7fffff) * | ||
115 | ((logtable[(logentry + 1) & 0xff] - | ||
116 | logtable[logentry]) & 0xffff)) >> 15; | ||
117 | |||
118 | /* now we return the result */ | ||
119 | return ((msb << 24) + (logtable[logentry] << 8) + interpolation); | ||
120 | } | ||
121 | EXPORT_SYMBOL(intlog2); | ||
122 | |||
123 | unsigned int intlog10(u32 value) | ||
124 | { | ||
125 | /** | ||
126 | * returns: log10(value) * 2^24 | ||
127 | * wrong result if value = 0 (log10(0) is undefined) | ||
128 | */ | ||
129 | u64 log; | ||
130 | |||
131 | if (unlikely(value == 0)) { | ||
132 | WARN_ON(1); | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | log = intlog2(value); | ||
137 | |||
138 | /** | ||
139 | * we use the following method: | ||
140 | * log10(x) = log2(x) * log10(2) | ||
141 | */ | ||
142 | |||
143 | return (log * 646456993) >> 31; | ||
144 | } | ||
145 | EXPORT_SYMBOL(intlog10); | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_math.h b/drivers/media/dvb/dvb-core/dvb_math.h deleted file mode 100644 index aecc867e9404..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_math.h +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | /* | ||
2 | * dvb-math provides some complex fixed-point math | ||
3 | * operations shared between the dvb related stuff | ||
4 | * | ||
5 | * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com) | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as | ||
9 | * published by the Free Software Foundation; either version 2.1 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifndef __DVB_MATH_H | ||
23 | #define __DVB_MATH_H | ||
24 | |||
25 | #include <linux/types.h> | ||
26 | |||
27 | /** | ||
28 | * computes log2 of a value; the result is shifted left by 24 bits | ||
29 | * | ||
30 | * to use rational values you can use the following method: | ||
31 | * intlog2(value) = intlog2(value * 2^x) - x * 2^24 | ||
32 | * | ||
33 | * example: intlog2(8) will give 3 << 24 = 3 * 2^24 | ||
34 | * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24 | ||
35 | * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24 | ||
36 | * | ||
37 | * @param value The value (must be != 0) | ||
38 | * @return log2(value) * 2^24 | ||
39 | */ | ||
40 | extern unsigned int intlog2(u32 value); | ||
41 | |||
42 | /** | ||
43 | * computes log10 of a value; the result is shifted left by 24 bits | ||
44 | * | ||
45 | * to use rational values you can use the following method: | ||
46 | * intlog10(value) = intlog10(value * 10^x) - x * 2^24 | ||
47 | * | ||
48 | * example: intlog10(1000) will give 3 << 24 = 3 * 2^24 | ||
49 | * due to the implementation intlog10(1000) might be not exactly 3 * 2^24 | ||
50 | * | ||
51 | * look at intlog2 for similar examples | ||
52 | * | ||
53 | * @param value The value (must be != 0) | ||
54 | * @return log10(value) * 2^24 | ||
55 | */ | ||
56 | extern unsigned int intlog10(u32 value); | ||
57 | |||
58 | #endif | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c deleted file mode 100644 index 8766ce8c354d..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ /dev/null | |||
@@ -1,1516 +0,0 @@ | |||
1 | /* | ||
2 | * dvb_net.c | ||
3 | * | ||
4 | * Copyright (C) 2001 Convergence integrated media GmbH | ||
5 | * Ralph Metzler <ralph@convergence.de> | ||
6 | * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de> | ||
7 | * | ||
8 | * ULE Decapsulation code: | ||
9 | * Copyright (C) 2003, 2004 gcs - Global Communication & Services GmbH. | ||
10 | * and Department of Scientific Computing | ||
11 | * Paris Lodron University of Salzburg. | ||
12 | * Hilmar Linder <hlinder@cosy.sbg.ac.at> | ||
13 | * and Wolfram Stering <wstering@cosy.sbg.ac.at> | ||
14 | * | ||
15 | * ULE Decaps according to RFC 4326. | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or | ||
18 | * modify it under the terms of the GNU General Public License | ||
19 | * as published by the Free Software Foundation; either version 2 | ||
20 | * of the License, or (at your option) any later version. | ||
21 | * | ||
22 | * This program is distributed in the hope that it will be useful, | ||
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
25 | * GNU General Public License for more details. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License | ||
28 | * along with this program; if not, write to the Free Software | ||
29 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
30 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
31 | */ | ||
32 | |||
33 | /* | ||
34 | * ULE ChangeLog: | ||
35 | * Feb 2004: hl/ws v1: Implementing draft-fair-ipdvb-ule-01.txt | ||
36 | * | ||
37 | * Dec 2004: hl/ws v2: Implementing draft-ietf-ipdvb-ule-03.txt: | ||
38 | * ULE Extension header handling. | ||
39 | * Bugreports by Moritz Vieth and Hanno Tersteegen, | ||
40 | * Fraunhofer Institute for Open Communication Systems | ||
41 | * Competence Center for Advanced Satellite Communications. | ||
42 | * Bugfixes and robustness improvements. | ||
43 | * Filtering on dest MAC addresses, if present (D-Bit = 0) | ||
44 | * ULE_DEBUG compile-time option. | ||
45 | * Apr 2006: cp v3: Bugfixes and compliency with RFC 4326 (ULE) by | ||
46 | * Christian Praehauser <cpraehaus@cosy.sbg.ac.at>, | ||
47 | * Paris Lodron University of Salzburg. | ||
48 | */ | ||
49 | |||
50 | /* | ||
51 | * FIXME / TODO (dvb_net.c): | ||
52 | * | ||
53 | * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero. | ||
54 | * | ||
55 | */ | ||
56 | |||
57 | #include <linux/module.h> | ||
58 | #include <linux/kernel.h> | ||
59 | #include <linux/netdevice.h> | ||
60 | #include <linux/etherdevice.h> | ||
61 | #include <linux/dvb/net.h> | ||
62 | #include <linux/uio.h> | ||
63 | #include <asm/uaccess.h> | ||
64 | #include <linux/crc32.h> | ||
65 | #include <linux/mutex.h> | ||
66 | #include <linux/sched.h> | ||
67 | |||
68 | #include "dvb_demux.h" | ||
69 | #include "dvb_net.h" | ||
70 | |||
71 | static int dvb_net_debug; | ||
72 | module_param(dvb_net_debug, int, 0444); | ||
73 | MODULE_PARM_DESC(dvb_net_debug, "enable debug messages"); | ||
74 | |||
75 | #define dprintk(x...) do { if (dvb_net_debug) printk(x); } while (0) | ||
76 | |||
77 | |||
78 | static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) | ||
79 | { | ||
80 | unsigned int j; | ||
81 | for (j = 0; j < cnt; j++) | ||
82 | c = crc32_be( c, iov[j].iov_base, iov[j].iov_len ); | ||
83 | return c; | ||
84 | } | ||
85 | |||
86 | |||
87 | #define DVB_NET_MULTICAST_MAX 10 | ||
88 | |||
89 | #undef ULE_DEBUG | ||
90 | |||
91 | #ifdef ULE_DEBUG | ||
92 | |||
93 | #define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" | ||
94 | #define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5] | ||
95 | |||
96 | #define isprint(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) | ||
97 | |||
98 | static void hexdump( const unsigned char *buf, unsigned short len ) | ||
99 | { | ||
100 | char str[80], octet[10]; | ||
101 | int ofs, i, l; | ||
102 | |||
103 | for (ofs = 0; ofs < len; ofs += 16) { | ||
104 | sprintf( str, "%03d: ", ofs ); | ||
105 | |||
106 | for (i = 0; i < 16; i++) { | ||
107 | if ((i + ofs) < len) | ||
108 | sprintf( octet, "%02x ", buf[ofs + i] ); | ||
109 | else | ||
110 | strcpy( octet, " " ); | ||
111 | |||
112 | strcat( str, octet ); | ||
113 | } | ||
114 | strcat( str, " " ); | ||
115 | l = strlen( str ); | ||
116 | |||
117 | for (i = 0; (i < 16) && ((i + ofs) < len); i++) | ||
118 | str[l++] = isprint( buf[ofs + i] ) ? buf[ofs + i] : '.'; | ||
119 | |||
120 | str[l] = '\0'; | ||
121 | printk( KERN_WARNING "%s\n", str ); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | #endif | ||
126 | |||
127 | struct dvb_net_priv { | ||
128 | int in_use; | ||
129 | u16 pid; | ||
130 | struct net_device *net; | ||
131 | struct dvb_net *host; | ||
132 | struct dmx_demux *demux; | ||
133 | struct dmx_section_feed *secfeed; | ||
134 | struct dmx_section_filter *secfilter; | ||
135 | struct dmx_ts_feed *tsfeed; | ||
136 | int multi_num; | ||
137 | struct dmx_section_filter *multi_secfilter[DVB_NET_MULTICAST_MAX]; | ||
138 | unsigned char multi_macs[DVB_NET_MULTICAST_MAX][6]; | ||
139 | int rx_mode; | ||
140 | #define RX_MODE_UNI 0 | ||
141 | #define RX_MODE_MULTI 1 | ||
142 | #define RX_MODE_ALL_MULTI 2 | ||
143 | #define RX_MODE_PROMISC 3 | ||
144 | struct work_struct set_multicast_list_wq; | ||
145 | struct work_struct restart_net_feed_wq; | ||
146 | unsigned char feedtype; /* Either FEED_TYPE_ or FEED_TYPE_ULE */ | ||
147 | int need_pusi; /* Set to 1, if synchronization on PUSI required. */ | ||
148 | unsigned char tscc; /* TS continuity counter after sync on PUSI. */ | ||
149 | struct sk_buff *ule_skb; /* ULE SNDU decodes into this buffer. */ | ||
150 | unsigned char *ule_next_hdr; /* Pointer into skb to next ULE extension header. */ | ||
151 | unsigned short ule_sndu_len; /* ULE SNDU length in bytes, w/o D-Bit. */ | ||
152 | unsigned short ule_sndu_type; /* ULE SNDU type field, complete. */ | ||
153 | unsigned char ule_sndu_type_1; /* ULE SNDU type field, if split across 2 TS cells. */ | ||
154 | unsigned char ule_dbit; /* Whether the DestMAC address present | ||
155 | * or not (bit is set). */ | ||
156 | unsigned char ule_bridged; /* Whether the ULE_BRIDGED extension header was found. */ | ||
157 | int ule_sndu_remain; /* Nr. of bytes still required for current ULE SNDU. */ | ||
158 | unsigned long ts_count; /* Current ts cell counter. */ | ||
159 | struct mutex mutex; | ||
160 | }; | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Determine the packet's protocol ID. The rule here is that we | ||
165 | * assume 802.3 if the type field is short enough to be a length. | ||
166 | * This is normal practice and works for any 'now in use' protocol. | ||
167 | * | ||
168 | * stolen from eth.c out of the linux kernel, hacked for dvb-device | ||
169 | * by Michael Holzt <kju@debian.org> | ||
170 | */ | ||
171 | static __be16 dvb_net_eth_type_trans(struct sk_buff *skb, | ||
172 | struct net_device *dev) | ||
173 | { | ||
174 | struct ethhdr *eth; | ||
175 | unsigned char *rawp; | ||
176 | |||
177 | skb_reset_mac_header(skb); | ||
178 | skb_pull(skb,dev->hard_header_len); | ||
179 | eth = eth_hdr(skb); | ||
180 | |||
181 | if (*eth->h_dest & 1) { | ||
182 | if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0) | ||
183 | skb->pkt_type=PACKET_BROADCAST; | ||
184 | else | ||
185 | skb->pkt_type=PACKET_MULTICAST; | ||
186 | } | ||
187 | |||
188 | if (ntohs(eth->h_proto) >= 1536) | ||
189 | return eth->h_proto; | ||
190 | |||
191 | rawp = skb->data; | ||
192 | |||
193 | /** | ||
194 | * This is a magic hack to spot IPX packets. Older Novell breaks | ||
195 | * the protocol design and runs IPX over 802.3 without an 802.2 LLC | ||
196 | * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This | ||
197 | * won't work for fault tolerant netware but does for the rest. | ||
198 | */ | ||
199 | if (*(unsigned short *)rawp == 0xFFFF) | ||
200 | return htons(ETH_P_802_3); | ||
201 | |||
202 | /** | ||
203 | * Real 802.2 LLC | ||
204 | */ | ||
205 | return htons(ETH_P_802_2); | ||
206 | } | ||
207 | |||
208 | #define TS_SZ 188 | ||
209 | #define TS_SYNC 0x47 | ||
210 | #define TS_TEI 0x80 | ||
211 | #define TS_SC 0xC0 | ||
212 | #define TS_PUSI 0x40 | ||
213 | #define TS_AF_A 0x20 | ||
214 | #define TS_AF_D 0x10 | ||
215 | |||
216 | /* ULE Extension Header handlers. */ | ||
217 | |||
218 | #define ULE_TEST 0 | ||
219 | #define ULE_BRIDGED 1 | ||
220 | |||
221 | #define ULE_OPTEXTHDR_PADDING 0 | ||
222 | |||
223 | static int ule_test_sndu( struct dvb_net_priv *p ) | ||
224 | { | ||
225 | return -1; | ||
226 | } | ||
227 | |||
228 | static int ule_bridged_sndu( struct dvb_net_priv *p ) | ||
229 | { | ||
230 | struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr; | ||
231 | if(ntohs(hdr->h_proto) < 1536) { | ||
232 | int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data); | ||
233 | /* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */ | ||
234 | if(framelen != ntohs(hdr->h_proto)) { | ||
235 | return -1; | ||
236 | } | ||
237 | } | ||
238 | /* Note: | ||
239 | * From RFC4326: | ||
240 | * "A bridged SNDU is a Mandatory Extension Header of Type 1. | ||
241 | * It must be the final (or only) extension header specified in the header chain of a SNDU." | ||
242 | * The 'ule_bridged' flag will cause the extension header processing loop to terminate. | ||
243 | */ | ||
244 | p->ule_bridged = 1; | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int ule_exthdr_padding(struct dvb_net_priv *p) | ||
249 | { | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | /** Handle ULE extension headers. | ||
254 | * Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding. | ||
255 | * Returns: >= 0: nr. of bytes consumed by next extension header | ||
256 | * -1: Mandatory extension header that is not recognized or TEST SNDU; discard. | ||
257 | */ | ||
258 | static int handle_one_ule_extension( struct dvb_net_priv *p ) | ||
259 | { | ||
260 | /* Table of mandatory extension header handlers. The header type is the index. */ | ||
261 | static int (*ule_mandatory_ext_handlers[255])( struct dvb_net_priv *p ) = | ||
262 | { [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL, }; | ||
263 | |||
264 | /* Table of optional extension header handlers. The header type is the index. */ | ||
265 | static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = | ||
266 | { [0] = ule_exthdr_padding, [1] = NULL, }; | ||
267 | |||
268 | int ext_len = 0; | ||
269 | unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8; | ||
270 | unsigned char htype = p->ule_sndu_type & 0x00FF; | ||
271 | |||
272 | /* Discriminate mandatory and optional extension headers. */ | ||
273 | if (hlen == 0) { | ||
274 | /* Mandatory extension header */ | ||
275 | if (ule_mandatory_ext_handlers[htype]) { | ||
276 | ext_len = ule_mandatory_ext_handlers[htype]( p ); | ||
277 | if(ext_len >= 0) { | ||
278 | p->ule_next_hdr += ext_len; | ||
279 | if (!p->ule_bridged) { | ||
280 | p->ule_sndu_type = ntohs(*(__be16 *)p->ule_next_hdr); | ||
281 | p->ule_next_hdr += 2; | ||
282 | } else { | ||
283 | p->ule_sndu_type = ntohs(*(__be16 *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN))); | ||
284 | /* This assures the extension handling loop will terminate. */ | ||
285 | } | ||
286 | } | ||
287 | // else: extension handler failed or SNDU should be discarded | ||
288 | } else | ||
289 | ext_len = -1; /* SNDU has to be discarded. */ | ||
290 | } else { | ||
291 | /* Optional extension header. Calculate the length. */ | ||
292 | ext_len = hlen << 1; | ||
293 | /* Process the optional extension header according to its type. */ | ||
294 | if (ule_optional_ext_handlers[htype]) | ||
295 | (void)ule_optional_ext_handlers[htype]( p ); | ||
296 | p->ule_next_hdr += ext_len; | ||
297 | p->ule_sndu_type = ntohs( *(__be16 *)(p->ule_next_hdr-2) ); | ||
298 | /* | ||
299 | * note: the length of the next header type is included in the | ||
300 | * length of THIS optional extension header | ||
301 | */ | ||
302 | } | ||
303 | |||
304 | return ext_len; | ||
305 | } | ||
306 | |||
307 | static int handle_ule_extensions( struct dvb_net_priv *p ) | ||
308 | { | ||
309 | int total_ext_len = 0, l; | ||
310 | |||
311 | p->ule_next_hdr = p->ule_skb->data; | ||
312 | do { | ||
313 | l = handle_one_ule_extension( p ); | ||
314 | if (l < 0) | ||
315 | return l; /* Stop extension header processing and discard SNDU. */ | ||
316 | total_ext_len += l; | ||
317 | #ifdef ULE_DEBUG | ||
318 | dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, " | ||
319 | "l=%i, total_ext_len=%i\n", p->ule_next_hdr, | ||
320 | (int) p->ule_sndu_type, l, total_ext_len); | ||
321 | #endif | ||
322 | |||
323 | } while (p->ule_sndu_type < 1536); | ||
324 | |||
325 | return total_ext_len; | ||
326 | } | ||
327 | |||
328 | |||
329 | /** Prepare for a new ULE SNDU: reset the decoder state. */ | ||
330 | static inline void reset_ule( struct dvb_net_priv *p ) | ||
331 | { | ||
332 | p->ule_skb = NULL; | ||
333 | p->ule_next_hdr = NULL; | ||
334 | p->ule_sndu_len = 0; | ||
335 | p->ule_sndu_type = 0; | ||
336 | p->ule_sndu_type_1 = 0; | ||
337 | p->ule_sndu_remain = 0; | ||
338 | p->ule_dbit = 0xFF; | ||
339 | p->ule_bridged = 0; | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * Decode ULE SNDUs according to draft-ietf-ipdvb-ule-03.txt from a sequence of | ||
344 | * TS cells of a single PID. | ||
345 | */ | ||
346 | static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | ||
347 | { | ||
348 | struct dvb_net_priv *priv = netdev_priv(dev); | ||
349 | unsigned long skipped = 0L; | ||
350 | const u8 *ts, *ts_end, *from_where = NULL; | ||
351 | u8 ts_remain = 0, how_much = 0, new_ts = 1; | ||
352 | struct ethhdr *ethh = NULL; | ||
353 | bool error = false; | ||
354 | |||
355 | #ifdef ULE_DEBUG | ||
356 | /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ | ||
357 | static unsigned char ule_hist[100*TS_SZ]; | ||
358 | static unsigned char *ule_where = ule_hist, ule_dump; | ||
359 | #endif | ||
360 | |||
361 | /* For all TS cells in current buffer. | ||
362 | * Appearently, we are called for every single TS cell. | ||
363 | */ | ||
364 | for (ts = buf, ts_end = buf + buf_len; ts < ts_end; /* no default incr. */ ) { | ||
365 | |||
366 | if (new_ts) { | ||
367 | /* We are about to process a new TS cell. */ | ||
368 | |||
369 | #ifdef ULE_DEBUG | ||
370 | if (ule_where >= &ule_hist[100*TS_SZ]) ule_where = ule_hist; | ||
371 | memcpy( ule_where, ts, TS_SZ ); | ||
372 | if (ule_dump) { | ||
373 | hexdump( ule_where, TS_SZ ); | ||
374 | ule_dump = 0; | ||
375 | } | ||
376 | ule_where += TS_SZ; | ||
377 | #endif | ||
378 | |||
379 | /* Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control . */ | ||
380 | if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI) || ((ts[3] & TS_SC) != 0)) { | ||
381 | printk(KERN_WARNING "%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n", | ||
382 | priv->ts_count, ts[0], ts[1] & TS_TEI >> 7, ts[3] & 0xC0 >> 6); | ||
383 | |||
384 | /* Drop partly decoded SNDU, reset state, resync on PUSI. */ | ||
385 | if (priv->ule_skb) { | ||
386 | dev_kfree_skb( priv->ule_skb ); | ||
387 | /* Prepare for next SNDU. */ | ||
388 | dev->stats.rx_errors++; | ||
389 | dev->stats.rx_frame_errors++; | ||
390 | } | ||
391 | reset_ule(priv); | ||
392 | priv->need_pusi = 1; | ||
393 | |||
394 | /* Continue with next TS cell. */ | ||
395 | ts += TS_SZ; | ||
396 | priv->ts_count++; | ||
397 | continue; | ||
398 | } | ||
399 | |||
400 | ts_remain = 184; | ||
401 | from_where = ts + 4; | ||
402 | } | ||
403 | /* Synchronize on PUSI, if required. */ | ||
404 | if (priv->need_pusi) { | ||
405 | if (ts[1] & TS_PUSI) { | ||
406 | /* Find beginning of first ULE SNDU in current TS cell. */ | ||
407 | /* Synchronize continuity counter. */ | ||
408 | priv->tscc = ts[3] & 0x0F; | ||
409 | /* There is a pointer field here. */ | ||
410 | if (ts[4] > ts_remain) { | ||
411 | printk(KERN_ERR "%lu: Invalid ULE packet " | ||
412 | "(pointer field %d)\n", priv->ts_count, ts[4]); | ||
413 | ts += TS_SZ; | ||
414 | priv->ts_count++; | ||
415 | continue; | ||
416 | } | ||
417 | /* Skip to destination of pointer field. */ | ||
418 | from_where = &ts[5] + ts[4]; | ||
419 | ts_remain -= 1 + ts[4]; | ||
420 | skipped = 0; | ||
421 | } else { | ||
422 | skipped++; | ||
423 | ts += TS_SZ; | ||
424 | priv->ts_count++; | ||
425 | continue; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | if (new_ts) { | ||
430 | /* Check continuity counter. */ | ||
431 | if ((ts[3] & 0x0F) == priv->tscc) | ||
432 | priv->tscc = (priv->tscc + 1) & 0x0F; | ||
433 | else { | ||
434 | /* TS discontinuity handling: */ | ||
435 | printk(KERN_WARNING "%lu: TS discontinuity: got %#x, " | ||
436 | "expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc); | ||
437 | /* Drop partly decoded SNDU, reset state, resync on PUSI. */ | ||
438 | if (priv->ule_skb) { | ||
439 | dev_kfree_skb( priv->ule_skb ); | ||
440 | /* Prepare for next SNDU. */ | ||
441 | // reset_ule(priv); moved to below. | ||
442 | dev->stats.rx_errors++; | ||
443 | dev->stats.rx_frame_errors++; | ||
444 | } | ||
445 | reset_ule(priv); | ||
446 | /* skip to next PUSI. */ | ||
447 | priv->need_pusi = 1; | ||
448 | continue; | ||
449 | } | ||
450 | /* If we still have an incomplete payload, but PUSI is | ||
451 | * set; some TS cells are missing. | ||
452 | * This is only possible here, if we missed exactly 16 TS | ||
453 | * cells (continuity counter wrap). */ | ||
454 | if (ts[1] & TS_PUSI) { | ||
455 | if (! priv->need_pusi) { | ||
456 | if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) { | ||
457 | /* Pointer field is invalid. Drop this TS cell and any started ULE SNDU. */ | ||
458 | printk(KERN_WARNING "%lu: Invalid pointer " | ||
459 | "field: %u.\n", priv->ts_count, *from_where); | ||
460 | |||
461 | /* Drop partly decoded SNDU, reset state, resync on PUSI. */ | ||
462 | if (priv->ule_skb) { | ||
463 | error = true; | ||
464 | dev_kfree_skb(priv->ule_skb); | ||
465 | } | ||
466 | |||
467 | if (error || priv->ule_sndu_remain) { | ||
468 | dev->stats.rx_errors++; | ||
469 | dev->stats.rx_frame_errors++; | ||
470 | error = false; | ||
471 | } | ||
472 | |||
473 | reset_ule(priv); | ||
474 | priv->need_pusi = 1; | ||
475 | continue; | ||
476 | } | ||
477 | /* Skip pointer field (we're processing a | ||
478 | * packed payload). */ | ||
479 | from_where += 1; | ||
480 | ts_remain -= 1; | ||
481 | } else | ||
482 | priv->need_pusi = 0; | ||
483 | |||
484 | if (priv->ule_sndu_remain > 183) { | ||
485 | /* Current SNDU lacks more data than there could be available in the | ||
486 | * current TS cell. */ | ||
487 | dev->stats.rx_errors++; | ||
488 | dev->stats.rx_length_errors++; | ||
489 | printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but " | ||
490 | "got PUSI (pf %d, ts_remain %d). Flushing incomplete payload.\n", | ||
491 | priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain); | ||
492 | dev_kfree_skb(priv->ule_skb); | ||
493 | /* Prepare for next SNDU. */ | ||
494 | reset_ule(priv); | ||
495 | /* Resync: go to where pointer field points to: start of next ULE SNDU. */ | ||
496 | from_where += ts[4]; | ||
497 | ts_remain -= ts[4]; | ||
498 | } | ||
499 | } | ||
500 | } | ||
501 | |||
502 | /* Check if new payload needs to be started. */ | ||
503 | if (priv->ule_skb == NULL) { | ||
504 | /* Start a new payload with skb. | ||
505 | * Find ULE header. It is only guaranteed that the | ||
506 | * length field (2 bytes) is contained in the current | ||
507 | * TS. | ||
508 | * Check ts_remain has to be >= 2 here. */ | ||
509 | if (ts_remain < 2) { | ||
510 | printk(KERN_WARNING "Invalid payload packing: only %d " | ||
511 | "bytes left in TS. Resyncing.\n", ts_remain); | ||
512 | priv->ule_sndu_len = 0; | ||
513 | priv->need_pusi = 1; | ||
514 | ts += TS_SZ; | ||
515 | continue; | ||
516 | } | ||
517 | |||
518 | if (! priv->ule_sndu_len) { | ||
519 | /* Got at least two bytes, thus extrace the SNDU length. */ | ||
520 | priv->ule_sndu_len = from_where[0] << 8 | from_where[1]; | ||
521 | if (priv->ule_sndu_len & 0x8000) { | ||
522 | /* D-Bit is set: no dest mac present. */ | ||
523 | priv->ule_sndu_len &= 0x7FFF; | ||
524 | priv->ule_dbit = 1; | ||
525 | } else | ||
526 | priv->ule_dbit = 0; | ||
527 | |||
528 | if (priv->ule_sndu_len < 5) { | ||
529 | printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. " | ||
530 | "Resyncing.\n", priv->ts_count, priv->ule_sndu_len); | ||
531 | dev->stats.rx_errors++; | ||
532 | dev->stats.rx_length_errors++; | ||
533 | priv->ule_sndu_len = 0; | ||
534 | priv->need_pusi = 1; | ||
535 | new_ts = 1; | ||
536 | ts += TS_SZ; | ||
537 | priv->ts_count++; | ||
538 | continue; | ||
539 | } | ||
540 | ts_remain -= 2; /* consume the 2 bytes SNDU length. */ | ||
541 | from_where += 2; | ||
542 | } | ||
543 | |||
544 | priv->ule_sndu_remain = priv->ule_sndu_len + 2; | ||
545 | /* | ||
546 | * State of current TS: | ||
547 | * ts_remain (remaining bytes in the current TS cell) | ||
548 | * 0 ule_type is not available now, we need the next TS cell | ||
549 | * 1 the first byte of the ule_type is present | ||
550 | * >=2 full ULE header present, maybe some payload data as well. | ||
551 | */ | ||
552 | switch (ts_remain) { | ||
553 | case 1: | ||
554 | priv->ule_sndu_remain--; | ||
555 | priv->ule_sndu_type = from_where[0] << 8; | ||
556 | priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */ | ||
557 | ts_remain -= 1; from_where += 1; | ||
558 | /* Continue w/ next TS. */ | ||
559 | case 0: | ||
560 | new_ts = 1; | ||
561 | ts += TS_SZ; | ||
562 | priv->ts_count++; | ||
563 | continue; | ||
564 | |||
565 | default: /* complete ULE header is present in current TS. */ | ||
566 | /* Extract ULE type field. */ | ||
567 | if (priv->ule_sndu_type_1) { | ||
568 | priv->ule_sndu_type_1 = 0; | ||
569 | priv->ule_sndu_type |= from_where[0]; | ||
570 | from_where += 1; /* points to payload start. */ | ||
571 | ts_remain -= 1; | ||
572 | } else { | ||
573 | /* Complete type is present in new TS. */ | ||
574 | priv->ule_sndu_type = from_where[0] << 8 | from_where[1]; | ||
575 | from_where += 2; /* points to payload start. */ | ||
576 | ts_remain -= 2; | ||
577 | } | ||
578 | break; | ||
579 | } | ||
580 | |||
581 | /* Allocate the skb (decoder target buffer) with the correct size, as follows: | ||
582 | * prepare for the largest case: bridged SNDU with MAC address (dbit = 0). */ | ||
583 | priv->ule_skb = dev_alloc_skb( priv->ule_sndu_len + ETH_HLEN + ETH_ALEN ); | ||
584 | if (priv->ule_skb == NULL) { | ||
585 | printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", | ||
586 | dev->name); | ||
587 | dev->stats.rx_dropped++; | ||
588 | return; | ||
589 | } | ||
590 | |||
591 | /* This includes the CRC32 _and_ dest mac, if !dbit. */ | ||
592 | priv->ule_sndu_remain = priv->ule_sndu_len; | ||
593 | priv->ule_skb->dev = dev; | ||
594 | /* Leave space for Ethernet or bridged SNDU header (eth hdr plus one MAC addr). */ | ||
595 | skb_reserve( priv->ule_skb, ETH_HLEN + ETH_ALEN ); | ||
596 | } | ||
597 | |||
598 | /* Copy data into our current skb. */ | ||
599 | how_much = min(priv->ule_sndu_remain, (int)ts_remain); | ||
600 | memcpy(skb_put(priv->ule_skb, how_much), from_where, how_much); | ||
601 | priv->ule_sndu_remain -= how_much; | ||
602 | ts_remain -= how_much; | ||
603 | from_where += how_much; | ||
604 | |||
605 | /* Check for complete payload. */ | ||
606 | if (priv->ule_sndu_remain <= 0) { | ||
607 | /* Check CRC32, we've got it in our skb already. */ | ||
608 | __be16 ulen = htons(priv->ule_sndu_len); | ||
609 | __be16 utype = htons(priv->ule_sndu_type); | ||
610 | const u8 *tail; | ||
611 | struct kvec iov[3] = { | ||
612 | { &ulen, sizeof ulen }, | ||
613 | { &utype, sizeof utype }, | ||
614 | { priv->ule_skb->data, priv->ule_skb->len - 4 } | ||
615 | }; | ||
616 | u32 ule_crc = ~0L, expected_crc; | ||
617 | if (priv->ule_dbit) { | ||
618 | /* Set D-bit for CRC32 verification, | ||
619 | * if it was set originally. */ | ||
620 | ulen |= htons(0x8000); | ||
621 | } | ||
622 | |||
623 | ule_crc = iov_crc32(ule_crc, iov, 3); | ||
624 | tail = skb_tail_pointer(priv->ule_skb); | ||
625 | expected_crc = *(tail - 4) << 24 | | ||
626 | *(tail - 3) << 16 | | ||
627 | *(tail - 2) << 8 | | ||
628 | *(tail - 1); | ||
629 | if (ule_crc != expected_crc) { | ||
630 | printk(KERN_WARNING "%lu: CRC32 check FAILED: %08x / %08x, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n", | ||
631 | priv->ts_count, ule_crc, expected_crc, priv->ule_sndu_len, priv->ule_sndu_type, ts_remain, ts_remain > 2 ? *(unsigned short *)from_where : 0); | ||
632 | |||
633 | #ifdef ULE_DEBUG | ||
634 | hexdump( iov[0].iov_base, iov[0].iov_len ); | ||
635 | hexdump( iov[1].iov_base, iov[1].iov_len ); | ||
636 | hexdump( iov[2].iov_base, iov[2].iov_len ); | ||
637 | |||
638 | if (ule_where == ule_hist) { | ||
639 | hexdump( &ule_hist[98*TS_SZ], TS_SZ ); | ||
640 | hexdump( &ule_hist[99*TS_SZ], TS_SZ ); | ||
641 | } else if (ule_where == &ule_hist[TS_SZ]) { | ||
642 | hexdump( &ule_hist[99*TS_SZ], TS_SZ ); | ||
643 | hexdump( ule_hist, TS_SZ ); | ||
644 | } else { | ||
645 | hexdump( ule_where - TS_SZ - TS_SZ, TS_SZ ); | ||
646 | hexdump( ule_where - TS_SZ, TS_SZ ); | ||
647 | } | ||
648 | ule_dump = 1; | ||
649 | #endif | ||
650 | |||
651 | dev->stats.rx_errors++; | ||
652 | dev->stats.rx_crc_errors++; | ||
653 | dev_kfree_skb(priv->ule_skb); | ||
654 | } else { | ||
655 | /* CRC32 verified OK. */ | ||
656 | u8 dest_addr[ETH_ALEN]; | ||
657 | static const u8 bc_addr[ETH_ALEN] = | ||
658 | { [ 0 ... ETH_ALEN-1] = 0xff }; | ||
659 | |||
660 | /* CRC32 was OK. Remove it from skb. */ | ||
661 | priv->ule_skb->tail -= 4; | ||
662 | priv->ule_skb->len -= 4; | ||
663 | |||
664 | if (!priv->ule_dbit) { | ||
665 | /* | ||
666 | * The destination MAC address is the | ||
667 | * next data in the skb. It comes | ||
668 | * before any extension headers. | ||
669 | * | ||
670 | * Check if the payload of this SNDU | ||
671 | * should be passed up the stack. | ||
672 | */ | ||
673 | register int drop = 0; | ||
674 | if (priv->rx_mode != RX_MODE_PROMISC) { | ||
675 | if (priv->ule_skb->data[0] & 0x01) { | ||
676 | /* multicast or broadcast */ | ||
677 | if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) { | ||
678 | /* multicast */ | ||
679 | if (priv->rx_mode == RX_MODE_MULTI) { | ||
680 | int i; | ||
681 | for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++) | ||
682 | ; | ||
683 | if (i == priv->multi_num) | ||
684 | drop = 1; | ||
685 | } else if (priv->rx_mode != RX_MODE_ALL_MULTI) | ||
686 | drop = 1; /* no broadcast; */ | ||
687 | /* else: all multicast mode: accept all multicast packets */ | ||
688 | } | ||
689 | /* else: broadcast */ | ||
690 | } | ||
691 | else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN)) | ||
692 | drop = 1; | ||
693 | /* else: destination address matches the MAC address of our receiver device */ | ||
694 | } | ||
695 | /* else: promiscuous mode; pass everything up the stack */ | ||
696 | |||
697 | if (drop) { | ||
698 | #ifdef ULE_DEBUG | ||
699 | dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n", | ||
700 | MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr)); | ||
701 | #endif | ||
702 | dev_kfree_skb(priv->ule_skb); | ||
703 | goto sndu_done; | ||
704 | } | ||
705 | else | ||
706 | { | ||
707 | skb_copy_from_linear_data(priv->ule_skb, | ||
708 | dest_addr, | ||
709 | ETH_ALEN); | ||
710 | skb_pull(priv->ule_skb, ETH_ALEN); | ||
711 | } | ||
712 | } | ||
713 | |||
714 | /* Handle ULE Extension Headers. */ | ||
715 | if (priv->ule_sndu_type < 1536) { | ||
716 | /* There is an extension header. Handle it accordingly. */ | ||
717 | int l = handle_ule_extensions(priv); | ||
718 | if (l < 0) { | ||
719 | /* Mandatory extension header unknown or TEST SNDU. Drop it. */ | ||
720 | // printk( KERN_WARNING "Dropping SNDU, extension headers.\n" ); | ||
721 | dev_kfree_skb(priv->ule_skb); | ||
722 | goto sndu_done; | ||
723 | } | ||
724 | skb_pull(priv->ule_skb, l); | ||
725 | } | ||
726 | |||
727 | /* | ||
728 | * Construct/assure correct ethernet header. | ||
729 | * Note: in bridged mode (priv->ule_bridged != | ||
730 | * 0) we already have the (original) ethernet | ||
731 | * header at the start of the payload (after | ||
732 | * optional dest. address and any extension | ||
733 | * headers). | ||
734 | */ | ||
735 | |||
736 | if (!priv->ule_bridged) { | ||
737 | skb_push(priv->ule_skb, ETH_HLEN); | ||
738 | ethh = (struct ethhdr *)priv->ule_skb->data; | ||
739 | if (!priv->ule_dbit) { | ||
740 | /* dest_addr buffer is only valid if priv->ule_dbit == 0 */ | ||
741 | memcpy(ethh->h_dest, dest_addr, ETH_ALEN); | ||
742 | memset(ethh->h_source, 0, ETH_ALEN); | ||
743 | } | ||
744 | else /* zeroize source and dest */ | ||
745 | memset( ethh, 0, ETH_ALEN*2 ); | ||
746 | |||
747 | ethh->h_proto = htons(priv->ule_sndu_type); | ||
748 | } | ||
749 | /* else: skb is in correct state; nothing to do. */ | ||
750 | priv->ule_bridged = 0; | ||
751 | |||
752 | /* Stuff into kernel's protocol stack. */ | ||
753 | priv->ule_skb->protocol = dvb_net_eth_type_trans(priv->ule_skb, dev); | ||
754 | /* If D-bit is set (i.e. destination MAC address not present), | ||
755 | * receive the packet anyhow. */ | ||
756 | /* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) | ||
757 | priv->ule_skb->pkt_type = PACKET_HOST; */ | ||
758 | dev->stats.rx_packets++; | ||
759 | dev->stats.rx_bytes += priv->ule_skb->len; | ||
760 | netif_rx(priv->ule_skb); | ||
761 | } | ||
762 | sndu_done: | ||
763 | /* Prepare for next SNDU. */ | ||
764 | reset_ule(priv); | ||
765 | } | ||
766 | |||
767 | /* More data in current TS (look at the bytes following the CRC32)? */ | ||
768 | if (ts_remain >= 2 && *((unsigned short *)from_where) != 0xFFFF) { | ||
769 | /* Next ULE SNDU starts right there. */ | ||
770 | new_ts = 0; | ||
771 | priv->ule_skb = NULL; | ||
772 | priv->ule_sndu_type_1 = 0; | ||
773 | priv->ule_sndu_len = 0; | ||
774 | // printk(KERN_WARNING "More data in current TS: [%#x %#x %#x %#x]\n", | ||
775 | // *(from_where + 0), *(from_where + 1), | ||
776 | // *(from_where + 2), *(from_where + 3)); | ||
777 | // printk(KERN_WARNING "ts @ %p, stopped @ %p:\n", ts, from_where + 0); | ||
778 | // hexdump(ts, 188); | ||
779 | } else { | ||
780 | new_ts = 1; | ||
781 | ts += TS_SZ; | ||
782 | priv->ts_count++; | ||
783 | if (priv->ule_skb == NULL) { | ||
784 | priv->need_pusi = 1; | ||
785 | priv->ule_sndu_type_1 = 0; | ||
786 | priv->ule_sndu_len = 0; | ||
787 | } | ||
788 | } | ||
789 | } /* for all available TS cells */ | ||
790 | } | ||
791 | |||
792 | static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len, | ||
793 | const u8 *buffer2, size_t buffer2_len, | ||
794 | struct dmx_ts_feed *feed, enum dmx_success success) | ||
795 | { | ||
796 | struct net_device *dev = feed->priv; | ||
797 | |||
798 | if (buffer2) | ||
799 | printk(KERN_WARNING "buffer2 not NULL: %p.\n", buffer2); | ||
800 | if (buffer1_len > 32768) | ||
801 | printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len); | ||
802 | /* printk("TS callback: %u bytes, %u TS cells @ %p.\n", | ||
803 | buffer1_len, buffer1_len / TS_SZ, buffer1); */ | ||
804 | dvb_net_ule(dev, buffer1, buffer1_len); | ||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | |||
809 | static void dvb_net_sec(struct net_device *dev, | ||
810 | const u8 *pkt, int pkt_len) | ||
811 | { | ||
812 | u8 *eth; | ||
813 | struct sk_buff *skb; | ||
814 | struct net_device_stats *stats = &dev->stats; | ||
815 | int snap = 0; | ||
816 | |||
817 | /* note: pkt_len includes a 32bit checksum */ | ||
818 | if (pkt_len < 16) { | ||
819 | printk("%s: IP/MPE packet length = %d too small.\n", | ||
820 | dev->name, pkt_len); | ||
821 | stats->rx_errors++; | ||
822 | stats->rx_length_errors++; | ||
823 | return; | ||
824 | } | ||
825 | /* it seems some ISPs manage to screw up here, so we have to | ||
826 | * relax the error checks... */ | ||
827 | #if 0 | ||
828 | if ((pkt[5] & 0xfd) != 0xc1) { | ||
829 | /* drop scrambled or broken packets */ | ||
830 | #else | ||
831 | if ((pkt[5] & 0x3c) != 0x00) { | ||
832 | /* drop scrambled */ | ||
833 | #endif | ||
834 | stats->rx_errors++; | ||
835 | stats->rx_crc_errors++; | ||
836 | return; | ||
837 | } | ||
838 | if (pkt[5] & 0x02) { | ||
839 | /* handle LLC/SNAP, see rfc-1042 */ | ||
840 | if (pkt_len < 24 || memcmp(&pkt[12], "\xaa\xaa\x03\0\0\0", 6)) { | ||
841 | stats->rx_dropped++; | ||
842 | return; | ||
843 | } | ||
844 | snap = 8; | ||
845 | } | ||
846 | if (pkt[7]) { | ||
847 | /* FIXME: assemble datagram from multiple sections */ | ||
848 | stats->rx_errors++; | ||
849 | stats->rx_frame_errors++; | ||
850 | return; | ||
851 | } | ||
852 | |||
853 | /* we have 14 byte ethernet header (ip header follows); | ||
854 | * 12 byte MPE header; 4 byte checksum; + 2 byte alignment, 8 byte LLC/SNAP | ||
855 | */ | ||
856 | if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2 - snap))) { | ||
857 | //printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); | ||
858 | stats->rx_dropped++; | ||
859 | return; | ||
860 | } | ||
861 | skb_reserve(skb, 2); /* longword align L3 header */ | ||
862 | skb->dev = dev; | ||
863 | |||
864 | /* copy L3 payload */ | ||
865 | eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14 - snap); | ||
866 | memcpy(eth + 14, pkt + 12 + snap, pkt_len - 12 - 4 - snap); | ||
867 | |||
868 | /* create ethernet header: */ | ||
869 | eth[0]=pkt[0x0b]; | ||
870 | eth[1]=pkt[0x0a]; | ||
871 | eth[2]=pkt[0x09]; | ||
872 | eth[3]=pkt[0x08]; | ||
873 | eth[4]=pkt[0x04]; | ||
874 | eth[5]=pkt[0x03]; | ||
875 | |||
876 | eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0; | ||
877 | |||
878 | if (snap) { | ||
879 | eth[12] = pkt[18]; | ||
880 | eth[13] = pkt[19]; | ||
881 | } else { | ||
882 | /* protocol numbers are from rfc-1700 or | ||
883 | * http://www.iana.org/assignments/ethernet-numbers | ||
884 | */ | ||
885 | if (pkt[12] >> 4 == 6) { /* version field from IP header */ | ||
886 | eth[12] = 0x86; /* IPv6 */ | ||
887 | eth[13] = 0xdd; | ||
888 | } else { | ||
889 | eth[12] = 0x08; /* IPv4 */ | ||
890 | eth[13] = 0x00; | ||
891 | } | ||
892 | } | ||
893 | |||
894 | skb->protocol = dvb_net_eth_type_trans(skb, dev); | ||
895 | |||
896 | stats->rx_packets++; | ||
897 | stats->rx_bytes+=skb->len; | ||
898 | netif_rx(skb); | ||
899 | } | ||
900 | |||
901 | static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len, | ||
902 | const u8 *buffer2, size_t buffer2_len, | ||
903 | struct dmx_section_filter *filter, | ||
904 | enum dmx_success success) | ||
905 | { | ||
906 | struct net_device *dev = filter->priv; | ||
907 | |||
908 | /** | ||
909 | * we rely on the DVB API definition where exactly one complete | ||
910 | * section is delivered in buffer1 | ||
911 | */ | ||
912 | dvb_net_sec (dev, buffer1, buffer1_len); | ||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev) | ||
917 | { | ||
918 | dev_kfree_skb(skb); | ||
919 | return NETDEV_TX_OK; | ||
920 | } | ||
921 | |||
922 | static u8 mask_normal[6]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
923 | static u8 mask_allmulti[6]={0xff, 0xff, 0xff, 0x00, 0x00, 0x00}; | ||
924 | static u8 mac_allmulti[6]={0x01, 0x00, 0x5e, 0x00, 0x00, 0x00}; | ||
925 | static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
926 | |||
927 | static int dvb_net_filter_sec_set(struct net_device *dev, | ||
928 | struct dmx_section_filter **secfilter, | ||
929 | u8 *mac, u8 *mac_mask) | ||
930 | { | ||
931 | struct dvb_net_priv *priv = netdev_priv(dev); | ||
932 | int ret; | ||
933 | |||
934 | *secfilter=NULL; | ||
935 | ret = priv->secfeed->allocate_filter(priv->secfeed, secfilter); | ||
936 | if (ret<0) { | ||
937 | printk("%s: could not get filter\n", dev->name); | ||
938 | return ret; | ||
939 | } | ||
940 | |||
941 | (*secfilter)->priv=(void *) dev; | ||
942 | |||
943 | memset((*secfilter)->filter_value, 0x00, DMX_MAX_FILTER_SIZE); | ||
944 | memset((*secfilter)->filter_mask, 0x00, DMX_MAX_FILTER_SIZE); | ||
945 | memset((*secfilter)->filter_mode, 0xff, DMX_MAX_FILTER_SIZE); | ||
946 | |||
947 | (*secfilter)->filter_value[0]=0x3e; | ||
948 | (*secfilter)->filter_value[3]=mac[5]; | ||
949 | (*secfilter)->filter_value[4]=mac[4]; | ||
950 | (*secfilter)->filter_value[8]=mac[3]; | ||
951 | (*secfilter)->filter_value[9]=mac[2]; | ||
952 | (*secfilter)->filter_value[10]=mac[1]; | ||
953 | (*secfilter)->filter_value[11]=mac[0]; | ||
954 | |||
955 | (*secfilter)->filter_mask[0] = 0xff; | ||
956 | (*secfilter)->filter_mask[3] = mac_mask[5]; | ||
957 | (*secfilter)->filter_mask[4] = mac_mask[4]; | ||
958 | (*secfilter)->filter_mask[8] = mac_mask[3]; | ||
959 | (*secfilter)->filter_mask[9] = mac_mask[2]; | ||
960 | (*secfilter)->filter_mask[10] = mac_mask[1]; | ||
961 | (*secfilter)->filter_mask[11]=mac_mask[0]; | ||
962 | |||
963 | dprintk("%s: filter mac=%pM\n", dev->name, mac); | ||
964 | dprintk("%s: filter mask=%pM\n", dev->name, mac_mask); | ||
965 | |||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | static int dvb_net_feed_start(struct net_device *dev) | ||
970 | { | ||
971 | int ret = 0, i; | ||
972 | struct dvb_net_priv *priv = netdev_priv(dev); | ||
973 | struct dmx_demux *demux = priv->demux; | ||
974 | unsigned char *mac = (unsigned char *) dev->dev_addr; | ||
975 | |||
976 | dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode); | ||
977 | mutex_lock(&priv->mutex); | ||
978 | if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) | ||
979 | printk("%s: BUG %d\n", __func__, __LINE__); | ||
980 | |||
981 | priv->secfeed=NULL; | ||
982 | priv->secfilter=NULL; | ||
983 | priv->tsfeed = NULL; | ||
984 | |||
985 | if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) { | ||
986 | dprintk("%s: alloc secfeed\n", __func__); | ||
987 | ret=demux->allocate_section_feed(demux, &priv->secfeed, | ||
988 | dvb_net_sec_callback); | ||
989 | if (ret<0) { | ||
990 | printk("%s: could not allocate section feed\n", dev->name); | ||
991 | goto error; | ||
992 | } | ||
993 | |||
994 | ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1); | ||
995 | |||
996 | if (ret<0) { | ||
997 | printk("%s: could not set section feed\n", dev->name); | ||
998 | priv->demux->release_section_feed(priv->demux, priv->secfeed); | ||
999 | priv->secfeed=NULL; | ||
1000 | goto error; | ||
1001 | } | ||
1002 | |||
1003 | if (priv->rx_mode != RX_MODE_PROMISC) { | ||
1004 | dprintk("%s: set secfilter\n", __func__); | ||
1005 | dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal); | ||
1006 | } | ||
1007 | |||
1008 | switch (priv->rx_mode) { | ||
1009 | case RX_MODE_MULTI: | ||
1010 | for (i = 0; i < priv->multi_num; i++) { | ||
1011 | dprintk("%s: set multi_secfilter[%d]\n", __func__, i); | ||
1012 | dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i], | ||
1013 | priv->multi_macs[i], mask_normal); | ||
1014 | } | ||
1015 | break; | ||
1016 | case RX_MODE_ALL_MULTI: | ||
1017 | priv->multi_num=1; | ||
1018 | dprintk("%s: set multi_secfilter[0]\n", __func__); | ||
1019 | dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0], | ||
1020 | mac_allmulti, mask_allmulti); | ||
1021 | break; | ||
1022 | case RX_MODE_PROMISC: | ||
1023 | priv->multi_num=0; | ||
1024 | dprintk("%s: set secfilter\n", __func__); | ||
1025 | dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc); | ||
1026 | break; | ||
1027 | } | ||
1028 | |||
1029 | dprintk("%s: start filtering\n", __func__); | ||
1030 | priv->secfeed->start_filtering(priv->secfeed); | ||
1031 | } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) { | ||
1032 | struct timespec timeout = { 0, 10000000 }; // 10 msec | ||
1033 | |||
1034 | /* we have payloads encapsulated in TS */ | ||
1035 | dprintk("%s: alloc tsfeed\n", __func__); | ||
1036 | ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback); | ||
1037 | if (ret < 0) { | ||
1038 | printk("%s: could not allocate ts feed\n", dev->name); | ||
1039 | goto error; | ||
1040 | } | ||
1041 | |||
1042 | /* Set netdevice pointer for ts decaps callback. */ | ||
1043 | priv->tsfeed->priv = (void *)dev; | ||
1044 | ret = priv->tsfeed->set(priv->tsfeed, | ||
1045 | priv->pid, /* pid */ | ||
1046 | TS_PACKET, /* type */ | ||
1047 | DMX_TS_PES_OTHER, /* pes type */ | ||
1048 | 32768, /* circular buffer size */ | ||
1049 | timeout /* timeout */ | ||
1050 | ); | ||
1051 | |||
1052 | if (ret < 0) { | ||
1053 | printk("%s: could not set ts feed\n", dev->name); | ||
1054 | priv->demux->release_ts_feed(priv->demux, priv->tsfeed); | ||
1055 | priv->tsfeed = NULL; | ||
1056 | goto error; | ||
1057 | } | ||
1058 | |||
1059 | dprintk("%s: start filtering\n", __func__); | ||
1060 | priv->tsfeed->start_filtering(priv->tsfeed); | ||
1061 | } else | ||
1062 | ret = -EINVAL; | ||
1063 | |||
1064 | error: | ||
1065 | mutex_unlock(&priv->mutex); | ||
1066 | return ret; | ||
1067 | } | ||
1068 | |||
1069 | static int dvb_net_feed_stop(struct net_device *dev) | ||
1070 | { | ||
1071 | struct dvb_net_priv *priv = netdev_priv(dev); | ||
1072 | int i, ret = 0; | ||
1073 | |||
1074 | dprintk("%s\n", __func__); | ||
1075 | mutex_lock(&priv->mutex); | ||
1076 | if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) { | ||
1077 | if (priv->secfeed) { | ||
1078 | if (priv->secfeed->is_filtering) { | ||
1079 | dprintk("%s: stop secfeed\n", __func__); | ||
1080 | priv->secfeed->stop_filtering(priv->secfeed); | ||
1081 | } | ||
1082 | |||
1083 | if (priv->secfilter) { | ||
1084 | dprintk("%s: release secfilter\n", __func__); | ||
1085 | priv->secfeed->release_filter(priv->secfeed, | ||
1086 | priv->secfilter); | ||
1087 | priv->secfilter=NULL; | ||
1088 | } | ||
1089 | |||
1090 | for (i=0; i<priv->multi_num; i++) { | ||
1091 | if (priv->multi_secfilter[i]) { | ||
1092 | dprintk("%s: release multi_filter[%d]\n", | ||
1093 | __func__, i); | ||
1094 | priv->secfeed->release_filter(priv->secfeed, | ||
1095 | priv->multi_secfilter[i]); | ||
1096 | priv->multi_secfilter[i] = NULL; | ||
1097 | } | ||
1098 | } | ||
1099 | |||
1100 | priv->demux->release_section_feed(priv->demux, priv->secfeed); | ||
1101 | priv->secfeed = NULL; | ||
1102 | } else | ||
1103 | printk("%s: no feed to stop\n", dev->name); | ||
1104 | } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) { | ||
1105 | if (priv->tsfeed) { | ||
1106 | if (priv->tsfeed->is_filtering) { | ||
1107 | dprintk("%s: stop tsfeed\n", __func__); | ||
1108 | priv->tsfeed->stop_filtering(priv->tsfeed); | ||
1109 | } | ||
1110 | priv->demux->release_ts_feed(priv->demux, priv->tsfeed); | ||
1111 | priv->tsfeed = NULL; | ||
1112 | } | ||
1113 | else | ||
1114 | printk("%s: no ts feed to stop\n", dev->name); | ||
1115 | } else | ||
1116 | ret = -EINVAL; | ||
1117 | mutex_unlock(&priv->mutex); | ||
1118 | return ret; | ||
1119 | } | ||
1120 | |||
1121 | |||
1122 | static int dvb_set_mc_filter(struct net_device *dev, unsigned char *addr) | ||
1123 | { | ||
1124 | struct dvb_net_priv *priv = netdev_priv(dev); | ||
1125 | |||
1126 | if (priv->multi_num == DVB_NET_MULTICAST_MAX) | ||
1127 | return -ENOMEM; | ||
1128 | |||
1129 | memcpy(priv->multi_macs[priv->multi_num], addr, ETH_ALEN); | ||
1130 | |||
1131 | priv->multi_num++; | ||
1132 | return 0; | ||
1133 | } | ||
1134 | |||
1135 | |||
1136 | static void wq_set_multicast_list (struct work_struct *work) | ||
1137 | { | ||
1138 | struct dvb_net_priv *priv = | ||
1139 | container_of(work, struct dvb_net_priv, set_multicast_list_wq); | ||
1140 | struct net_device *dev = priv->net; | ||
1141 | |||
1142 | dvb_net_feed_stop(dev); | ||
1143 | priv->rx_mode = RX_MODE_UNI; | ||
1144 | netif_addr_lock_bh(dev); | ||
1145 | |||
1146 | if (dev->flags & IFF_PROMISC) { | ||
1147 | dprintk("%s: promiscuous mode\n", dev->name); | ||
1148 | priv->rx_mode = RX_MODE_PROMISC; | ||
1149 | } else if ((dev->flags & IFF_ALLMULTI)) { | ||
1150 | dprintk("%s: allmulti mode\n", dev->name); | ||
1151 | priv->rx_mode = RX_MODE_ALL_MULTI; | ||
1152 | } else if (!netdev_mc_empty(dev)) { | ||
1153 | struct netdev_hw_addr *ha; | ||
1154 | |||
1155 | dprintk("%s: set_mc_list, %d entries\n", | ||
1156 | dev->name, netdev_mc_count(dev)); | ||
1157 | |||
1158 | priv->rx_mode = RX_MODE_MULTI; | ||
1159 | priv->multi_num = 0; | ||
1160 | |||
1161 | netdev_for_each_mc_addr(ha, dev) | ||
1162 | dvb_set_mc_filter(dev, ha->addr); | ||
1163 | } | ||
1164 | |||
1165 | netif_addr_unlock_bh(dev); | ||
1166 | dvb_net_feed_start(dev); | ||
1167 | } | ||
1168 | |||
1169 | |||
1170 | static void dvb_net_set_multicast_list (struct net_device *dev) | ||
1171 | { | ||
1172 | struct dvb_net_priv *priv = netdev_priv(dev); | ||
1173 | schedule_work(&priv->set_multicast_list_wq); | ||
1174 | } | ||
1175 | |||
1176 | |||
1177 | static void wq_restart_net_feed (struct work_struct *work) | ||
1178 | { | ||
1179 | struct dvb_net_priv *priv = | ||
1180 | container_of(work, struct dvb_net_priv, restart_net_feed_wq); | ||
1181 | struct net_device *dev = priv->net; | ||
1182 | |||
1183 | if (netif_running(dev)) { | ||
1184 | dvb_net_feed_stop(dev); | ||
1185 | dvb_net_feed_start(dev); | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | |||
1190 | static int dvb_net_set_mac (struct net_device *dev, void *p) | ||
1191 | { | ||
1192 | struct dvb_net_priv *priv = netdev_priv(dev); | ||
1193 | struct sockaddr *addr=p; | ||
1194 | |||
1195 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); | ||
1196 | |||
1197 | if (netif_running(dev)) | ||
1198 | schedule_work(&priv->restart_net_feed_wq); | ||
1199 | |||
1200 | return 0; | ||
1201 | } | ||
1202 | |||
1203 | |||
1204 | static int dvb_net_open(struct net_device *dev) | ||
1205 | { | ||
1206 | struct dvb_net_priv *priv = netdev_priv(dev); | ||
1207 | |||
1208 | priv->in_use++; | ||
1209 | dvb_net_feed_start(dev); | ||
1210 | return 0; | ||
1211 | } | ||
1212 | |||
1213 | |||
1214 | static int dvb_net_stop(struct net_device *dev) | ||
1215 | { | ||
1216 | struct dvb_net_priv *priv = netdev_priv(dev); | ||
1217 | |||
1218 | priv->in_use--; | ||
1219 | return dvb_net_feed_stop(dev); | ||
1220 | } | ||
1221 | |||
1222 | static const struct header_ops dvb_header_ops = { | ||
1223 | .create = eth_header, | ||
1224 | .parse = eth_header_parse, | ||
1225 | .rebuild = eth_rebuild_header, | ||
1226 | }; | ||
1227 | |||
1228 | |||
1229 | static const struct net_device_ops dvb_netdev_ops = { | ||
1230 | .ndo_open = dvb_net_open, | ||
1231 | .ndo_stop = dvb_net_stop, | ||
1232 | .ndo_start_xmit = dvb_net_tx, | ||
1233 | .ndo_set_rx_mode = dvb_net_set_multicast_list, | ||
1234 | .ndo_set_mac_address = dvb_net_set_mac, | ||
1235 | .ndo_change_mtu = eth_change_mtu, | ||
1236 | .ndo_validate_addr = eth_validate_addr, | ||
1237 | }; | ||
1238 | |||
1239 | static void dvb_net_setup(struct net_device *dev) | ||
1240 | { | ||
1241 | ether_setup(dev); | ||
1242 | |||
1243 | dev->header_ops = &dvb_header_ops; | ||
1244 | dev->netdev_ops = &dvb_netdev_ops; | ||
1245 | dev->mtu = 4096; | ||
1246 | |||
1247 | dev->flags |= IFF_NOARP; | ||
1248 | } | ||
1249 | |||
1250 | static int get_if(struct dvb_net *dvbnet) | ||
1251 | { | ||
1252 | int i; | ||
1253 | |||
1254 | for (i=0; i<DVB_NET_DEVICES_MAX; i++) | ||
1255 | if (!dvbnet->state[i]) | ||
1256 | break; | ||
1257 | |||
1258 | if (i == DVB_NET_DEVICES_MAX) | ||
1259 | return -1; | ||
1260 | |||
1261 | dvbnet->state[i]=1; | ||
1262 | return i; | ||
1263 | } | ||
1264 | |||
1265 | static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) | ||
1266 | { | ||
1267 | struct net_device *net; | ||
1268 | struct dvb_net_priv *priv; | ||
1269 | int result; | ||
1270 | int if_num; | ||
1271 | |||
1272 | if (feedtype != DVB_NET_FEEDTYPE_MPE && feedtype != DVB_NET_FEEDTYPE_ULE) | ||
1273 | return -EINVAL; | ||
1274 | if ((if_num = get_if(dvbnet)) < 0) | ||
1275 | return -EINVAL; | ||
1276 | |||
1277 | net = alloc_netdev(sizeof(struct dvb_net_priv), "dvb", dvb_net_setup); | ||
1278 | if (!net) | ||
1279 | return -ENOMEM; | ||
1280 | |||
1281 | if (dvbnet->dvbdev->id) | ||
1282 | snprintf(net->name, IFNAMSIZ, "dvb%d%u%d", | ||
1283 | dvbnet->dvbdev->adapter->num, dvbnet->dvbdev->id, if_num); | ||
1284 | else | ||
1285 | /* compatibility fix to keep dvb0_0 format */ | ||
1286 | snprintf(net->name, IFNAMSIZ, "dvb%d_%d", | ||
1287 | dvbnet->dvbdev->adapter->num, if_num); | ||
1288 | |||
1289 | net->addr_len = 6; | ||
1290 | memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6); | ||
1291 | |||
1292 | dvbnet->device[if_num] = net; | ||
1293 | |||
1294 | priv = netdev_priv(net); | ||
1295 | priv->net = net; | ||
1296 | priv->demux = dvbnet->demux; | ||
1297 | priv->pid = pid; | ||
1298 | priv->rx_mode = RX_MODE_UNI; | ||
1299 | priv->need_pusi = 1; | ||
1300 | priv->tscc = 0; | ||
1301 | priv->feedtype = feedtype; | ||
1302 | reset_ule(priv); | ||
1303 | |||
1304 | INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list); | ||
1305 | INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed); | ||
1306 | mutex_init(&priv->mutex); | ||
1307 | |||
1308 | net->base_addr = pid; | ||
1309 | |||
1310 | if ((result = register_netdev(net)) < 0) { | ||
1311 | dvbnet->device[if_num] = NULL; | ||
1312 | free_netdev(net); | ||
1313 | return result; | ||
1314 | } | ||
1315 | printk("dvb_net: created network interface %s\n", net->name); | ||
1316 | |||
1317 | return if_num; | ||
1318 | } | ||
1319 | |||
1320 | static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num) | ||
1321 | { | ||
1322 | struct net_device *net = dvbnet->device[num]; | ||
1323 | struct dvb_net_priv *priv; | ||
1324 | |||
1325 | if (!dvbnet->state[num]) | ||
1326 | return -EINVAL; | ||
1327 | priv = netdev_priv(net); | ||
1328 | if (priv->in_use) | ||
1329 | return -EBUSY; | ||
1330 | |||
1331 | dvb_net_stop(net); | ||
1332 | flush_work_sync(&priv->set_multicast_list_wq); | ||
1333 | flush_work_sync(&priv->restart_net_feed_wq); | ||
1334 | printk("dvb_net: removed network interface %s\n", net->name); | ||
1335 | unregister_netdev(net); | ||
1336 | dvbnet->state[num]=0; | ||
1337 | dvbnet->device[num] = NULL; | ||
1338 | free_netdev(net); | ||
1339 | |||
1340 | return 0; | ||
1341 | } | ||
1342 | |||
1343 | static int dvb_net_do_ioctl(struct file *file, | ||
1344 | unsigned int cmd, void *parg) | ||
1345 | { | ||
1346 | struct dvb_device *dvbdev = file->private_data; | ||
1347 | struct dvb_net *dvbnet = dvbdev->priv; | ||
1348 | |||
1349 | if (((file->f_flags&O_ACCMODE)==O_RDONLY)) | ||
1350 | return -EPERM; | ||
1351 | |||
1352 | switch (cmd) { | ||
1353 | case NET_ADD_IF: | ||
1354 | { | ||
1355 | struct dvb_net_if *dvbnetif = parg; | ||
1356 | int result; | ||
1357 | |||
1358 | if (!capable(CAP_SYS_ADMIN)) | ||
1359 | return -EPERM; | ||
1360 | |||
1361 | if (!try_module_get(dvbdev->adapter->module)) | ||
1362 | return -EPERM; | ||
1363 | |||
1364 | result=dvb_net_add_if(dvbnet, dvbnetif->pid, dvbnetif->feedtype); | ||
1365 | if (result<0) { | ||
1366 | module_put(dvbdev->adapter->module); | ||
1367 | return result; | ||
1368 | } | ||
1369 | dvbnetif->if_num=result; | ||
1370 | break; | ||
1371 | } | ||
1372 | case NET_GET_IF: | ||
1373 | { | ||
1374 | struct net_device *netdev; | ||
1375 | struct dvb_net_priv *priv_data; | ||
1376 | struct dvb_net_if *dvbnetif = parg; | ||
1377 | |||
1378 | if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || | ||
1379 | !dvbnet->state[dvbnetif->if_num]) | ||
1380 | return -EINVAL; | ||
1381 | |||
1382 | netdev = dvbnet->device[dvbnetif->if_num]; | ||
1383 | |||
1384 | priv_data = netdev_priv(netdev); | ||
1385 | dvbnetif->pid=priv_data->pid; | ||
1386 | dvbnetif->feedtype=priv_data->feedtype; | ||
1387 | break; | ||
1388 | } | ||
1389 | case NET_REMOVE_IF: | ||
1390 | { | ||
1391 | int ret; | ||
1392 | |||
1393 | if (!capable(CAP_SYS_ADMIN)) | ||
1394 | return -EPERM; | ||
1395 | if ((unsigned long) parg >= DVB_NET_DEVICES_MAX) | ||
1396 | return -EINVAL; | ||
1397 | ret = dvb_net_remove_if(dvbnet, (unsigned long) parg); | ||
1398 | if (!ret) | ||
1399 | module_put(dvbdev->adapter->module); | ||
1400 | return ret; | ||
1401 | } | ||
1402 | |||
1403 | /* binary compatibility cruft */ | ||
1404 | case __NET_ADD_IF_OLD: | ||
1405 | { | ||
1406 | struct __dvb_net_if_old *dvbnetif = parg; | ||
1407 | int result; | ||
1408 | |||
1409 | if (!capable(CAP_SYS_ADMIN)) | ||
1410 | return -EPERM; | ||
1411 | |||
1412 | if (!try_module_get(dvbdev->adapter->module)) | ||
1413 | return -EPERM; | ||
1414 | |||
1415 | result=dvb_net_add_if(dvbnet, dvbnetif->pid, DVB_NET_FEEDTYPE_MPE); | ||
1416 | if (result<0) { | ||
1417 | module_put(dvbdev->adapter->module); | ||
1418 | return result; | ||
1419 | } | ||
1420 | dvbnetif->if_num=result; | ||
1421 | break; | ||
1422 | } | ||
1423 | case __NET_GET_IF_OLD: | ||
1424 | { | ||
1425 | struct net_device *netdev; | ||
1426 | struct dvb_net_priv *priv_data; | ||
1427 | struct __dvb_net_if_old *dvbnetif = parg; | ||
1428 | |||
1429 | if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || | ||
1430 | !dvbnet->state[dvbnetif->if_num]) | ||
1431 | return -EINVAL; | ||
1432 | |||
1433 | netdev = dvbnet->device[dvbnetif->if_num]; | ||
1434 | |||
1435 | priv_data = netdev_priv(netdev); | ||
1436 | dvbnetif->pid=priv_data->pid; | ||
1437 | break; | ||
1438 | } | ||
1439 | default: | ||
1440 | return -ENOTTY; | ||
1441 | } | ||
1442 | return 0; | ||
1443 | } | ||
1444 | |||
1445 | static long dvb_net_ioctl(struct file *file, | ||
1446 | unsigned int cmd, unsigned long arg) | ||
1447 | { | ||
1448 | return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl); | ||
1449 | } | ||
1450 | |||
1451 | static int dvb_net_close(struct inode *inode, struct file *file) | ||
1452 | { | ||
1453 | struct dvb_device *dvbdev = file->private_data; | ||
1454 | struct dvb_net *dvbnet = dvbdev->priv; | ||
1455 | |||
1456 | dvb_generic_release(inode, file); | ||
1457 | |||
1458 | if(dvbdev->users == 1 && dvbnet->exit == 1) { | ||
1459 | fops_put(file->f_op); | ||
1460 | file->f_op = NULL; | ||
1461 | wake_up(&dvbdev->wait_queue); | ||
1462 | } | ||
1463 | return 0; | ||
1464 | } | ||
1465 | |||
1466 | |||
1467 | static const struct file_operations dvb_net_fops = { | ||
1468 | .owner = THIS_MODULE, | ||
1469 | .unlocked_ioctl = dvb_net_ioctl, | ||
1470 | .open = dvb_generic_open, | ||
1471 | .release = dvb_net_close, | ||
1472 | .llseek = noop_llseek, | ||
1473 | }; | ||
1474 | |||
1475 | static struct dvb_device dvbdev_net = { | ||
1476 | .priv = NULL, | ||
1477 | .users = 1, | ||
1478 | .writers = 1, | ||
1479 | .fops = &dvb_net_fops, | ||
1480 | }; | ||
1481 | |||
1482 | |||
1483 | void dvb_net_release (struct dvb_net *dvbnet) | ||
1484 | { | ||
1485 | int i; | ||
1486 | |||
1487 | dvbnet->exit = 1; | ||
1488 | if (dvbnet->dvbdev->users < 1) | ||
1489 | wait_event(dvbnet->dvbdev->wait_queue, | ||
1490 | dvbnet->dvbdev->users==1); | ||
1491 | |||
1492 | dvb_unregister_device(dvbnet->dvbdev); | ||
1493 | |||
1494 | for (i=0; i<DVB_NET_DEVICES_MAX; i++) { | ||
1495 | if (!dvbnet->state[i]) | ||
1496 | continue; | ||
1497 | dvb_net_remove_if(dvbnet, i); | ||
1498 | } | ||
1499 | } | ||
1500 | EXPORT_SYMBOL(dvb_net_release); | ||
1501 | |||
1502 | |||
1503 | int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet, | ||
1504 | struct dmx_demux *dmx) | ||
1505 | { | ||
1506 | int i; | ||
1507 | |||
1508 | dvbnet->demux = dmx; | ||
1509 | |||
1510 | for (i=0; i<DVB_NET_DEVICES_MAX; i++) | ||
1511 | dvbnet->state[i] = 0; | ||
1512 | |||
1513 | return dvb_register_device(adap, &dvbnet->dvbdev, &dvbdev_net, | ||
1514 | dvbnet, DVB_DEVICE_NET); | ||
1515 | } | ||
1516 | EXPORT_SYMBOL(dvb_net_init); | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb/dvb-core/dvb_net.h deleted file mode 100644 index 1e53acd50cf4..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_net.h +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /* | ||
2 | * dvb_net.h | ||
3 | * | ||
4 | * Copyright (C) 2001 Ralph Metzler for convergence integrated media GmbH | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public License | ||
8 | * as published by the Free Software Foundation; either version 2.1 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef _DVB_NET_H_ | ||
23 | #define _DVB_NET_H_ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/netdevice.h> | ||
27 | #include <linux/inetdevice.h> | ||
28 | #include <linux/etherdevice.h> | ||
29 | #include <linux/skbuff.h> | ||
30 | |||
31 | #include "dvbdev.h" | ||
32 | |||
33 | #define DVB_NET_DEVICES_MAX 10 | ||
34 | |||
35 | #ifdef CONFIG_DVB_NET | ||
36 | |||
37 | struct dvb_net { | ||
38 | struct dvb_device *dvbdev; | ||
39 | struct net_device *device[DVB_NET_DEVICES_MAX]; | ||
40 | int state[DVB_NET_DEVICES_MAX]; | ||
41 | unsigned int exit:1; | ||
42 | struct dmx_demux *demux; | ||
43 | }; | ||
44 | |||
45 | void dvb_net_release(struct dvb_net *); | ||
46 | int dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *); | ||
47 | |||
48 | #else | ||
49 | |||
50 | struct dvb_net { | ||
51 | struct dvb_device *dvbdev; | ||
52 | }; | ||
53 | |||
54 | static inline void dvb_net_release(struct dvb_net *dvbnet) | ||
55 | { | ||
56 | } | ||
57 | |||
58 | static inline int dvb_net_init(struct dvb_adapter *adap, | ||
59 | struct dvb_net *dvbnet, struct dmx_demux *dmx) | ||
60 | { | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | #endif /* ifdef CONFIG_DVB_NET */ | ||
65 | |||
66 | #endif | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c deleted file mode 100644 index a5712cd7c65f..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +++ /dev/null | |||
@@ -1,299 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * dvb_ringbuffer.c: ring buffer implementation for the dvb driver | ||
4 | * | ||
5 | * Copyright (C) 2003 Oliver Endriss | ||
6 | * Copyright (C) 2004 Andrew de Quincey | ||
7 | * | ||
8 | * based on code originally found in av7110.c & dvb_ci.c: | ||
9 | * Copyright (C) 1999-2003 Ralph Metzler | ||
10 | * & Marcus Metzler for convergence integrated media GmbH | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU Lesser General Public License | ||
14 | * as published by the Free Software Foundation; either version 2.1 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Lesser General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Lesser General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
25 | */ | ||
26 | |||
27 | |||
28 | |||
29 | #include <linux/errno.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/sched.h> | ||
33 | #include <linux/string.h> | ||
34 | #include <asm/uaccess.h> | ||
35 | |||
36 | #include "dvb_ringbuffer.h" | ||
37 | |||
38 | #define PKT_READY 0 | ||
39 | #define PKT_DISPOSED 1 | ||
40 | |||
41 | |||
42 | void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len) | ||
43 | { | ||
44 | rbuf->pread=rbuf->pwrite=0; | ||
45 | rbuf->data=data; | ||
46 | rbuf->size=len; | ||
47 | rbuf->error=0; | ||
48 | |||
49 | init_waitqueue_head(&rbuf->queue); | ||
50 | |||
51 | spin_lock_init(&(rbuf->lock)); | ||
52 | } | ||
53 | |||
54 | |||
55 | |||
56 | int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf) | ||
57 | { | ||
58 | return (rbuf->pread==rbuf->pwrite); | ||
59 | } | ||
60 | |||
61 | |||
62 | |||
63 | ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf) | ||
64 | { | ||
65 | ssize_t free; | ||
66 | |||
67 | free = rbuf->pread - rbuf->pwrite; | ||
68 | if (free <= 0) | ||
69 | free += rbuf->size; | ||
70 | return free-1; | ||
71 | } | ||
72 | |||
73 | |||
74 | |||
75 | ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf) | ||
76 | { | ||
77 | ssize_t avail; | ||
78 | |||
79 | avail = rbuf->pwrite - rbuf->pread; | ||
80 | if (avail < 0) | ||
81 | avail += rbuf->size; | ||
82 | return avail; | ||
83 | } | ||
84 | |||
85 | |||
86 | |||
87 | void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) | ||
88 | { | ||
89 | rbuf->pread = rbuf->pwrite; | ||
90 | rbuf->error = 0; | ||
91 | } | ||
92 | EXPORT_SYMBOL(dvb_ringbuffer_flush); | ||
93 | |||
94 | void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf) | ||
95 | { | ||
96 | rbuf->pread = rbuf->pwrite = 0; | ||
97 | rbuf->error = 0; | ||
98 | } | ||
99 | |||
100 | void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf) | ||
101 | { | ||
102 | unsigned long flags; | ||
103 | |||
104 | spin_lock_irqsave(&rbuf->lock, flags); | ||
105 | dvb_ringbuffer_flush(rbuf); | ||
106 | spin_unlock_irqrestore(&rbuf->lock, flags); | ||
107 | |||
108 | wake_up(&rbuf->queue); | ||
109 | } | ||
110 | |||
111 | ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len) | ||
112 | { | ||
113 | size_t todo = len; | ||
114 | size_t split; | ||
115 | |||
116 | split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; | ||
117 | if (split > 0) { | ||
118 | if (copy_to_user(buf, rbuf->data+rbuf->pread, split)) | ||
119 | return -EFAULT; | ||
120 | buf += split; | ||
121 | todo -= split; | ||
122 | rbuf->pread = 0; | ||
123 | } | ||
124 | if (copy_to_user(buf, rbuf->data+rbuf->pread, todo)) | ||
125 | return -EFAULT; | ||
126 | |||
127 | rbuf->pread = (rbuf->pread + todo) % rbuf->size; | ||
128 | |||
129 | return len; | ||
130 | } | ||
131 | |||
132 | void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len) | ||
133 | { | ||
134 | size_t todo = len; | ||
135 | size_t split; | ||
136 | |||
137 | split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; | ||
138 | if (split > 0) { | ||
139 | memcpy(buf, rbuf->data+rbuf->pread, split); | ||
140 | buf += split; | ||
141 | todo -= split; | ||
142 | rbuf->pread = 0; | ||
143 | } | ||
144 | memcpy(buf, rbuf->data+rbuf->pread, todo); | ||
145 | |||
146 | rbuf->pread = (rbuf->pread + todo) % rbuf->size; | ||
147 | } | ||
148 | |||
149 | |||
150 | ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len) | ||
151 | { | ||
152 | size_t todo = len; | ||
153 | size_t split; | ||
154 | |||
155 | split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; | ||
156 | |||
157 | if (split > 0) { | ||
158 | memcpy(rbuf->data+rbuf->pwrite, buf, split); | ||
159 | buf += split; | ||
160 | todo -= split; | ||
161 | rbuf->pwrite = 0; | ||
162 | } | ||
163 | memcpy(rbuf->data+rbuf->pwrite, buf, todo); | ||
164 | rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size; | ||
165 | |||
166 | return len; | ||
167 | } | ||
168 | |||
169 | ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len) | ||
170 | { | ||
171 | int status; | ||
172 | ssize_t oldpwrite = rbuf->pwrite; | ||
173 | |||
174 | DVB_RINGBUFFER_WRITE_BYTE(rbuf, len >> 8); | ||
175 | DVB_RINGBUFFER_WRITE_BYTE(rbuf, len & 0xff); | ||
176 | DVB_RINGBUFFER_WRITE_BYTE(rbuf, PKT_READY); | ||
177 | status = dvb_ringbuffer_write(rbuf, buf, len); | ||
178 | |||
179 | if (status < 0) rbuf->pwrite = oldpwrite; | ||
180 | return status; | ||
181 | } | ||
182 | |||
183 | ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx, | ||
184 | int offset, u8 __user *buf, size_t len) | ||
185 | { | ||
186 | size_t todo; | ||
187 | size_t split; | ||
188 | size_t pktlen; | ||
189 | |||
190 | pktlen = rbuf->data[idx] << 8; | ||
191 | pktlen |= rbuf->data[(idx + 1) % rbuf->size]; | ||
192 | if (offset > pktlen) return -EINVAL; | ||
193 | if ((offset + len) > pktlen) len = pktlen - offset; | ||
194 | |||
195 | idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size; | ||
196 | todo = len; | ||
197 | split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; | ||
198 | if (split > 0) { | ||
199 | if (copy_to_user(buf, rbuf->data+idx, split)) | ||
200 | return -EFAULT; | ||
201 | buf += split; | ||
202 | todo -= split; | ||
203 | idx = 0; | ||
204 | } | ||
205 | if (copy_to_user(buf, rbuf->data+idx, todo)) | ||
206 | return -EFAULT; | ||
207 | |||
208 | return len; | ||
209 | } | ||
210 | |||
211 | ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, | ||
212 | int offset, u8* buf, size_t len) | ||
213 | { | ||
214 | size_t todo; | ||
215 | size_t split; | ||
216 | size_t pktlen; | ||
217 | |||
218 | pktlen = rbuf->data[idx] << 8; | ||
219 | pktlen |= rbuf->data[(idx + 1) % rbuf->size]; | ||
220 | if (offset > pktlen) return -EINVAL; | ||
221 | if ((offset + len) > pktlen) len = pktlen - offset; | ||
222 | |||
223 | idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size; | ||
224 | todo = len; | ||
225 | split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; | ||
226 | if (split > 0) { | ||
227 | memcpy(buf, rbuf->data+idx, split); | ||
228 | buf += split; | ||
229 | todo -= split; | ||
230 | idx = 0; | ||
231 | } | ||
232 | memcpy(buf, rbuf->data+idx, todo); | ||
233 | return len; | ||
234 | } | ||
235 | |||
236 | void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx) | ||
237 | { | ||
238 | size_t pktlen; | ||
239 | |||
240 | rbuf->data[(idx + 2) % rbuf->size] = PKT_DISPOSED; | ||
241 | |||
242 | // clean up disposed packets | ||
243 | while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) { | ||
244 | if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) { | ||
245 | pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8; | ||
246 | pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1); | ||
247 | DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE); | ||
248 | } else { | ||
249 | // first packet is not disposed, so we stop cleaning now | ||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | |||
255 | ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen) | ||
256 | { | ||
257 | int consumed; | ||
258 | int curpktlen; | ||
259 | int curpktstatus; | ||
260 | |||
261 | if (idx == -1) { | ||
262 | idx = rbuf->pread; | ||
263 | } else { | ||
264 | curpktlen = rbuf->data[idx] << 8; | ||
265 | curpktlen |= rbuf->data[(idx + 1) % rbuf->size]; | ||
266 | idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; | ||
267 | } | ||
268 | |||
269 | consumed = (idx - rbuf->pread) % rbuf->size; | ||
270 | |||
271 | while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) { | ||
272 | |||
273 | curpktlen = rbuf->data[idx] << 8; | ||
274 | curpktlen |= rbuf->data[(idx + 1) % rbuf->size]; | ||
275 | curpktstatus = rbuf->data[(idx + 2) % rbuf->size]; | ||
276 | |||
277 | if (curpktstatus == PKT_READY) { | ||
278 | *pktlen = curpktlen; | ||
279 | return idx; | ||
280 | } | ||
281 | |||
282 | consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE; | ||
283 | idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; | ||
284 | } | ||
285 | |||
286 | // no packets available | ||
287 | return -1; | ||
288 | } | ||
289 | |||
290 | |||
291 | |||
292 | EXPORT_SYMBOL(dvb_ringbuffer_init); | ||
293 | EXPORT_SYMBOL(dvb_ringbuffer_empty); | ||
294 | EXPORT_SYMBOL(dvb_ringbuffer_free); | ||
295 | EXPORT_SYMBOL(dvb_ringbuffer_avail); | ||
296 | EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup); | ||
297 | EXPORT_SYMBOL(dvb_ringbuffer_read_user); | ||
298 | EXPORT_SYMBOL(dvb_ringbuffer_read); | ||
299 | EXPORT_SYMBOL(dvb_ringbuffer_write); | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h deleted file mode 100644 index 41f04dae69b6..000000000000 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h +++ /dev/null | |||
@@ -1,186 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * dvb_ringbuffer.h: ring buffer implementation for the dvb driver | ||
4 | * | ||
5 | * Copyright (C) 2003 Oliver Endriss | ||
6 | * Copyright (C) 2004 Andrew de Quincey | ||
7 | * | ||
8 | * based on code originally found in av7110.c & dvb_ci.c: | ||
9 | * Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler | ||
10 | * for convergence integrated media GmbH | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU Lesser General Public License | ||
14 | * as published by the Free Software Foundation; either version 2.1 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Lesser General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Lesser General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _DVB_RINGBUFFER_H_ | ||
28 | #define _DVB_RINGBUFFER_H_ | ||
29 | |||
30 | #include <linux/spinlock.h> | ||
31 | #include <linux/wait.h> | ||
32 | |||
33 | struct dvb_ringbuffer { | ||
34 | u8 *data; | ||
35 | ssize_t size; | ||
36 | ssize_t pread; | ||
37 | ssize_t pwrite; | ||
38 | int error; | ||
39 | |||
40 | wait_queue_head_t queue; | ||
41 | spinlock_t lock; | ||
42 | }; | ||
43 | |||
44 | #define DVB_RINGBUFFER_PKTHDRSIZE 3 | ||
45 | |||
46 | |||
47 | /* | ||
48 | ** Notes: | ||
49 | ** ------ | ||
50 | ** (1) For performance reasons read and write routines don't check buffer sizes | ||
51 | ** and/or number of bytes free/available. This has to be done before these | ||
52 | ** routines are called. For example: | ||
53 | ** | ||
54 | ** *** write <buflen> bytes *** | ||
55 | ** free = dvb_ringbuffer_free(rbuf); | ||
56 | ** if (free >= buflen) | ||
57 | ** count = dvb_ringbuffer_write(rbuf, buffer, buflen); | ||
58 | ** else | ||
59 | ** ... | ||
60 | ** | ||
61 | ** *** read min. 1000, max. <bufsize> bytes *** | ||
62 | ** avail = dvb_ringbuffer_avail(rbuf); | ||
63 | ** if (avail >= 1000) | ||
64 | ** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize)); | ||
65 | ** else | ||
66 | ** ... | ||
67 | ** | ||
68 | ** (2) If there is exactly one reader and one writer, there is no need | ||
69 | ** to lock read or write operations. | ||
70 | ** Two or more readers must be locked against each other. | ||
71 | ** Flushing the buffer counts as a read operation. | ||
72 | ** Resetting the buffer counts as a read and write operation. | ||
73 | ** Two or more writers must be locked against each other. | ||
74 | */ | ||
75 | |||
76 | /* initialize ring buffer, lock and queue */ | ||
77 | extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len); | ||
78 | |||
79 | /* test whether buffer is empty */ | ||
80 | extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf); | ||
81 | |||
82 | /* return the number of free bytes in the buffer */ | ||
83 | extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf); | ||
84 | |||
85 | /* return the number of bytes waiting in the buffer */ | ||
86 | extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf); | ||
87 | |||
88 | |||
89 | /* | ||
90 | ** Reset the read and write pointers to zero and flush the buffer | ||
91 | ** This counts as a read and write operation | ||
92 | */ | ||
93 | extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf); | ||
94 | |||
95 | |||
96 | /* read routines & macros */ | ||
97 | /* ---------------------- */ | ||
98 | /* flush buffer */ | ||
99 | extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf); | ||
100 | |||
101 | /* flush buffer protected by spinlock and wake-up waiting task(s) */ | ||
102 | extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); | ||
103 | |||
104 | /* peek at byte <offs> in the buffer */ | ||
105 | #define DVB_RINGBUFFER_PEEK(rbuf,offs) \ | ||
106 | (rbuf)->data[((rbuf)->pread+(offs))%(rbuf)->size] | ||
107 | |||
108 | /* advance read ptr by <num> bytes */ | ||
109 | #define DVB_RINGBUFFER_SKIP(rbuf,num) \ | ||
110 | (rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size | ||
111 | |||
112 | /* | ||
113 | ** read <len> bytes from ring buffer into <buf> | ||
114 | ** <usermem> specifies whether <buf> resides in user space | ||
115 | ** returns number of bytes transferred or -EFAULT | ||
116 | */ | ||
117 | extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, | ||
118 | u8 __user *buf, size_t len); | ||
119 | extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, | ||
120 | u8 *buf, size_t len); | ||
121 | |||
122 | |||
123 | /* write routines & macros */ | ||
124 | /* ----------------------- */ | ||
125 | /* write single byte to ring buffer */ | ||
126 | #define DVB_RINGBUFFER_WRITE_BYTE(rbuf,byte) \ | ||
127 | { (rbuf)->data[(rbuf)->pwrite]=(byte); \ | ||
128 | (rbuf)->pwrite=((rbuf)->pwrite+1)%(rbuf)->size; } | ||
129 | /* | ||
130 | ** write <len> bytes to ring buffer | ||
131 | ** <usermem> specifies whether <buf> resides in user space | ||
132 | ** returns number of bytes transferred or -EFAULT | ||
133 | */ | ||
134 | extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, | ||
135 | size_t len); | ||
136 | |||
137 | |||
138 | /** | ||
139 | * Write a packet into the ringbuffer. | ||
140 | * | ||
141 | * <rbuf> Ringbuffer to write to. | ||
142 | * <buf> Buffer to write. | ||
143 | * <len> Length of buffer (currently limited to 65535 bytes max). | ||
144 | * returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL. | ||
145 | */ | ||
146 | extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, | ||
147 | size_t len); | ||
148 | |||
149 | /** | ||
150 | * Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this | ||
151 | * does NOT update the read pointer in the ringbuffer. You must use | ||
152 | * dvb_ringbuffer_pkt_dispose() to mark a packet as no longer required. | ||
153 | * | ||
154 | * <rbuf> Ringbuffer concerned. | ||
155 | * <idx> Packet index as returned by dvb_ringbuffer_pkt_next(). | ||
156 | * <offset> Offset into packet to read from. | ||
157 | * <buf> Destination buffer for data. | ||
158 | * <len> Size of destination buffer. | ||
159 | * <usermem> Set to 1 if <buf> is in userspace. | ||
160 | * returns Number of bytes read, or -EFAULT. | ||
161 | */ | ||
162 | extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx, | ||
163 | int offset, u8 __user *buf, size_t len); | ||
164 | extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, | ||
165 | int offset, u8 *buf, size_t len); | ||
166 | |||
167 | /** | ||
168 | * Dispose of a packet in the ring buffer. | ||
169 | * | ||
170 | * <rbuf> Ring buffer concerned. | ||
171 | * <idx> Packet index as returned by dvb_ringbuffer_pkt_next(). | ||
172 | */ | ||
173 | extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx); | ||
174 | |||
175 | /** | ||
176 | * Get the index of the next packet in a ringbuffer. | ||
177 | * | ||
178 | * <rbuf> Ringbuffer concerned. | ||
179 | * <idx> Previous packet index, or -1 to return the first packet index. | ||
180 | * <pktlen> On success, will be updated to contain the length of the packet in bytes. | ||
181 | * returns Packet index (if >=0), or -1 if no packets available. | ||
182 | */ | ||
183 | extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen); | ||
184 | |||
185 | |||
186 | #endif /* _DVB_RINGBUFFER_H_ */ | ||
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c deleted file mode 100644 index 39eab73b01ae..000000000000 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ /dev/null | |||
@@ -1,507 +0,0 @@ | |||
1 | /* | ||
2 | * dvbdev.c | ||
3 | * | ||
4 | * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de> | ||
5 | * & Marcus Metzler <marcus@convergence.de> | ||
6 | * for convergence integrated media GmbH | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public License | ||
10 | * as published by the Free Software Foundation; either version 2.1 | ||
11 | * of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/types.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/string.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/device.h> | ||
32 | #include <linux/fs.h> | ||
33 | #include <linux/cdev.h> | ||
34 | #include <linux/mutex.h> | ||
35 | #include "dvbdev.h" | ||
36 | |||
37 | static DEFINE_MUTEX(dvbdev_mutex); | ||
38 | static int dvbdev_debug; | ||
39 | |||
40 | module_param(dvbdev_debug, int, 0644); | ||
41 | MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off)."); | ||
42 | |||
43 | #define dprintk if (dvbdev_debug) printk | ||
44 | |||
45 | static LIST_HEAD(dvb_adapter_list); | ||
46 | static DEFINE_MUTEX(dvbdev_register_lock); | ||
47 | |||
48 | static const char * const dnames[] = { | ||
49 | "video", "audio", "sec", "frontend", "demux", "dvr", "ca", | ||
50 | "net", "osd" | ||
51 | }; | ||
52 | |||
53 | #ifdef CONFIG_DVB_DYNAMIC_MINORS | ||
54 | #define MAX_DVB_MINORS 256 | ||
55 | #define DVB_MAX_IDS MAX_DVB_MINORS | ||
56 | #else | ||
57 | #define DVB_MAX_IDS 4 | ||
58 | #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) | ||
59 | #define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) | ||
60 | #endif | ||
61 | |||
62 | static struct class *dvb_class; | ||
63 | |||
64 | static struct dvb_device *dvb_minors[MAX_DVB_MINORS]; | ||
65 | static DECLARE_RWSEM(minor_rwsem); | ||
66 | |||
67 | static int dvb_device_open(struct inode *inode, struct file *file) | ||
68 | { | ||
69 | struct dvb_device *dvbdev; | ||
70 | |||
71 | mutex_lock(&dvbdev_mutex); | ||
72 | down_read(&minor_rwsem); | ||
73 | dvbdev = dvb_minors[iminor(inode)]; | ||
74 | |||
75 | if (dvbdev && dvbdev->fops) { | ||
76 | int err = 0; | ||
77 | const struct file_operations *old_fops; | ||
78 | |||
79 | file->private_data = dvbdev; | ||
80 | old_fops = file->f_op; | ||
81 | file->f_op = fops_get(dvbdev->fops); | ||
82 | if (file->f_op == NULL) { | ||
83 | file->f_op = old_fops; | ||
84 | goto fail; | ||
85 | } | ||
86 | if(file->f_op->open) | ||
87 | err = file->f_op->open(inode,file); | ||
88 | if (err) { | ||
89 | fops_put(file->f_op); | ||
90 | file->f_op = fops_get(old_fops); | ||
91 | } | ||
92 | fops_put(old_fops); | ||
93 | up_read(&minor_rwsem); | ||
94 | mutex_unlock(&dvbdev_mutex); | ||
95 | return err; | ||
96 | } | ||
97 | fail: | ||
98 | up_read(&minor_rwsem); | ||
99 | mutex_unlock(&dvbdev_mutex); | ||
100 | return -ENODEV; | ||
101 | } | ||
102 | |||
103 | |||
104 | static const struct file_operations dvb_device_fops = | ||
105 | { | ||
106 | .owner = THIS_MODULE, | ||
107 | .open = dvb_device_open, | ||
108 | .llseek = noop_llseek, | ||
109 | }; | ||
110 | |||
111 | static struct cdev dvb_device_cdev; | ||
112 | |||
113 | int dvb_generic_open(struct inode *inode, struct file *file) | ||
114 | { | ||
115 | struct dvb_device *dvbdev = file->private_data; | ||
116 | |||
117 | if (!dvbdev) | ||
118 | return -ENODEV; | ||
119 | |||
120 | if (!dvbdev->users) | ||
121 | return -EBUSY; | ||
122 | |||
123 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||
124 | if (!dvbdev->readers) | ||
125 | return -EBUSY; | ||
126 | dvbdev->readers--; | ||
127 | } else { | ||
128 | if (!dvbdev->writers) | ||
129 | return -EBUSY; | ||
130 | dvbdev->writers--; | ||
131 | } | ||
132 | |||
133 | dvbdev->users--; | ||
134 | return 0; | ||
135 | } | ||
136 | EXPORT_SYMBOL(dvb_generic_open); | ||
137 | |||
138 | |||
139 | int dvb_generic_release(struct inode *inode, struct file *file) | ||
140 | { | ||
141 | struct dvb_device *dvbdev = file->private_data; | ||
142 | |||
143 | if (!dvbdev) | ||
144 | return -ENODEV; | ||
145 | |||
146 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||
147 | dvbdev->readers++; | ||
148 | } else { | ||
149 | dvbdev->writers++; | ||
150 | } | ||
151 | |||
152 | dvbdev->users++; | ||
153 | return 0; | ||
154 | } | ||
155 | EXPORT_SYMBOL(dvb_generic_release); | ||
156 | |||
157 | |||
158 | long dvb_generic_ioctl(struct file *file, | ||
159 | unsigned int cmd, unsigned long arg) | ||
160 | { | ||
161 | struct dvb_device *dvbdev = file->private_data; | ||
162 | |||
163 | if (!dvbdev) | ||
164 | return -ENODEV; | ||
165 | |||
166 | if (!dvbdev->kernel_ioctl) | ||
167 | return -EINVAL; | ||
168 | |||
169 | return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl); | ||
170 | } | ||
171 | EXPORT_SYMBOL(dvb_generic_ioctl); | ||
172 | |||
173 | |||
174 | static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) | ||
175 | { | ||
176 | u32 id = 0; | ||
177 | |||
178 | while (id < DVB_MAX_IDS) { | ||
179 | struct dvb_device *dev; | ||
180 | list_for_each_entry(dev, &adap->device_list, list_head) | ||
181 | if (dev->type == type && dev->id == id) | ||
182 | goto skip; | ||
183 | return id; | ||
184 | skip: | ||
185 | id++; | ||
186 | } | ||
187 | return -ENFILE; | ||
188 | } | ||
189 | |||
190 | |||
191 | int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, | ||
192 | const struct dvb_device *template, void *priv, int type) | ||
193 | { | ||
194 | struct dvb_device *dvbdev; | ||
195 | struct file_operations *dvbdevfops; | ||
196 | struct device *clsdev; | ||
197 | int minor; | ||
198 | int id; | ||
199 | |||
200 | mutex_lock(&dvbdev_register_lock); | ||
201 | |||
202 | if ((id = dvbdev_get_free_id (adap, type)) < 0){ | ||
203 | mutex_unlock(&dvbdev_register_lock); | ||
204 | *pdvbdev = NULL; | ||
205 | printk(KERN_ERR "%s: couldn't find free device id\n", __func__); | ||
206 | return -ENFILE; | ||
207 | } | ||
208 | |||
209 | *pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL); | ||
210 | |||
211 | if (!dvbdev){ | ||
212 | mutex_unlock(&dvbdev_register_lock); | ||
213 | return -ENOMEM; | ||
214 | } | ||
215 | |||
216 | dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL); | ||
217 | |||
218 | if (!dvbdevfops){ | ||
219 | kfree (dvbdev); | ||
220 | mutex_unlock(&dvbdev_register_lock); | ||
221 | return -ENOMEM; | ||
222 | } | ||
223 | |||
224 | memcpy(dvbdev, template, sizeof(struct dvb_device)); | ||
225 | dvbdev->type = type; | ||
226 | dvbdev->id = id; | ||
227 | dvbdev->adapter = adap; | ||
228 | dvbdev->priv = priv; | ||
229 | dvbdev->fops = dvbdevfops; | ||
230 | init_waitqueue_head (&dvbdev->wait_queue); | ||
231 | |||
232 | memcpy(dvbdevfops, template->fops, sizeof(struct file_operations)); | ||
233 | dvbdevfops->owner = adap->module; | ||
234 | |||
235 | list_add_tail (&dvbdev->list_head, &adap->device_list); | ||
236 | |||
237 | down_write(&minor_rwsem); | ||
238 | #ifdef CONFIG_DVB_DYNAMIC_MINORS | ||
239 | for (minor = 0; minor < MAX_DVB_MINORS; minor++) | ||
240 | if (dvb_minors[minor] == NULL) | ||
241 | break; | ||
242 | |||
243 | if (minor == MAX_DVB_MINORS) { | ||
244 | kfree(dvbdevfops); | ||
245 | kfree(dvbdev); | ||
246 | up_write(&minor_rwsem); | ||
247 | mutex_unlock(&dvbdev_register_lock); | ||
248 | return -EINVAL; | ||
249 | } | ||
250 | #else | ||
251 | minor = nums2minor(adap->num, type, id); | ||
252 | #endif | ||
253 | |||
254 | dvbdev->minor = minor; | ||
255 | dvb_minors[minor] = dvbdev; | ||
256 | up_write(&minor_rwsem); | ||
257 | |||
258 | mutex_unlock(&dvbdev_register_lock); | ||
259 | |||
260 | clsdev = device_create(dvb_class, adap->device, | ||
261 | MKDEV(DVB_MAJOR, minor), | ||
262 | dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id); | ||
263 | if (IS_ERR(clsdev)) { | ||
264 | printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n", | ||
265 | __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); | ||
266 | return PTR_ERR(clsdev); | ||
267 | } | ||
268 | |||
269 | dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", | ||
270 | adap->num, dnames[type], id, minor, minor); | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | EXPORT_SYMBOL(dvb_register_device); | ||
275 | |||
276 | |||
277 | void dvb_unregister_device(struct dvb_device *dvbdev) | ||
278 | { | ||
279 | if (!dvbdev) | ||
280 | return; | ||
281 | |||
282 | down_write(&minor_rwsem); | ||
283 | dvb_minors[dvbdev->minor] = NULL; | ||
284 | up_write(&minor_rwsem); | ||
285 | |||
286 | device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); | ||
287 | |||
288 | list_del (&dvbdev->list_head); | ||
289 | kfree (dvbdev->fops); | ||
290 | kfree (dvbdev); | ||
291 | } | ||
292 | EXPORT_SYMBOL(dvb_unregister_device); | ||
293 | |||
294 | static int dvbdev_check_free_adapter_num(int num) | ||
295 | { | ||
296 | struct list_head *entry; | ||
297 | list_for_each(entry, &dvb_adapter_list) { | ||
298 | struct dvb_adapter *adap; | ||
299 | adap = list_entry(entry, struct dvb_adapter, list_head); | ||
300 | if (adap->num == num) | ||
301 | return 0; | ||
302 | } | ||
303 | return 1; | ||
304 | } | ||
305 | |||
306 | static int dvbdev_get_free_adapter_num (void) | ||
307 | { | ||
308 | int num = 0; | ||
309 | |||
310 | while (num < DVB_MAX_ADAPTERS) { | ||
311 | if (dvbdev_check_free_adapter_num(num)) | ||
312 | return num; | ||
313 | num++; | ||
314 | } | ||
315 | |||
316 | return -ENFILE; | ||
317 | } | ||
318 | |||
319 | |||
320 | int dvb_register_adapter(struct dvb_adapter *adap, const char *name, | ||
321 | struct module *module, struct device *device, | ||
322 | short *adapter_nums) | ||
323 | { | ||
324 | int i, num; | ||
325 | |||
326 | mutex_lock(&dvbdev_register_lock); | ||
327 | |||
328 | for (i = 0; i < DVB_MAX_ADAPTERS; ++i) { | ||
329 | num = adapter_nums[i]; | ||
330 | if (num >= 0 && num < DVB_MAX_ADAPTERS) { | ||
331 | /* use the one the driver asked for */ | ||
332 | if (dvbdev_check_free_adapter_num(num)) | ||
333 | break; | ||
334 | } else { | ||
335 | num = dvbdev_get_free_adapter_num(); | ||
336 | break; | ||
337 | } | ||
338 | num = -1; | ||
339 | } | ||
340 | |||
341 | if (num < 0) { | ||
342 | mutex_unlock(&dvbdev_register_lock); | ||
343 | return -ENFILE; | ||
344 | } | ||
345 | |||
346 | memset (adap, 0, sizeof(struct dvb_adapter)); | ||
347 | INIT_LIST_HEAD (&adap->device_list); | ||
348 | |||
349 | printk(KERN_INFO "DVB: registering new adapter (%s)\n", name); | ||
350 | |||
351 | adap->num = num; | ||
352 | adap->name = name; | ||
353 | adap->module = module; | ||
354 | adap->device = device; | ||
355 | adap->mfe_shared = 0; | ||
356 | adap->mfe_dvbdev = NULL; | ||
357 | mutex_init (&adap->mfe_lock); | ||
358 | |||
359 | list_add_tail (&adap->list_head, &dvb_adapter_list); | ||
360 | |||
361 | mutex_unlock(&dvbdev_register_lock); | ||
362 | |||
363 | return num; | ||
364 | } | ||
365 | EXPORT_SYMBOL(dvb_register_adapter); | ||
366 | |||
367 | |||
368 | int dvb_unregister_adapter(struct dvb_adapter *adap) | ||
369 | { | ||
370 | mutex_lock(&dvbdev_register_lock); | ||
371 | list_del (&adap->list_head); | ||
372 | mutex_unlock(&dvbdev_register_lock); | ||
373 | return 0; | ||
374 | } | ||
375 | EXPORT_SYMBOL(dvb_unregister_adapter); | ||
376 | |||
377 | /* if the miracle happens and "generic_usercopy()" is included into | ||
378 | the kernel, then this can vanish. please don't make the mistake and | ||
379 | define this as video_usercopy(). this will introduce a dependecy | ||
380 | to the v4l "videodev.o" module, which is unnecessary for some | ||
381 | cards (ie. the budget dvb-cards don't need the v4l module...) */ | ||
382 | int dvb_usercopy(struct file *file, | ||
383 | unsigned int cmd, unsigned long arg, | ||
384 | int (*func)(struct file *file, | ||
385 | unsigned int cmd, void *arg)) | ||
386 | { | ||
387 | char sbuf[128]; | ||
388 | void *mbuf = NULL; | ||
389 | void *parg = NULL; | ||
390 | int err = -EINVAL; | ||
391 | |||
392 | /* Copy arguments into temp kernel buffer */ | ||
393 | switch (_IOC_DIR(cmd)) { | ||
394 | case _IOC_NONE: | ||
395 | /* | ||
396 | * For this command, the pointer is actually an integer | ||
397 | * argument. | ||
398 | */ | ||
399 | parg = (void *) arg; | ||
400 | break; | ||
401 | case _IOC_READ: /* some v4l ioctls are marked wrong ... */ | ||
402 | case _IOC_WRITE: | ||
403 | case (_IOC_WRITE | _IOC_READ): | ||
404 | if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { | ||
405 | parg = sbuf; | ||
406 | } else { | ||
407 | /* too big to allocate from stack */ | ||
408 | mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); | ||
409 | if (NULL == mbuf) | ||
410 | return -ENOMEM; | ||
411 | parg = mbuf; | ||
412 | } | ||
413 | |||
414 | err = -EFAULT; | ||
415 | if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) | ||
416 | goto out; | ||
417 | break; | ||
418 | } | ||
419 | |||
420 | /* call driver */ | ||
421 | mutex_lock(&dvbdev_mutex); | ||
422 | if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) | ||
423 | err = -EINVAL; | ||
424 | mutex_unlock(&dvbdev_mutex); | ||
425 | |||
426 | if (err < 0) | ||
427 | goto out; | ||
428 | |||
429 | /* Copy results into user buffer */ | ||
430 | switch (_IOC_DIR(cmd)) | ||
431 | { | ||
432 | case _IOC_READ: | ||
433 | case (_IOC_WRITE | _IOC_READ): | ||
434 | if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) | ||
435 | err = -EFAULT; | ||
436 | break; | ||
437 | } | ||
438 | |||
439 | out: | ||
440 | kfree(mbuf); | ||
441 | return err; | ||
442 | } | ||
443 | |||
444 | static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
445 | { | ||
446 | struct dvb_device *dvbdev = dev_get_drvdata(dev); | ||
447 | |||
448 | add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num); | ||
449 | add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]); | ||
450 | add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id); | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static char *dvb_devnode(struct device *dev, umode_t *mode) | ||
455 | { | ||
456 | struct dvb_device *dvbdev = dev_get_drvdata(dev); | ||
457 | |||
458 | return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d", | ||
459 | dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); | ||
460 | } | ||
461 | |||
462 | |||
463 | static int __init init_dvbdev(void) | ||
464 | { | ||
465 | int retval; | ||
466 | dev_t dev = MKDEV(DVB_MAJOR, 0); | ||
467 | |||
468 | if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) { | ||
469 | printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR); | ||
470 | return retval; | ||
471 | } | ||
472 | |||
473 | cdev_init(&dvb_device_cdev, &dvb_device_fops); | ||
474 | if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) { | ||
475 | printk(KERN_ERR "dvb-core: unable register character device\n"); | ||
476 | goto error; | ||
477 | } | ||
478 | |||
479 | dvb_class = class_create(THIS_MODULE, "dvb"); | ||
480 | if (IS_ERR(dvb_class)) { | ||
481 | retval = PTR_ERR(dvb_class); | ||
482 | goto error; | ||
483 | } | ||
484 | dvb_class->dev_uevent = dvb_uevent; | ||
485 | dvb_class->devnode = dvb_devnode; | ||
486 | return 0; | ||
487 | |||
488 | error: | ||
489 | cdev_del(&dvb_device_cdev); | ||
490 | unregister_chrdev_region(dev, MAX_DVB_MINORS); | ||
491 | return retval; | ||
492 | } | ||
493 | |||
494 | |||
495 | static void __exit exit_dvbdev(void) | ||
496 | { | ||
497 | class_destroy(dvb_class); | ||
498 | cdev_del(&dvb_device_cdev); | ||
499 | unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); | ||
500 | } | ||
501 | |||
502 | subsys_initcall(init_dvbdev); | ||
503 | module_exit(exit_dvbdev); | ||
504 | |||
505 | MODULE_DESCRIPTION("DVB Core Driver"); | ||
506 | MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler"); | ||
507 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h deleted file mode 100644 index 93a9470d3f0c..000000000000 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ /dev/null | |||
@@ -1,146 +0,0 @@ | |||
1 | /* | ||
2 | * dvbdev.h | ||
3 | * | ||
4 | * Copyright (C) 2000 Ralph Metzler & Marcus Metzler | ||
5 | * for convergence integrated media GmbH | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Lesser Public License | ||
9 | * as published by the Free Software Foundation; either version 2.1 | ||
10 | * of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef _DVBDEV_H_ | ||
24 | #define _DVBDEV_H_ | ||
25 | |||
26 | #include <linux/types.h> | ||
27 | #include <linux/poll.h> | ||
28 | #include <linux/fs.h> | ||
29 | #include <linux/list.h> | ||
30 | |||
31 | #define DVB_MAJOR 212 | ||
32 | |||
33 | #if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0 | ||
34 | #define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS | ||
35 | #else | ||
36 | #define DVB_MAX_ADAPTERS 8 | ||
37 | #endif | ||
38 | |||
39 | #define DVB_UNSET (-1) | ||
40 | |||
41 | #define DVB_DEVICE_VIDEO 0 | ||
42 | #define DVB_DEVICE_AUDIO 1 | ||
43 | #define DVB_DEVICE_SEC 2 | ||
44 | #define DVB_DEVICE_FRONTEND 3 | ||
45 | #define DVB_DEVICE_DEMUX 4 | ||
46 | #define DVB_DEVICE_DVR 5 | ||
47 | #define DVB_DEVICE_CA 6 | ||
48 | #define DVB_DEVICE_NET 7 | ||
49 | #define DVB_DEVICE_OSD 8 | ||
50 | |||
51 | #define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \ | ||
52 | static short adapter_nr[] = \ | ||
53 | {[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \ | ||
54 | module_param_array(adapter_nr, short, NULL, 0444); \ | ||
55 | MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers") | ||
56 | |||
57 | struct dvb_frontend; | ||
58 | |||
59 | struct dvb_adapter { | ||
60 | int num; | ||
61 | struct list_head list_head; | ||
62 | struct list_head device_list; | ||
63 | const char *name; | ||
64 | u8 proposed_mac [6]; | ||
65 | void* priv; | ||
66 | |||
67 | struct device *device; | ||
68 | |||
69 | struct module *module; | ||
70 | |||
71 | int mfe_shared; /* indicates mutually exclusive frontends */ | ||
72 | struct dvb_device *mfe_dvbdev; /* frontend device in use */ | ||
73 | struct mutex mfe_lock; /* access lock for thread creation */ | ||
74 | }; | ||
75 | |||
76 | |||
77 | struct dvb_device { | ||
78 | struct list_head list_head; | ||
79 | const struct file_operations *fops; | ||
80 | struct dvb_adapter *adapter; | ||
81 | int type; | ||
82 | int minor; | ||
83 | u32 id; | ||
84 | |||
85 | /* in theory, 'users' can vanish now, | ||
86 | but I don't want to change too much now... */ | ||
87 | int readers; | ||
88 | int writers; | ||
89 | int users; | ||
90 | |||
91 | wait_queue_head_t wait_queue; | ||
92 | /* don't really need those !? -- FIXME: use video_usercopy */ | ||
93 | int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg); | ||
94 | |||
95 | void *priv; | ||
96 | }; | ||
97 | |||
98 | |||
99 | extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name, | ||
100 | struct module *module, struct device *device, | ||
101 | short *adapter_nums); | ||
102 | extern int dvb_unregister_adapter (struct dvb_adapter *adap); | ||
103 | |||
104 | extern int dvb_register_device (struct dvb_adapter *adap, | ||
105 | struct dvb_device **pdvbdev, | ||
106 | const struct dvb_device *template, | ||
107 | void *priv, | ||
108 | int type); | ||
109 | |||
110 | extern void dvb_unregister_device (struct dvb_device *dvbdev); | ||
111 | |||
112 | extern int dvb_generic_open (struct inode *inode, struct file *file); | ||
113 | extern int dvb_generic_release (struct inode *inode, struct file *file); | ||
114 | extern long dvb_generic_ioctl (struct file *file, | ||
115 | unsigned int cmd, unsigned long arg); | ||
116 | |||
117 | /* we don't mess with video_usercopy() any more, | ||
118 | we simply define out own dvb_usercopy(), which will hopefully become | ||
119 | generic_usercopy() someday... */ | ||
120 | |||
121 | extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, | ||
122 | int (*func)(struct file *file, unsigned int cmd, void *arg)); | ||
123 | |||
124 | /** generic DVB attach function. */ | ||
125 | #ifdef CONFIG_MEDIA_ATTACH | ||
126 | #define dvb_attach(FUNCTION, ARGS...) ({ \ | ||
127 | void *__r = NULL; \ | ||
128 | typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ | ||
129 | if (__a) { \ | ||
130 | __r = (void *) __a(ARGS); \ | ||
131 | if (__r == NULL) \ | ||
132 | symbol_put(FUNCTION); \ | ||
133 | } else { \ | ||
134 | printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \ | ||
135 | } \ | ||
136 | __r; \ | ||
137 | }) | ||
138 | |||
139 | #else | ||
140 | #define dvb_attach(FUNCTION, ARGS...) ({ \ | ||
141 | FUNCTION(ARGS); \ | ||
142 | }) | ||
143 | |||
144 | #endif | ||
145 | |||
146 | #endif /* #ifndef _DVBDEV_H_ */ | ||
diff --git a/drivers/media/dvb/dvb-usb-v2/Makefile b/drivers/media/dvb/dvb-usb-v2/Makefile index 61b0f53669e8..9fef543dac21 100644 --- a/drivers/media/dvb/dvb-usb-v2/Makefile +++ b/drivers/media/dvb/dvb-usb-v2/Makefile | |||
@@ -42,7 +42,7 @@ obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o | |||
42 | dvb-usb-rtl28xxu-objs = rtl28xxu.o | 42 | dvb-usb-rtl28xxu-objs = rtl28xxu.o |
43 | obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o | 43 | obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o |
44 | 44 | ||
45 | ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core | 45 | ccflags-y += -I$(srctree)/drivers/media/dvb-core |
46 | ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/ | 46 | ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/ |
47 | ccflags-y += -I$(srctree)/drivers/media/common/tuners | 47 | ccflags-y += -I$(srctree)/drivers/media/common/tuners |
48 | 48 | ||
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 061d5448fa1e..cc95b116bbc2 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -75,7 +75,7 @@ obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o | |||
75 | dvb-usb-technisat-usb2-objs = technisat-usb2.o | 75 | dvb-usb-technisat-usb2-objs = technisat-usb2.o |
76 | obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o | 76 | obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o |
77 | 77 | ||
78 | ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core | 78 | ccflags-y += -I$(srctree)/drivers/media/dvb-core |
79 | ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/ | 79 | ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/ |
80 | # due to tuner-xc3028 | 80 | # due to tuner-xc3028 |
81 | ccflags-y += -I$(srctree)/drivers/media/common/tuners | 81 | ccflags-y += -I$(srctree)/drivers/media/common/tuners |
diff --git a/drivers/media/dvb/firewire/Makefile b/drivers/media/dvb/firewire/Makefile index 357b3aab186b..f3148138c963 100644 --- a/drivers/media/dvb/firewire/Makefile +++ b/drivers/media/dvb/firewire/Makefile | |||
@@ -3,4 +3,4 @@ obj-$(CONFIG_DVB_FIREDTV) += firedtv.o | |||
3 | firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o firedtv-fw.o | 3 | firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o firedtv-fw.o |
4 | firedtv-$(CONFIG_DVB_FIREDTV_INPUT) += firedtv-rc.o | 4 | firedtv-$(CONFIG_DVB_FIREDTV_INPUT) += firedtv-rc.o |
5 | 5 | ||
6 | ccflags-y += -Idrivers/media/dvb/dvb-core | 6 | ccflags-y += -Idrivers/media/dvb-core |
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 185bb8b51952..a378c5293764 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the kernel DVB frontend device drivers. | 2 | # Makefile for the kernel DVB frontend device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core/ | 5 | ccflags-y += -I$(srctree)/drivers/media/dvb-core/ |
6 | ccflags-y += -I$(srctree)/drivers/media/common/tuners/ | 6 | ccflags-y += -I$(srctree)/drivers/media/common/tuners/ |
7 | 7 | ||
8 | stb0899-objs = stb0899_drv.o stb0899_algo.o | 8 | stb0899-objs = stb0899_drv.o stb0899_algo.o |
diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index ec8116dcb368..338411917361 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile | |||
@@ -25,4 +25,4 @@ obj-$(CONFIG_MANTIS_CORE) += mantis_core.o | |||
25 | obj-$(CONFIG_DVB_MANTIS) += mantis.o | 25 | obj-$(CONFIG_DVB_MANTIS) += mantis.o |
26 | obj-$(CONFIG_DVB_HOPPER) += hopper.o | 26 | obj-$(CONFIG_DVB_HOPPER) += hopper.o |
27 | 27 | ||
28 | ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | 28 | ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb/frontends/ |
diff --git a/drivers/media/dvb/ngene/Makefile b/drivers/media/dvb/ngene/Makefile index 13ebeffb705f..dae76597fc31 100644 --- a/drivers/media/dvb/ngene/Makefile +++ b/drivers/media/dvb/ngene/Makefile | |||
@@ -6,7 +6,7 @@ ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o | |||
6 | 6 | ||
7 | obj-$(CONFIG_DVB_NGENE) += ngene.o | 7 | obj-$(CONFIG_DVB_NGENE) += ngene.o |
8 | 8 | ||
9 | ccflags-y += -Idrivers/media/dvb/dvb-core/ | 9 | ccflags-y += -Idrivers/media/dvb-core/ |
10 | ccflags-y += -Idrivers/media/dvb/frontends/ | 10 | ccflags-y += -Idrivers/media/dvb/frontends/ |
11 | ccflags-y += -Idrivers/media/common/tuners/ | 11 | ccflags-y += -Idrivers/media/common/tuners/ |
12 | 12 | ||
diff --git a/drivers/media/dvb/pluto2/Makefile b/drivers/media/dvb/pluto2/Makefile index 700822350ec5..14fa5789c748 100644 --- a/drivers/media/dvb/pluto2/Makefile +++ b/drivers/media/dvb/pluto2/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | obj-$(CONFIG_DVB_PLUTO2) += pluto2.o | 1 | obj-$(CONFIG_DVB_PLUTO2) += pluto2.o |
2 | 2 | ||
3 | ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | 3 | ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb/frontends/ |
diff --git a/drivers/media/dvb/pt1/Makefile b/drivers/media/dvb/pt1/Makefile index d80d8e8e7c57..c80492a1039e 100644 --- a/drivers/media/dvb/pt1/Makefile +++ b/drivers/media/dvb/pt1/Makefile | |||
@@ -2,4 +2,4 @@ earth-pt1-objs := pt1.o va1j5jf8007s.o va1j5jf8007t.o | |||
2 | 2 | ||
3 | obj-$(CONFIG_DVB_PT1) += earth-pt1.o | 3 | obj-$(CONFIG_DVB_PT1) += earth-pt1.o |
4 | 4 | ||
5 | ccflags-y += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends | 5 | ccflags-y += -Idrivers/media/dvb-core -Idrivers/media/dvb/frontends |
diff --git a/drivers/media/dvb/siano/Makefile b/drivers/media/dvb/siano/Makefile index f233b57c86fb..14756bdb6eaa 100644 --- a/drivers/media/dvb/siano/Makefile +++ b/drivers/media/dvb/siano/Makefile | |||
@@ -5,7 +5,7 @@ obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o | |||
5 | obj-$(CONFIG_SMS_USB_DRV) += smsusb.o | 5 | obj-$(CONFIG_SMS_USB_DRV) += smsusb.o |
6 | obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o | 6 | obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o |
7 | 7 | ||
8 | ccflags-y += -Idrivers/media/dvb/dvb-core | 8 | ccflags-y += -Idrivers/media/dvb-core |
9 | 9 | ||
10 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) | 10 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) |
11 | 11 | ||
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile index f6e869372e30..b0ddb4544cb7 100644 --- a/drivers/media/dvb/ttpci/Makefile +++ b/drivers/media/dvb/ttpci/Makefile | |||
@@ -17,5 +17,5 @@ obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci.o | |||
17 | obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o | 17 | obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o |
18 | obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o | 18 | obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o |
19 | 19 | ||
20 | ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | 20 | ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb/frontends/ |
21 | ccflags-y += -Idrivers/media/common/tuners | 21 | ccflags-y += -Idrivers/media/common/tuners |
diff --git a/drivers/media/dvb/ttusb-budget/Makefile b/drivers/media/dvb/ttusb-budget/Makefile index 8d6c4acb7f1d..c5abe78ae04f 100644 --- a/drivers/media/dvb/ttusb-budget/Makefile +++ b/drivers/media/dvb/ttusb-budget/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o | 1 | obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o |
2 | 2 | ||
3 | ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends | 3 | ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb/frontends |
diff --git a/drivers/media/dvb/ttusb-dec/Makefile b/drivers/media/dvb/ttusb-dec/Makefile index ed28b5384d20..5352740d2353 100644 --- a/drivers/media/dvb/ttusb-dec/Makefile +++ b/drivers/media/dvb/ttusb-dec/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o | 1 | obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o |
2 | 2 | ||
3 | ccflags-y += -Idrivers/media/dvb/dvb-core/ | 3 | ccflags-y += -Idrivers/media/dvb-core/ |