diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/media/dvb/dvb-core | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'drivers/media/dvb/dvb-core')
20 files changed, 11384 insertions, 0 deletions
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile new file mode 100644 index 00000000000..8f22bcd7c1f --- /dev/null +++ b/drivers/media/dvb/dvb-core/Makefile | |||
@@ -0,0 +1,11 @@ | |||
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 new file mode 100644 index 00000000000..eb91fd808c1 --- /dev/null +++ b/drivers/media/dvb/dvb-core/demux.h | |||
@@ -0,0 +1,280 @@ | |||
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 new file mode 100644 index 00000000000..e4b5c03ae51 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dmxdev.c | |||
@@ -0,0 +1,1278 @@ | |||
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 <asm/system.h> | ||
33 | #include "dmxdev.h" | ||
34 | |||
35 | static int debug; | ||
36 | |||
37 | module_param(debug, int, 0644); | ||
38 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | ||
39 | |||
40 | #define dprintk if (debug) printk | ||
41 | |||
42 | static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, | ||
43 | const u8 *src, size_t len) | ||
44 | { | ||
45 | ssize_t free; | ||
46 | |||
47 | if (!len) | ||
48 | return 0; | ||
49 | if (!buf->data) | ||
50 | return 0; | ||
51 | |||
52 | free = dvb_ringbuffer_free(buf); | ||
53 | if (len > free) { | ||
54 | dprintk("dmxdev: buffer overflow\n"); | ||
55 | return -EOVERFLOW; | ||
56 | } | ||
57 | |||
58 | return dvb_ringbuffer_write(buf, src, len); | ||
59 | } | ||
60 | |||
61 | static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, | ||
62 | int non_blocking, char __user *buf, | ||
63 | size_t count, loff_t *ppos) | ||
64 | { | ||
65 | size_t todo; | ||
66 | ssize_t avail; | ||
67 | ssize_t ret = 0; | ||
68 | |||
69 | if (!src->data) | ||
70 | return 0; | ||
71 | |||
72 | if (src->error) { | ||
73 | ret = src->error; | ||
74 | dvb_ringbuffer_flush(src); | ||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | for (todo = count; todo > 0; todo -= ret) { | ||
79 | if (non_blocking && dvb_ringbuffer_empty(src)) { | ||
80 | ret = -EWOULDBLOCK; | ||
81 | break; | ||
82 | } | ||
83 | |||
84 | ret = wait_event_interruptible(src->queue, | ||
85 | !dvb_ringbuffer_empty(src) || | ||
86 | (src->error != 0)); | ||
87 | if (ret < 0) | ||
88 | break; | ||
89 | |||
90 | if (src->error) { | ||
91 | ret = src->error; | ||
92 | dvb_ringbuffer_flush(src); | ||
93 | break; | ||
94 | } | ||
95 | |||
96 | avail = dvb_ringbuffer_avail(src); | ||
97 | if (avail > todo) | ||
98 | avail = todo; | ||
99 | |||
100 | ret = dvb_ringbuffer_read_user(src, buf, avail); | ||
101 | if (ret < 0) | ||
102 | break; | ||
103 | |||
104 | buf += ret; | ||
105 | } | ||
106 | |||
107 | return (count - todo) ? (count - todo) : ret; | ||
108 | } | ||
109 | |||
110 | static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type) | ||
111 | { | ||
112 | struct list_head *head, *pos; | ||
113 | |||
114 | head = demux->get_frontends(demux); | ||
115 | if (!head) | ||
116 | return NULL; | ||
117 | list_for_each(pos, head) | ||
118 | if (DMX_FE_ENTRY(pos)->source == type) | ||
119 | return DMX_FE_ENTRY(pos); | ||
120 | |||
121 | return NULL; | ||
122 | } | ||
123 | |||
124 | static int dvb_dvr_open(struct inode *inode, struct file *file) | ||
125 | { | ||
126 | struct dvb_device *dvbdev = file->private_data; | ||
127 | struct dmxdev *dmxdev = dvbdev->priv; | ||
128 | struct dmx_frontend *front; | ||
129 | |||
130 | dprintk("function : %s\n", __func__); | ||
131 | |||
132 | if (mutex_lock_interruptible(&dmxdev->mutex)) | ||
133 | return -ERESTARTSYS; | ||
134 | |||
135 | if (dmxdev->exit) { | ||
136 | mutex_unlock(&dmxdev->mutex); | ||
137 | return -ENODEV; | ||
138 | } | ||
139 | |||
140 | if ((file->f_flags & O_ACCMODE) == O_RDWR) { | ||
141 | if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) { | ||
142 | mutex_unlock(&dmxdev->mutex); | ||
143 | return -EOPNOTSUPP; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||
148 | void *mem; | ||
149 | if (!dvbdev->readers) { | ||
150 | mutex_unlock(&dmxdev->mutex); | ||
151 | return -EBUSY; | ||
152 | } | ||
153 | mem = vmalloc(DVR_BUFFER_SIZE); | ||
154 | if (!mem) { | ||
155 | mutex_unlock(&dmxdev->mutex); | ||
156 | return -ENOMEM; | ||
157 | } | ||
158 | dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); | ||
159 | dvbdev->readers--; | ||
160 | } | ||
161 | |||
162 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) { | ||
163 | dmxdev->dvr_orig_fe = dmxdev->demux->frontend; | ||
164 | |||
165 | if (!dmxdev->demux->write) { | ||
166 | mutex_unlock(&dmxdev->mutex); | ||
167 | return -EOPNOTSUPP; | ||
168 | } | ||
169 | |||
170 | front = get_fe(dmxdev->demux, DMX_MEMORY_FE); | ||
171 | |||
172 | if (!front) { | ||
173 | mutex_unlock(&dmxdev->mutex); | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | dmxdev->demux->disconnect_frontend(dmxdev->demux); | ||
177 | dmxdev->demux->connect_frontend(dmxdev->demux, front); | ||
178 | } | ||
179 | dvbdev->users++; | ||
180 | mutex_unlock(&dmxdev->mutex); | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int dvb_dvr_release(struct inode *inode, struct file *file) | ||
185 | { | ||
186 | struct dvb_device *dvbdev = file->private_data; | ||
187 | struct dmxdev *dmxdev = dvbdev->priv; | ||
188 | |||
189 | mutex_lock(&dmxdev->mutex); | ||
190 | |||
191 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) { | ||
192 | dmxdev->demux->disconnect_frontend(dmxdev->demux); | ||
193 | dmxdev->demux->connect_frontend(dmxdev->demux, | ||
194 | dmxdev->dvr_orig_fe); | ||
195 | } | ||
196 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||
197 | dvbdev->readers++; | ||
198 | if (dmxdev->dvr_buffer.data) { | ||
199 | void *mem = dmxdev->dvr_buffer.data; | ||
200 | mb(); | ||
201 | spin_lock_irq(&dmxdev->lock); | ||
202 | dmxdev->dvr_buffer.data = NULL; | ||
203 | spin_unlock_irq(&dmxdev->lock); | ||
204 | vfree(mem); | ||
205 | } | ||
206 | } | ||
207 | /* TODO */ | ||
208 | dvbdev->users--; | ||
209 | if (dvbdev->users == 1 && dmxdev->exit == 1) { | ||
210 | fops_put(file->f_op); | ||
211 | file->f_op = NULL; | ||
212 | mutex_unlock(&dmxdev->mutex); | ||
213 | wake_up(&dvbdev->wait_queue); | ||
214 | } else | ||
215 | mutex_unlock(&dmxdev->mutex); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static ssize_t dvb_dvr_write(struct file *file, const char __user *buf, | ||
221 | size_t count, loff_t *ppos) | ||
222 | { | ||
223 | struct dvb_device *dvbdev = file->private_data; | ||
224 | struct dmxdev *dmxdev = dvbdev->priv; | ||
225 | int ret; | ||
226 | |||
227 | if (!dmxdev->demux->write) | ||
228 | return -EOPNOTSUPP; | ||
229 | if ((file->f_flags & O_ACCMODE) != O_WRONLY) | ||
230 | return -EINVAL; | ||
231 | if (mutex_lock_interruptible(&dmxdev->mutex)) | ||
232 | return -ERESTARTSYS; | ||
233 | |||
234 | if (dmxdev->exit) { | ||
235 | mutex_unlock(&dmxdev->mutex); | ||
236 | return -ENODEV; | ||
237 | } | ||
238 | ret = dmxdev->demux->write(dmxdev->demux, buf, count); | ||
239 | mutex_unlock(&dmxdev->mutex); | ||
240 | return ret; | ||
241 | } | ||
242 | |||
243 | static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, | ||
244 | loff_t *ppos) | ||
245 | { | ||
246 | struct dvb_device *dvbdev = file->private_data; | ||
247 | struct dmxdev *dmxdev = dvbdev->priv; | ||
248 | |||
249 | if (dmxdev->exit) | ||
250 | return -ENODEV; | ||
251 | |||
252 | return dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, | ||
253 | file->f_flags & O_NONBLOCK, | ||
254 | buf, count, ppos); | ||
255 | } | ||
256 | |||
257 | static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev, | ||
258 | unsigned long size) | ||
259 | { | ||
260 | struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer; | ||
261 | void *newmem; | ||
262 | void *oldmem; | ||
263 | |||
264 | dprintk("function : %s\n", __func__); | ||
265 | |||
266 | if (buf->size == size) | ||
267 | return 0; | ||
268 | if (!size) | ||
269 | return -EINVAL; | ||
270 | |||
271 | newmem = vmalloc(size); | ||
272 | if (!newmem) | ||
273 | return -ENOMEM; | ||
274 | |||
275 | oldmem = buf->data; | ||
276 | |||
277 | spin_lock_irq(&dmxdev->lock); | ||
278 | buf->data = newmem; | ||
279 | buf->size = size; | ||
280 | |||
281 | /* reset and not flush in case the buffer shrinks */ | ||
282 | dvb_ringbuffer_reset(buf); | ||
283 | spin_unlock_irq(&dmxdev->lock); | ||
284 | |||
285 | vfree(oldmem); | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter | ||
291 | *dmxdevfilter, int state) | ||
292 | { | ||
293 | spin_lock_irq(&dmxdevfilter->dev->lock); | ||
294 | dmxdevfilter->state = state; | ||
295 | spin_unlock_irq(&dmxdevfilter->dev->lock); | ||
296 | } | ||
297 | |||
298 | static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, | ||
299 | unsigned long size) | ||
300 | { | ||
301 | struct dvb_ringbuffer *buf = &dmxdevfilter->buffer; | ||
302 | void *newmem; | ||
303 | void *oldmem; | ||
304 | |||
305 | if (buf->size == size) | ||
306 | return 0; | ||
307 | if (!size) | ||
308 | return -EINVAL; | ||
309 | if (dmxdevfilter->state >= DMXDEV_STATE_GO) | ||
310 | return -EBUSY; | ||
311 | |||
312 | newmem = vmalloc(size); | ||
313 | if (!newmem) | ||
314 | return -ENOMEM; | ||
315 | |||
316 | oldmem = buf->data; | ||
317 | |||
318 | spin_lock_irq(&dmxdevfilter->dev->lock); | ||
319 | buf->data = newmem; | ||
320 | buf->size = size; | ||
321 | |||
322 | /* reset and not flush in case the buffer shrinks */ | ||
323 | dvb_ringbuffer_reset(buf); | ||
324 | spin_unlock_irq(&dmxdevfilter->dev->lock); | ||
325 | |||
326 | vfree(oldmem); | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static void dvb_dmxdev_filter_timeout(unsigned long data) | ||
332 | { | ||
333 | struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data; | ||
334 | |||
335 | dmxdevfilter->buffer.error = -ETIMEDOUT; | ||
336 | spin_lock_irq(&dmxdevfilter->dev->lock); | ||
337 | dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT; | ||
338 | spin_unlock_irq(&dmxdevfilter->dev->lock); | ||
339 | wake_up(&dmxdevfilter->buffer.queue); | ||
340 | } | ||
341 | |||
342 | static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) | ||
343 | { | ||
344 | struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec; | ||
345 | |||
346 | del_timer(&dmxdevfilter->timer); | ||
347 | if (para->timeout) { | ||
348 | dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout; | ||
349 | dmxdevfilter->timer.data = (unsigned long)dmxdevfilter; | ||
350 | dmxdevfilter->timer.expires = | ||
351 | jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000; | ||
352 | add_timer(&dmxdevfilter->timer); | ||
353 | } | ||
354 | } | ||
355 | |||
356 | static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, | ||
357 | const u8 *buffer2, size_t buffer2_len, | ||
358 | struct dmx_section_filter *filter, | ||
359 | enum dmx_success success) | ||
360 | { | ||
361 | struct dmxdev_filter *dmxdevfilter = filter->priv; | ||
362 | int ret; | ||
363 | |||
364 | if (dmxdevfilter->buffer.error) { | ||
365 | wake_up(&dmxdevfilter->buffer.queue); | ||
366 | return 0; | ||
367 | } | ||
368 | spin_lock(&dmxdevfilter->dev->lock); | ||
369 | if (dmxdevfilter->state != DMXDEV_STATE_GO) { | ||
370 | spin_unlock(&dmxdevfilter->dev->lock); | ||
371 | return 0; | ||
372 | } | ||
373 | del_timer(&dmxdevfilter->timer); | ||
374 | dprintk("dmxdev: section callback %02x %02x %02x %02x %02x %02x\n", | ||
375 | buffer1[0], buffer1[1], | ||
376 | buffer1[2], buffer1[3], buffer1[4], buffer1[5]); | ||
377 | ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, | ||
378 | buffer1_len); | ||
379 | if (ret == buffer1_len) { | ||
380 | ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, | ||
381 | buffer2_len); | ||
382 | } | ||
383 | if (ret < 0) { | ||
384 | dvb_ringbuffer_flush(&dmxdevfilter->buffer); | ||
385 | dmxdevfilter->buffer.error = ret; | ||
386 | } | ||
387 | if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) | ||
388 | dmxdevfilter->state = DMXDEV_STATE_DONE; | ||
389 | spin_unlock(&dmxdevfilter->dev->lock); | ||
390 | wake_up(&dmxdevfilter->buffer.queue); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, | ||
395 | const u8 *buffer2, size_t buffer2_len, | ||
396 | struct dmx_ts_feed *feed, | ||
397 | enum dmx_success success) | ||
398 | { | ||
399 | struct dmxdev_filter *dmxdevfilter = feed->priv; | ||
400 | struct dvb_ringbuffer *buffer; | ||
401 | int ret; | ||
402 | |||
403 | spin_lock(&dmxdevfilter->dev->lock); | ||
404 | if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { | ||
405 | spin_unlock(&dmxdevfilter->dev->lock); | ||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | if (dmxdevfilter->params.pes.output == DMX_OUT_TAP | ||
410 | || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) | ||
411 | buffer = &dmxdevfilter->buffer; | ||
412 | else | ||
413 | buffer = &dmxdevfilter->dev->dvr_buffer; | ||
414 | if (buffer->error) { | ||
415 | spin_unlock(&dmxdevfilter->dev->lock); | ||
416 | wake_up(&buffer->queue); | ||
417 | return 0; | ||
418 | } | ||
419 | ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); | ||
420 | if (ret == buffer1_len) | ||
421 | ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); | ||
422 | if (ret < 0) { | ||
423 | dvb_ringbuffer_flush(buffer); | ||
424 | buffer->error = ret; | ||
425 | } | ||
426 | spin_unlock(&dmxdevfilter->dev->lock); | ||
427 | wake_up(&buffer->queue); | ||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | /* stop feed but only mark the specified filter as stopped (state set) */ | ||
432 | static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) | ||
433 | { | ||
434 | struct dmxdev_feed *feed; | ||
435 | |||
436 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); | ||
437 | |||
438 | switch (dmxdevfilter->type) { | ||
439 | case DMXDEV_TYPE_SEC: | ||
440 | del_timer(&dmxdevfilter->timer); | ||
441 | dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec); | ||
442 | break; | ||
443 | case DMXDEV_TYPE_PES: | ||
444 | list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) | ||
445 | feed->ts->stop_filtering(feed->ts); | ||
446 | break; | ||
447 | default: | ||
448 | return -EINVAL; | ||
449 | } | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | /* start feed associated with the specified filter */ | ||
454 | static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter) | ||
455 | { | ||
456 | struct dmxdev_feed *feed; | ||
457 | int ret; | ||
458 | |||
459 | dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO); | ||
460 | |||
461 | switch (filter->type) { | ||
462 | case DMXDEV_TYPE_SEC: | ||
463 | return filter->feed.sec->start_filtering(filter->feed.sec); | ||
464 | case DMXDEV_TYPE_PES: | ||
465 | list_for_each_entry(feed, &filter->feed.ts, next) { | ||
466 | ret = feed->ts->start_filtering(feed->ts); | ||
467 | if (ret < 0) { | ||
468 | dvb_dmxdev_feed_stop(filter); | ||
469 | return ret; | ||
470 | } | ||
471 | } | ||
472 | break; | ||
473 | default: | ||
474 | return -EINVAL; | ||
475 | } | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | /* restart section feed if it has filters left associated with it, | ||
481 | otherwise release the feed */ | ||
482 | static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter) | ||
483 | { | ||
484 | int i; | ||
485 | struct dmxdev *dmxdev = filter->dev; | ||
486 | u16 pid = filter->params.sec.pid; | ||
487 | |||
488 | for (i = 0; i < dmxdev->filternum; i++) | ||
489 | if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && | ||
490 | dmxdev->filter[i].type == DMXDEV_TYPE_SEC && | ||
491 | dmxdev->filter[i].params.sec.pid == pid) { | ||
492 | dvb_dmxdev_feed_start(&dmxdev->filter[i]); | ||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | filter->dev->demux->release_section_feed(dmxdev->demux, | ||
497 | filter->feed.sec); | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) | ||
503 | { | ||
504 | struct dmxdev_feed *feed; | ||
505 | struct dmx_demux *demux; | ||
506 | |||
507 | if (dmxdevfilter->state < DMXDEV_STATE_GO) | ||
508 | return 0; | ||
509 | |||
510 | switch (dmxdevfilter->type) { | ||
511 | case DMXDEV_TYPE_SEC: | ||
512 | if (!dmxdevfilter->feed.sec) | ||
513 | break; | ||
514 | dvb_dmxdev_feed_stop(dmxdevfilter); | ||
515 | if (dmxdevfilter->filter.sec) | ||
516 | dmxdevfilter->feed.sec-> | ||
517 | release_filter(dmxdevfilter->feed.sec, | ||
518 | dmxdevfilter->filter.sec); | ||
519 | dvb_dmxdev_feed_restart(dmxdevfilter); | ||
520 | dmxdevfilter->feed.sec = NULL; | ||
521 | break; | ||
522 | case DMXDEV_TYPE_PES: | ||
523 | dvb_dmxdev_feed_stop(dmxdevfilter); | ||
524 | demux = dmxdevfilter->dev->demux; | ||
525 | list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) { | ||
526 | demux->release_ts_feed(demux, feed->ts); | ||
527 | feed->ts = NULL; | ||
528 | } | ||
529 | break; | ||
530 | default: | ||
531 | if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED) | ||
532 | return 0; | ||
533 | return -EINVAL; | ||
534 | } | ||
535 | |||
536 | dvb_ringbuffer_flush(&dmxdevfilter->buffer); | ||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | static void dvb_dmxdev_delete_pids(struct dmxdev_filter *dmxdevfilter) | ||
541 | { | ||
542 | struct dmxdev_feed *feed, *tmp; | ||
543 | |||
544 | /* delete all PIDs */ | ||
545 | list_for_each_entry_safe(feed, tmp, &dmxdevfilter->feed.ts, next) { | ||
546 | list_del(&feed->next); | ||
547 | kfree(feed); | ||
548 | } | ||
549 | |||
550 | BUG_ON(!list_empty(&dmxdevfilter->feed.ts)); | ||
551 | } | ||
552 | |||
553 | static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter) | ||
554 | { | ||
555 | if (dmxdevfilter->state < DMXDEV_STATE_SET) | ||
556 | return 0; | ||
557 | |||
558 | if (dmxdevfilter->type == DMXDEV_TYPE_PES) | ||
559 | dvb_dmxdev_delete_pids(dmxdevfilter); | ||
560 | |||
561 | dmxdevfilter->type = DMXDEV_TYPE_NONE; | ||
562 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); | ||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev, | ||
567 | struct dmxdev_filter *filter, | ||
568 | struct dmxdev_feed *feed) | ||
569 | { | ||
570 | struct timespec timeout = { 0 }; | ||
571 | struct dmx_pes_filter_params *para = &filter->params.pes; | ||
572 | dmx_output_t otype; | ||
573 | int ret; | ||
574 | int ts_type; | ||
575 | dmx_pes_type_t ts_pes; | ||
576 | struct dmx_ts_feed *tsfeed; | ||
577 | |||
578 | feed->ts = NULL; | ||
579 | otype = para->output; | ||
580 | |||
581 | ts_pes = para->pes_type; | ||
582 | |||
583 | if (ts_pes < DMX_PES_OTHER) | ||
584 | ts_type = TS_DECODER; | ||
585 | else | ||
586 | ts_type = 0; | ||
587 | |||
588 | if (otype == DMX_OUT_TS_TAP) | ||
589 | ts_type |= TS_PACKET; | ||
590 | else if (otype == DMX_OUT_TSDEMUX_TAP) | ||
591 | ts_type |= TS_PACKET | TS_DEMUX; | ||
592 | else if (otype == DMX_OUT_TAP) | ||
593 | ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY; | ||
594 | |||
595 | ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux, &feed->ts, | ||
596 | dvb_dmxdev_ts_callback); | ||
597 | if (ret < 0) | ||
598 | return ret; | ||
599 | |||
600 | tsfeed = feed->ts; | ||
601 | tsfeed->priv = filter; | ||
602 | |||
603 | ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, 32768, timeout); | ||
604 | if (ret < 0) { | ||
605 | dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); | ||
606 | return ret; | ||
607 | } | ||
608 | |||
609 | ret = tsfeed->start_filtering(tsfeed); | ||
610 | if (ret < 0) { | ||
611 | dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); | ||
612 | return ret; | ||
613 | } | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) | ||
619 | { | ||
620 | struct dmxdev *dmxdev = filter->dev; | ||
621 | struct dmxdev_feed *feed; | ||
622 | void *mem; | ||
623 | int ret, i; | ||
624 | |||
625 | if (filter->state < DMXDEV_STATE_SET) | ||
626 | return -EINVAL; | ||
627 | |||
628 | if (filter->state >= DMXDEV_STATE_GO) | ||
629 | dvb_dmxdev_filter_stop(filter); | ||
630 | |||
631 | if (!filter->buffer.data) { | ||
632 | mem = vmalloc(filter->buffer.size); | ||
633 | if (!mem) | ||
634 | return -ENOMEM; | ||
635 | spin_lock_irq(&filter->dev->lock); | ||
636 | filter->buffer.data = mem; | ||
637 | spin_unlock_irq(&filter->dev->lock); | ||
638 | } | ||
639 | |||
640 | dvb_ringbuffer_flush(&filter->buffer); | ||
641 | |||
642 | switch (filter->type) { | ||
643 | case DMXDEV_TYPE_SEC: | ||
644 | { | ||
645 | struct dmx_sct_filter_params *para = &filter->params.sec; | ||
646 | struct dmx_section_filter **secfilter = &filter->filter.sec; | ||
647 | struct dmx_section_feed **secfeed = &filter->feed.sec; | ||
648 | |||
649 | *secfilter = NULL; | ||
650 | *secfeed = NULL; | ||
651 | |||
652 | |||
653 | /* find active filter/feed with same PID */ | ||
654 | for (i = 0; i < dmxdev->filternum; i++) { | ||
655 | if (dmxdev->filter[i].state >= DMXDEV_STATE_GO && | ||
656 | dmxdev->filter[i].type == DMXDEV_TYPE_SEC && | ||
657 | dmxdev->filter[i].params.sec.pid == para->pid) { | ||
658 | *secfeed = dmxdev->filter[i].feed.sec; | ||
659 | break; | ||
660 | } | ||
661 | } | ||
662 | |||
663 | /* if no feed found, try to allocate new one */ | ||
664 | if (!*secfeed) { | ||
665 | ret = dmxdev->demux->allocate_section_feed(dmxdev->demux, | ||
666 | secfeed, | ||
667 | dvb_dmxdev_section_callback); | ||
668 | if (ret < 0) { | ||
669 | printk("DVB (%s): could not alloc feed\n", | ||
670 | __func__); | ||
671 | return ret; | ||
672 | } | ||
673 | |||
674 | ret = (*secfeed)->set(*secfeed, para->pid, 32768, | ||
675 | (para->flags & DMX_CHECK_CRC) ? 1 : 0); | ||
676 | if (ret < 0) { | ||
677 | printk("DVB (%s): could not set feed\n", | ||
678 | __func__); | ||
679 | dvb_dmxdev_feed_restart(filter); | ||
680 | return ret; | ||
681 | } | ||
682 | } else { | ||
683 | dvb_dmxdev_feed_stop(filter); | ||
684 | } | ||
685 | |||
686 | ret = (*secfeed)->allocate_filter(*secfeed, secfilter); | ||
687 | if (ret < 0) { | ||
688 | dvb_dmxdev_feed_restart(filter); | ||
689 | filter->feed.sec->start_filtering(*secfeed); | ||
690 | dprintk("could not get filter\n"); | ||
691 | return ret; | ||
692 | } | ||
693 | |||
694 | (*secfilter)->priv = filter; | ||
695 | |||
696 | memcpy(&((*secfilter)->filter_value[3]), | ||
697 | &(para->filter.filter[1]), DMX_FILTER_SIZE - 1); | ||
698 | memcpy(&(*secfilter)->filter_mask[3], | ||
699 | ¶->filter.mask[1], DMX_FILTER_SIZE - 1); | ||
700 | memcpy(&(*secfilter)->filter_mode[3], | ||
701 | ¶->filter.mode[1], DMX_FILTER_SIZE - 1); | ||
702 | |||
703 | (*secfilter)->filter_value[0] = para->filter.filter[0]; | ||
704 | (*secfilter)->filter_mask[0] = para->filter.mask[0]; | ||
705 | (*secfilter)->filter_mode[0] = para->filter.mode[0]; | ||
706 | (*secfilter)->filter_mask[1] = 0; | ||
707 | (*secfilter)->filter_mask[2] = 0; | ||
708 | |||
709 | filter->todo = 0; | ||
710 | |||
711 | ret = filter->feed.sec->start_filtering(filter->feed.sec); | ||
712 | if (ret < 0) | ||
713 | return ret; | ||
714 | |||
715 | dvb_dmxdev_filter_timer(filter); | ||
716 | break; | ||
717 | } | ||
718 | case DMXDEV_TYPE_PES: | ||
719 | list_for_each_entry(feed, &filter->feed.ts, next) { | ||
720 | ret = dvb_dmxdev_start_feed(dmxdev, filter, feed); | ||
721 | if (ret < 0) { | ||
722 | dvb_dmxdev_filter_stop(filter); | ||
723 | return ret; | ||
724 | } | ||
725 | } | ||
726 | break; | ||
727 | default: | ||
728 | return -EINVAL; | ||
729 | } | ||
730 | |||
731 | dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO); | ||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | static int dvb_demux_open(struct inode *inode, struct file *file) | ||
736 | { | ||
737 | struct dvb_device *dvbdev = file->private_data; | ||
738 | struct dmxdev *dmxdev = dvbdev->priv; | ||
739 | int i; | ||
740 | struct dmxdev_filter *dmxdevfilter; | ||
741 | |||
742 | if (!dmxdev->filter) | ||
743 | return -EINVAL; | ||
744 | |||
745 | if (mutex_lock_interruptible(&dmxdev->mutex)) | ||
746 | return -ERESTARTSYS; | ||
747 | |||
748 | for (i = 0; i < dmxdev->filternum; i++) | ||
749 | if (dmxdev->filter[i].state == DMXDEV_STATE_FREE) | ||
750 | break; | ||
751 | |||
752 | if (i == dmxdev->filternum) { | ||
753 | mutex_unlock(&dmxdev->mutex); | ||
754 | return -EMFILE; | ||
755 | } | ||
756 | |||
757 | dmxdevfilter = &dmxdev->filter[i]; | ||
758 | mutex_init(&dmxdevfilter->mutex); | ||
759 | file->private_data = dmxdevfilter; | ||
760 | |||
761 | dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); | ||
762 | dmxdevfilter->type = DMXDEV_TYPE_NONE; | ||
763 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); | ||
764 | init_timer(&dmxdevfilter->timer); | ||
765 | |||
766 | dvbdev->users++; | ||
767 | |||
768 | mutex_unlock(&dmxdev->mutex); | ||
769 | return 0; | ||
770 | } | ||
771 | |||
772 | static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, | ||
773 | struct dmxdev_filter *dmxdevfilter) | ||
774 | { | ||
775 | mutex_lock(&dmxdev->mutex); | ||
776 | mutex_lock(&dmxdevfilter->mutex); | ||
777 | |||
778 | dvb_dmxdev_filter_stop(dmxdevfilter); | ||
779 | dvb_dmxdev_filter_reset(dmxdevfilter); | ||
780 | |||
781 | if (dmxdevfilter->buffer.data) { | ||
782 | void *mem = dmxdevfilter->buffer.data; | ||
783 | |||
784 | spin_lock_irq(&dmxdev->lock); | ||
785 | dmxdevfilter->buffer.data = NULL; | ||
786 | spin_unlock_irq(&dmxdev->lock); | ||
787 | vfree(mem); | ||
788 | } | ||
789 | |||
790 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE); | ||
791 | wake_up(&dmxdevfilter->buffer.queue); | ||
792 | mutex_unlock(&dmxdevfilter->mutex); | ||
793 | mutex_unlock(&dmxdev->mutex); | ||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | static inline void invert_mode(dmx_filter_t *filter) | ||
798 | { | ||
799 | int i; | ||
800 | |||
801 | for (i = 0; i < DMX_FILTER_SIZE; i++) | ||
802 | filter->mode[i] ^= 0xff; | ||
803 | } | ||
804 | |||
805 | static int dvb_dmxdev_add_pid(struct dmxdev *dmxdev, | ||
806 | struct dmxdev_filter *filter, u16 pid) | ||
807 | { | ||
808 | struct dmxdev_feed *feed; | ||
809 | |||
810 | if ((filter->type != DMXDEV_TYPE_PES) || | ||
811 | (filter->state < DMXDEV_STATE_SET)) | ||
812 | return -EINVAL; | ||
813 | |||
814 | /* only TS packet filters may have multiple PIDs */ | ||
815 | if ((filter->params.pes.output != DMX_OUT_TSDEMUX_TAP) && | ||
816 | (!list_empty(&filter->feed.ts))) | ||
817 | return -EINVAL; | ||
818 | |||
819 | feed = kzalloc(sizeof(struct dmxdev_feed), GFP_KERNEL); | ||
820 | if (feed == NULL) | ||
821 | return -ENOMEM; | ||
822 | |||
823 | feed->pid = pid; | ||
824 | list_add(&feed->next, &filter->feed.ts); | ||
825 | |||
826 | if (filter->state >= DMXDEV_STATE_GO) | ||
827 | return dvb_dmxdev_start_feed(dmxdev, filter, feed); | ||
828 | |||
829 | return 0; | ||
830 | } | ||
831 | |||
832 | static int dvb_dmxdev_remove_pid(struct dmxdev *dmxdev, | ||
833 | struct dmxdev_filter *filter, u16 pid) | ||
834 | { | ||
835 | struct dmxdev_feed *feed, *tmp; | ||
836 | |||
837 | if ((filter->type != DMXDEV_TYPE_PES) || | ||
838 | (filter->state < DMXDEV_STATE_SET)) | ||
839 | return -EINVAL; | ||
840 | |||
841 | list_for_each_entry_safe(feed, tmp, &filter->feed.ts, next) { | ||
842 | if ((feed->pid == pid) && (feed->ts != NULL)) { | ||
843 | feed->ts->stop_filtering(feed->ts); | ||
844 | filter->dev->demux->release_ts_feed(filter->dev->demux, | ||
845 | feed->ts); | ||
846 | list_del(&feed->next); | ||
847 | kfree(feed); | ||
848 | } | ||
849 | } | ||
850 | |||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev, | ||
855 | struct dmxdev_filter *dmxdevfilter, | ||
856 | struct dmx_sct_filter_params *params) | ||
857 | { | ||
858 | dprintk("function : %s\n", __func__); | ||
859 | |||
860 | dvb_dmxdev_filter_stop(dmxdevfilter); | ||
861 | |||
862 | dmxdevfilter->type = DMXDEV_TYPE_SEC; | ||
863 | memcpy(&dmxdevfilter->params.sec, | ||
864 | params, sizeof(struct dmx_sct_filter_params)); | ||
865 | invert_mode(&dmxdevfilter->params.sec.filter); | ||
866 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); | ||
867 | |||
868 | if (params->flags & DMX_IMMEDIATE_START) | ||
869 | return dvb_dmxdev_filter_start(dmxdevfilter); | ||
870 | |||
871 | return 0; | ||
872 | } | ||
873 | |||
874 | static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev, | ||
875 | struct dmxdev_filter *dmxdevfilter, | ||
876 | struct dmx_pes_filter_params *params) | ||
877 | { | ||
878 | int ret; | ||
879 | |||
880 | dvb_dmxdev_filter_stop(dmxdevfilter); | ||
881 | dvb_dmxdev_filter_reset(dmxdevfilter); | ||
882 | |||
883 | if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0) | ||
884 | return -EINVAL; | ||
885 | |||
886 | dmxdevfilter->type = DMXDEV_TYPE_PES; | ||
887 | memcpy(&dmxdevfilter->params, params, | ||
888 | sizeof(struct dmx_pes_filter_params)); | ||
889 | INIT_LIST_HEAD(&dmxdevfilter->feed.ts); | ||
890 | |||
891 | dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); | ||
892 | |||
893 | ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter, | ||
894 | dmxdevfilter->params.pes.pid); | ||
895 | if (ret < 0) | ||
896 | return ret; | ||
897 | |||
898 | if (params->flags & DMX_IMMEDIATE_START) | ||
899 | return dvb_dmxdev_filter_start(dmxdevfilter); | ||
900 | |||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil, | ||
905 | struct file *file, char __user *buf, | ||
906 | size_t count, loff_t *ppos) | ||
907 | { | ||
908 | int result, hcount; | ||
909 | int done = 0; | ||
910 | |||
911 | if (dfil->todo <= 0) { | ||
912 | hcount = 3 + dfil->todo; | ||
913 | if (hcount > count) | ||
914 | hcount = count; | ||
915 | result = dvb_dmxdev_buffer_read(&dfil->buffer, | ||
916 | file->f_flags & O_NONBLOCK, | ||
917 | buf, hcount, ppos); | ||
918 | if (result < 0) { | ||
919 | dfil->todo = 0; | ||
920 | return result; | ||
921 | } | ||
922 | if (copy_from_user(dfil->secheader - dfil->todo, buf, result)) | ||
923 | return -EFAULT; | ||
924 | buf += result; | ||
925 | done = result; | ||
926 | count -= result; | ||
927 | dfil->todo -= result; | ||
928 | if (dfil->todo > -3) | ||
929 | return done; | ||
930 | dfil->todo = ((dfil->secheader[1] << 8) | dfil->secheader[2]) & 0xfff; | ||
931 | if (!count) | ||
932 | return done; | ||
933 | } | ||
934 | if (count > dfil->todo) | ||
935 | count = dfil->todo; | ||
936 | result = dvb_dmxdev_buffer_read(&dfil->buffer, | ||
937 | file->f_flags & O_NONBLOCK, | ||
938 | buf, count, ppos); | ||
939 | if (result < 0) | ||
940 | return result; | ||
941 | dfil->todo -= result; | ||
942 | return (result + done); | ||
943 | } | ||
944 | |||
945 | static ssize_t | ||
946 | dvb_demux_read(struct file *file, char __user *buf, size_t count, | ||
947 | loff_t *ppos) | ||
948 | { | ||
949 | struct dmxdev_filter *dmxdevfilter = file->private_data; | ||
950 | int ret; | ||
951 | |||
952 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) | ||
953 | return -ERESTARTSYS; | ||
954 | |||
955 | if (dmxdevfilter->type == DMXDEV_TYPE_SEC) | ||
956 | ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos); | ||
957 | else | ||
958 | ret = dvb_dmxdev_buffer_read(&dmxdevfilter->buffer, | ||
959 | file->f_flags & O_NONBLOCK, | ||
960 | buf, count, ppos); | ||
961 | |||
962 | mutex_unlock(&dmxdevfilter->mutex); | ||
963 | return ret; | ||
964 | } | ||
965 | |||
966 | static int dvb_demux_do_ioctl(struct file *file, | ||
967 | unsigned int cmd, void *parg) | ||
968 | { | ||
969 | struct dmxdev_filter *dmxdevfilter = file->private_data; | ||
970 | struct dmxdev *dmxdev = dmxdevfilter->dev; | ||
971 | unsigned long arg = (unsigned long)parg; | ||
972 | int ret = 0; | ||
973 | |||
974 | if (mutex_lock_interruptible(&dmxdev->mutex)) | ||
975 | return -ERESTARTSYS; | ||
976 | |||
977 | switch (cmd) { | ||
978 | case DMX_START: | ||
979 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
980 | mutex_unlock(&dmxdev->mutex); | ||
981 | return -ERESTARTSYS; | ||
982 | } | ||
983 | if (dmxdevfilter->state < DMXDEV_STATE_SET) | ||
984 | ret = -EINVAL; | ||
985 | else | ||
986 | ret = dvb_dmxdev_filter_start(dmxdevfilter); | ||
987 | mutex_unlock(&dmxdevfilter->mutex); | ||
988 | break; | ||
989 | |||
990 | case DMX_STOP: | ||
991 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
992 | mutex_unlock(&dmxdev->mutex); | ||
993 | return -ERESTARTSYS; | ||
994 | } | ||
995 | ret = dvb_dmxdev_filter_stop(dmxdevfilter); | ||
996 | mutex_unlock(&dmxdevfilter->mutex); | ||
997 | break; | ||
998 | |||
999 | case DMX_SET_FILTER: | ||
1000 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
1001 | mutex_unlock(&dmxdev->mutex); | ||
1002 | return -ERESTARTSYS; | ||
1003 | } | ||
1004 | ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, parg); | ||
1005 | mutex_unlock(&dmxdevfilter->mutex); | ||
1006 | break; | ||
1007 | |||
1008 | case DMX_SET_PES_FILTER: | ||
1009 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
1010 | mutex_unlock(&dmxdev->mutex); | ||
1011 | return -ERESTARTSYS; | ||
1012 | } | ||
1013 | ret = dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, parg); | ||
1014 | mutex_unlock(&dmxdevfilter->mutex); | ||
1015 | break; | ||
1016 | |||
1017 | case DMX_SET_BUFFER_SIZE: | ||
1018 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
1019 | mutex_unlock(&dmxdev->mutex); | ||
1020 | return -ERESTARTSYS; | ||
1021 | } | ||
1022 | ret = dvb_dmxdev_set_buffer_size(dmxdevfilter, arg); | ||
1023 | mutex_unlock(&dmxdevfilter->mutex); | ||
1024 | break; | ||
1025 | |||
1026 | case DMX_GET_PES_PIDS: | ||
1027 | if (!dmxdev->demux->get_pes_pids) { | ||
1028 | ret = -EINVAL; | ||
1029 | break; | ||
1030 | } | ||
1031 | dmxdev->demux->get_pes_pids(dmxdev->demux, parg); | ||
1032 | break; | ||
1033 | |||
1034 | case DMX_GET_CAPS: | ||
1035 | if (!dmxdev->demux->get_caps) { | ||
1036 | ret = -EINVAL; | ||
1037 | break; | ||
1038 | } | ||
1039 | ret = dmxdev->demux->get_caps(dmxdev->demux, parg); | ||
1040 | break; | ||
1041 | |||
1042 | case DMX_SET_SOURCE: | ||
1043 | if (!dmxdev->demux->set_source) { | ||
1044 | ret = -EINVAL; | ||
1045 | break; | ||
1046 | } | ||
1047 | ret = dmxdev->demux->set_source(dmxdev->demux, parg); | ||
1048 | break; | ||
1049 | |||
1050 | case DMX_GET_STC: | ||
1051 | if (!dmxdev->demux->get_stc) { | ||
1052 | ret = -EINVAL; | ||
1053 | break; | ||
1054 | } | ||
1055 | ret = dmxdev->demux->get_stc(dmxdev->demux, | ||
1056 | ((struct dmx_stc *)parg)->num, | ||
1057 | &((struct dmx_stc *)parg)->stc, | ||
1058 | &((struct dmx_stc *)parg)->base); | ||
1059 | break; | ||
1060 | |||
1061 | case DMX_ADD_PID: | ||
1062 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
1063 | ret = -ERESTARTSYS; | ||
1064 | break; | ||
1065 | } | ||
1066 | ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter, *(u16 *)parg); | ||
1067 | mutex_unlock(&dmxdevfilter->mutex); | ||
1068 | break; | ||
1069 | |||
1070 | case DMX_REMOVE_PID: | ||
1071 | if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { | ||
1072 | ret = -ERESTARTSYS; | ||
1073 | break; | ||
1074 | } | ||
1075 | ret = dvb_dmxdev_remove_pid(dmxdev, dmxdevfilter, *(u16 *)parg); | ||
1076 | mutex_unlock(&dmxdevfilter->mutex); | ||
1077 | break; | ||
1078 | |||
1079 | default: | ||
1080 | ret = -EINVAL; | ||
1081 | break; | ||
1082 | } | ||
1083 | mutex_unlock(&dmxdev->mutex); | ||
1084 | return ret; | ||
1085 | } | ||
1086 | |||
1087 | static long dvb_demux_ioctl(struct file *file, unsigned int cmd, | ||
1088 | unsigned long arg) | ||
1089 | { | ||
1090 | return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl); | ||
1091 | } | ||
1092 | |||
1093 | static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) | ||
1094 | { | ||
1095 | struct dmxdev_filter *dmxdevfilter = file->private_data; | ||
1096 | unsigned int mask = 0; | ||
1097 | |||
1098 | if (!dmxdevfilter) | ||
1099 | return -EINVAL; | ||
1100 | |||
1101 | poll_wait(file, &dmxdevfilter->buffer.queue, wait); | ||
1102 | |||
1103 | if (dmxdevfilter->state != DMXDEV_STATE_GO && | ||
1104 | dmxdevfilter->state != DMXDEV_STATE_DONE && | ||
1105 | dmxdevfilter->state != DMXDEV_STATE_TIMEDOUT) | ||
1106 | return 0; | ||
1107 | |||
1108 | if (dmxdevfilter->buffer.error) | ||
1109 | mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); | ||
1110 | |||
1111 | if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer)) | ||
1112 | mask |= (POLLIN | POLLRDNORM | POLLPRI); | ||
1113 | |||
1114 | return mask; | ||
1115 | } | ||
1116 | |||
1117 | static int dvb_demux_release(struct inode *inode, struct file *file) | ||
1118 | { | ||
1119 | struct dmxdev_filter *dmxdevfilter = file->private_data; | ||
1120 | struct dmxdev *dmxdev = dmxdevfilter->dev; | ||
1121 | |||
1122 | int ret; | ||
1123 | |||
1124 | ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter); | ||
1125 | |||
1126 | mutex_lock(&dmxdev->mutex); | ||
1127 | dmxdev->dvbdev->users--; | ||
1128 | if(dmxdev->dvbdev->users==1 && dmxdev->exit==1) { | ||
1129 | fops_put(file->f_op); | ||
1130 | file->f_op = NULL; | ||
1131 | mutex_unlock(&dmxdev->mutex); | ||
1132 | wake_up(&dmxdev->dvbdev->wait_queue); | ||
1133 | } else | ||
1134 | mutex_unlock(&dmxdev->mutex); | ||
1135 | |||
1136 | return ret; | ||
1137 | } | ||
1138 | |||
1139 | static const struct file_operations dvb_demux_fops = { | ||
1140 | .owner = THIS_MODULE, | ||
1141 | .read = dvb_demux_read, | ||
1142 | .unlocked_ioctl = dvb_demux_ioctl, | ||
1143 | .open = dvb_demux_open, | ||
1144 | .release = dvb_demux_release, | ||
1145 | .poll = dvb_demux_poll, | ||
1146 | .llseek = default_llseek, | ||
1147 | }; | ||
1148 | |||
1149 | static struct dvb_device dvbdev_demux = { | ||
1150 | .priv = NULL, | ||
1151 | .users = 1, | ||
1152 | .writers = 1, | ||
1153 | .fops = &dvb_demux_fops | ||
1154 | }; | ||
1155 | |||
1156 | static int dvb_dvr_do_ioctl(struct file *file, | ||
1157 | unsigned int cmd, void *parg) | ||
1158 | { | ||
1159 | struct dvb_device *dvbdev = file->private_data; | ||
1160 | struct dmxdev *dmxdev = dvbdev->priv; | ||
1161 | unsigned long arg = (unsigned long)parg; | ||
1162 | int ret; | ||
1163 | |||
1164 | if (mutex_lock_interruptible(&dmxdev->mutex)) | ||
1165 | return -ERESTARTSYS; | ||
1166 | |||
1167 | switch (cmd) { | ||
1168 | case DMX_SET_BUFFER_SIZE: | ||
1169 | ret = dvb_dvr_set_buffer_size(dmxdev, arg); | ||
1170 | break; | ||
1171 | |||
1172 | default: | ||
1173 | ret = -EINVAL; | ||
1174 | break; | ||
1175 | } | ||
1176 | mutex_unlock(&dmxdev->mutex); | ||
1177 | return ret; | ||
1178 | } | ||
1179 | |||
1180 | static long dvb_dvr_ioctl(struct file *file, | ||
1181 | unsigned int cmd, unsigned long arg) | ||
1182 | { | ||
1183 | return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl); | ||
1184 | } | ||
1185 | |||
1186 | static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) | ||
1187 | { | ||
1188 | struct dvb_device *dvbdev = file->private_data; | ||
1189 | struct dmxdev *dmxdev = dvbdev->priv; | ||
1190 | unsigned int mask = 0; | ||
1191 | |||
1192 | dprintk("function : %s\n", __func__); | ||
1193 | |||
1194 | poll_wait(file, &dmxdev->dvr_buffer.queue, wait); | ||
1195 | |||
1196 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) { | ||
1197 | if (dmxdev->dvr_buffer.error) | ||
1198 | mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR); | ||
1199 | |||
1200 | if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer)) | ||
1201 | mask |= (POLLIN | POLLRDNORM | POLLPRI); | ||
1202 | } else | ||
1203 | mask |= (POLLOUT | POLLWRNORM | POLLPRI); | ||
1204 | |||
1205 | return mask; | ||
1206 | } | ||
1207 | |||
1208 | static const struct file_operations dvb_dvr_fops = { | ||
1209 | .owner = THIS_MODULE, | ||
1210 | .read = dvb_dvr_read, | ||
1211 | .write = dvb_dvr_write, | ||
1212 | .unlocked_ioctl = dvb_dvr_ioctl, | ||
1213 | .open = dvb_dvr_open, | ||
1214 | .release = dvb_dvr_release, | ||
1215 | .poll = dvb_dvr_poll, | ||
1216 | .llseek = default_llseek, | ||
1217 | }; | ||
1218 | |||
1219 | static struct dvb_device dvbdev_dvr = { | ||
1220 | .priv = NULL, | ||
1221 | .readers = 1, | ||
1222 | .users = 1, | ||
1223 | .fops = &dvb_dvr_fops | ||
1224 | }; | ||
1225 | |||
1226 | int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) | ||
1227 | { | ||
1228 | int i; | ||
1229 | |||
1230 | if (dmxdev->demux->open(dmxdev->demux) < 0) | ||
1231 | return -EUSERS; | ||
1232 | |||
1233 | dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter)); | ||
1234 | if (!dmxdev->filter) | ||
1235 | return -ENOMEM; | ||
1236 | |||
1237 | mutex_init(&dmxdev->mutex); | ||
1238 | spin_lock_init(&dmxdev->lock); | ||
1239 | for (i = 0; i < dmxdev->filternum; i++) { | ||
1240 | dmxdev->filter[i].dev = dmxdev; | ||
1241 | dmxdev->filter[i].buffer.data = NULL; | ||
1242 | dvb_dmxdev_filter_state_set(&dmxdev->filter[i], | ||
1243 | DMXDEV_STATE_FREE); | ||
1244 | } | ||
1245 | |||
1246 | dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, | ||
1247 | DVB_DEVICE_DEMUX); | ||
1248 | dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, | ||
1249 | dmxdev, DVB_DEVICE_DVR); | ||
1250 | |||
1251 | dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); | ||
1252 | |||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1256 | EXPORT_SYMBOL(dvb_dmxdev_init); | ||
1257 | |||
1258 | void dvb_dmxdev_release(struct dmxdev *dmxdev) | ||
1259 | { | ||
1260 | dmxdev->exit=1; | ||
1261 | if (dmxdev->dvbdev->users > 1) { | ||
1262 | wait_event(dmxdev->dvbdev->wait_queue, | ||
1263 | dmxdev->dvbdev->users==1); | ||
1264 | } | ||
1265 | if (dmxdev->dvr_dvbdev->users > 1) { | ||
1266 | wait_event(dmxdev->dvr_dvbdev->wait_queue, | ||
1267 | dmxdev->dvr_dvbdev->users==1); | ||
1268 | } | ||
1269 | |||
1270 | dvb_unregister_device(dmxdev->dvbdev); | ||
1271 | dvb_unregister_device(dmxdev->dvr_dvbdev); | ||
1272 | |||
1273 | vfree(dmxdev->filter); | ||
1274 | dmxdev->filter = NULL; | ||
1275 | dmxdev->demux->close(dmxdev->demux); | ||
1276 | } | ||
1277 | |||
1278 | EXPORT_SYMBOL(dvb_dmxdev_release); | ||
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h new file mode 100644 index 00000000000..02ebe28f830 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dmxdev.h | |||
@@ -0,0 +1,118 @@ | |||
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_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c new file mode 100644 index 00000000000..7ea517b7e18 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c | |||
@@ -0,0 +1,1749 @@ | |||
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 ((count - fragpos) < fraglen) | ||
1310 | fraglen = count - fragpos; | ||
1311 | |||
1312 | fragbuf[0] = connection_id; | ||
1313 | fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00; | ||
1314 | status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen); | ||
1315 | if (status) { | ||
1316 | status = -EFAULT; | ||
1317 | goto exit; | ||
1318 | } | ||
1319 | |||
1320 | timeout = jiffies + HZ / 2; | ||
1321 | written = 0; | ||
1322 | while (!time_after(jiffies, timeout)) { | ||
1323 | /* check the CAM hasn't been removed/reset in the meantime */ | ||
1324 | if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) { | ||
1325 | status = -EIO; | ||
1326 | goto exit; | ||
1327 | } | ||
1328 | |||
1329 | mutex_lock(&ca->slot_info[slot].slot_lock); | ||
1330 | status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2); | ||
1331 | mutex_unlock(&ca->slot_info[slot].slot_lock); | ||
1332 | if (status == (fraglen + 2)) { | ||
1333 | written = 1; | ||
1334 | break; | ||
1335 | } | ||
1336 | if (status != -EAGAIN) | ||
1337 | goto exit; | ||
1338 | |||
1339 | msleep(1); | ||
1340 | } | ||
1341 | if (!written) { | ||
1342 | status = -EIO; | ||
1343 | goto exit; | ||
1344 | } | ||
1345 | |||
1346 | fragpos += fraglen; | ||
1347 | } | ||
1348 | status = count + 2; | ||
1349 | |||
1350 | exit: | ||
1351 | return status; | ||
1352 | } | ||
1353 | |||
1354 | |||
1355 | /** | ||
1356 | * Condition for waking up in dvb_ca_en50221_io_read_condition | ||
1357 | */ | ||
1358 | static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, | ||
1359 | int *result, int *_slot) | ||
1360 | { | ||
1361 | int slot; | ||
1362 | int slot_count = 0; | ||
1363 | int idx; | ||
1364 | size_t fraglen; | ||
1365 | int connection_id = -1; | ||
1366 | int found = 0; | ||
1367 | u8 hdr[2]; | ||
1368 | |||
1369 | slot = ca->next_read_slot; | ||
1370 | while ((slot_count < ca->slot_count) && (!found)) { | ||
1371 | if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) | ||
1372 | goto nextslot; | ||
1373 | |||
1374 | if (ca->slot_info[slot].rx_buffer.data == NULL) { | ||
1375 | return 0; | ||
1376 | } | ||
1377 | |||
1378 | idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen); | ||
1379 | while (idx != -1) { | ||
1380 | dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2); | ||
1381 | if (connection_id == -1) | ||
1382 | connection_id = hdr[0]; | ||
1383 | if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) { | ||
1384 | *_slot = slot; | ||
1385 | found = 1; | ||
1386 | break; | ||
1387 | } | ||
1388 | |||
1389 | idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); | ||
1390 | } | ||
1391 | |||
1392 | nextslot: | ||
1393 | slot = (slot + 1) % ca->slot_count; | ||
1394 | slot_count++; | ||
1395 | } | ||
1396 | |||
1397 | ca->next_read_slot = slot; | ||
1398 | return found; | ||
1399 | } | ||
1400 | |||
1401 | |||
1402 | /** | ||
1403 | * Implementation of read() syscall. | ||
1404 | * | ||
1405 | * @param file File structure. | ||
1406 | * @param buf Destination buffer. | ||
1407 | * @param count Size of destination buffer. | ||
1408 | * @param ppos Position in file (ignored). | ||
1409 | * | ||
1410 | * @return Number of bytes read, or <0 on error. | ||
1411 | */ | ||
1412 | static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, | ||
1413 | size_t count, loff_t * ppos) | ||
1414 | { | ||
1415 | struct dvb_device *dvbdev = file->private_data; | ||
1416 | struct dvb_ca_private *ca = dvbdev->priv; | ||
1417 | int status; | ||
1418 | int result = 0; | ||
1419 | u8 hdr[2]; | ||
1420 | int slot; | ||
1421 | int connection_id = -1; | ||
1422 | size_t idx, idx2; | ||
1423 | int last_fragment = 0; | ||
1424 | size_t fraglen; | ||
1425 | int pktlen; | ||
1426 | int dispose = 0; | ||
1427 | |||
1428 | dprintk("%s\n", __func__); | ||
1429 | |||
1430 | /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */ | ||
1431 | if (count < 2) | ||
1432 | return -EINVAL; | ||
1433 | |||
1434 | /* wait for some data */ | ||
1435 | if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot)) == 0) { | ||
1436 | |||
1437 | /* if we're in nonblocking mode, exit immediately */ | ||
1438 | if (file->f_flags & O_NONBLOCK) | ||
1439 | return -EWOULDBLOCK; | ||
1440 | |||
1441 | /* wait for some data */ | ||
1442 | status = wait_event_interruptible(ca->wait_queue, | ||
1443 | dvb_ca_en50221_io_read_condition | ||
1444 | (ca, &result, &slot)); | ||
1445 | } | ||
1446 | if ((status < 0) || (result < 0)) { | ||
1447 | if (result) | ||
1448 | return result; | ||
1449 | return status; | ||
1450 | } | ||
1451 | |||
1452 | idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen); | ||
1453 | pktlen = 2; | ||
1454 | do { | ||
1455 | if (idx == -1) { | ||
1456 | printk("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n", ca->dvbdev->adapter->num); | ||
1457 | status = -EIO; | ||
1458 | goto exit; | ||
1459 | } | ||
1460 | |||
1461 | dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2); | ||
1462 | if (connection_id == -1) | ||
1463 | connection_id = hdr[0]; | ||
1464 | if (hdr[0] == connection_id) { | ||
1465 | if (pktlen < count) { | ||
1466 | if ((pktlen + fraglen - 2) > count) { | ||
1467 | fraglen = count - pktlen; | ||
1468 | } else { | ||
1469 | fraglen -= 2; | ||
1470 | } | ||
1471 | |||
1472 | if ((status = dvb_ringbuffer_pkt_read_user(&ca->slot_info[slot].rx_buffer, idx, 2, | ||
1473 | buf + pktlen, fraglen)) < 0) { | ||
1474 | goto exit; | ||
1475 | } | ||
1476 | pktlen += fraglen; | ||
1477 | } | ||
1478 | |||
1479 | if ((hdr[1] & 0x80) == 0) | ||
1480 | last_fragment = 1; | ||
1481 | dispose = 1; | ||
1482 | } | ||
1483 | |||
1484 | idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); | ||
1485 | if (dispose) | ||
1486 | dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx); | ||
1487 | idx = idx2; | ||
1488 | dispose = 0; | ||
1489 | } while (!last_fragment); | ||
1490 | |||
1491 | hdr[0] = slot; | ||
1492 | hdr[1] = connection_id; | ||
1493 | status = copy_to_user(buf, hdr, 2); | ||
1494 | if (status) { | ||
1495 | status = -EFAULT; | ||
1496 | goto exit; | ||
1497 | } | ||
1498 | status = pktlen; | ||
1499 | |||
1500 | exit: | ||
1501 | return status; | ||
1502 | } | ||
1503 | |||
1504 | |||
1505 | /** | ||
1506 | * Implementation of file open syscall. | ||
1507 | * | ||
1508 | * @param inode Inode concerned. | ||
1509 | * @param file File concerned. | ||
1510 | * | ||
1511 | * @return 0 on success, <0 on failure. | ||
1512 | */ | ||
1513 | static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) | ||
1514 | { | ||
1515 | struct dvb_device *dvbdev = file->private_data; | ||
1516 | struct dvb_ca_private *ca = dvbdev->priv; | ||
1517 | int err; | ||
1518 | int i; | ||
1519 | |||
1520 | dprintk("%s\n", __func__); | ||
1521 | |||
1522 | if (!try_module_get(ca->pub->owner)) | ||
1523 | return -EIO; | ||
1524 | |||
1525 | err = dvb_generic_open(inode, file); | ||
1526 | if (err < 0) { | ||
1527 | module_put(ca->pub->owner); | ||
1528 | return err; | ||
1529 | } | ||
1530 | |||
1531 | for (i = 0; i < ca->slot_count; i++) { | ||
1532 | |||
1533 | if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) { | ||
1534 | if (ca->slot_info[i].rx_buffer.data != NULL) { | ||
1535 | /* it is safe to call this here without locks because | ||
1536 | * ca->open == 0. Data is not read in this case */ | ||
1537 | dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer); | ||
1538 | } | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | ca->open = 1; | ||
1543 | dvb_ca_en50221_thread_update_delay(ca); | ||
1544 | dvb_ca_en50221_thread_wakeup(ca); | ||
1545 | |||
1546 | return 0; | ||
1547 | } | ||
1548 | |||
1549 | |||
1550 | /** | ||
1551 | * Implementation of file close syscall. | ||
1552 | * | ||
1553 | * @param inode Inode concerned. | ||
1554 | * @param file File concerned. | ||
1555 | * | ||
1556 | * @return 0 on success, <0 on failure. | ||
1557 | */ | ||
1558 | static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) | ||
1559 | { | ||
1560 | struct dvb_device *dvbdev = file->private_data; | ||
1561 | struct dvb_ca_private *ca = dvbdev->priv; | ||
1562 | int err; | ||
1563 | |||
1564 | dprintk("%s\n", __func__); | ||
1565 | |||
1566 | /* mark the CA device as closed */ | ||
1567 | ca->open = 0; | ||
1568 | dvb_ca_en50221_thread_update_delay(ca); | ||
1569 | |||
1570 | err = dvb_generic_release(inode, file); | ||
1571 | |||
1572 | module_put(ca->pub->owner); | ||
1573 | |||
1574 | return err; | ||
1575 | } | ||
1576 | |||
1577 | |||
1578 | /** | ||
1579 | * Implementation of poll() syscall. | ||
1580 | * | ||
1581 | * @param file File concerned. | ||
1582 | * @param wait poll wait table. | ||
1583 | * | ||
1584 | * @return Standard poll mask. | ||
1585 | */ | ||
1586 | static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait) | ||
1587 | { | ||
1588 | struct dvb_device *dvbdev = file->private_data; | ||
1589 | struct dvb_ca_private *ca = dvbdev->priv; | ||
1590 | unsigned int mask = 0; | ||
1591 | int slot; | ||
1592 | int result = 0; | ||
1593 | |||
1594 | dprintk("%s\n", __func__); | ||
1595 | |||
1596 | if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { | ||
1597 | mask |= POLLIN; | ||
1598 | } | ||
1599 | |||
1600 | /* if there is something, return now */ | ||
1601 | if (mask) | ||
1602 | return mask; | ||
1603 | |||
1604 | /* wait for something to happen */ | ||
1605 | poll_wait(file, &ca->wait_queue, wait); | ||
1606 | |||
1607 | if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { | ||
1608 | mask |= POLLIN; | ||
1609 | } | ||
1610 | |||
1611 | return mask; | ||
1612 | } | ||
1613 | EXPORT_SYMBOL(dvb_ca_en50221_init); | ||
1614 | |||
1615 | |||
1616 | static const struct file_operations dvb_ca_fops = { | ||
1617 | .owner = THIS_MODULE, | ||
1618 | .read = dvb_ca_en50221_io_read, | ||
1619 | .write = dvb_ca_en50221_io_write, | ||
1620 | .unlocked_ioctl = dvb_ca_en50221_io_ioctl, | ||
1621 | .open = dvb_ca_en50221_io_open, | ||
1622 | .release = dvb_ca_en50221_io_release, | ||
1623 | .poll = dvb_ca_en50221_io_poll, | ||
1624 | .llseek = noop_llseek, | ||
1625 | }; | ||
1626 | |||
1627 | static struct dvb_device dvbdev_ca = { | ||
1628 | .priv = NULL, | ||
1629 | .users = 1, | ||
1630 | .readers = 1, | ||
1631 | .writers = 1, | ||
1632 | .fops = &dvb_ca_fops, | ||
1633 | }; | ||
1634 | |||
1635 | |||
1636 | /* ******************************************************************************** */ | ||
1637 | /* Initialisation/shutdown functions */ | ||
1638 | |||
1639 | |||
1640 | /** | ||
1641 | * Initialise a new DVB CA EN50221 interface device. | ||
1642 | * | ||
1643 | * @param dvb_adapter DVB adapter to attach the new CA device to. | ||
1644 | * @param ca The dvb_ca instance. | ||
1645 | * @param flags Flags describing the CA device (DVB_CA_FLAG_*). | ||
1646 | * @param slot_count Number of slots supported. | ||
1647 | * | ||
1648 | * @return 0 on success, nonzero on failure | ||
1649 | */ | ||
1650 | int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, | ||
1651 | struct dvb_ca_en50221 *pubca, int flags, int slot_count) | ||
1652 | { | ||
1653 | int ret; | ||
1654 | struct dvb_ca_private *ca = NULL; | ||
1655 | int i; | ||
1656 | |||
1657 | dprintk("%s\n", __func__); | ||
1658 | |||
1659 | if (slot_count < 1) | ||
1660 | return -EINVAL; | ||
1661 | |||
1662 | /* initialise the system data */ | ||
1663 | if ((ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) { | ||
1664 | ret = -ENOMEM; | ||
1665 | goto error; | ||
1666 | } | ||
1667 | ca->pub = pubca; | ||
1668 | ca->flags = flags; | ||
1669 | ca->slot_count = slot_count; | ||
1670 | if ((ca->slot_info = kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL)) == NULL) { | ||
1671 | ret = -ENOMEM; | ||
1672 | goto error; | ||
1673 | } | ||
1674 | init_waitqueue_head(&ca->wait_queue); | ||
1675 | ca->open = 0; | ||
1676 | ca->wakeup = 0; | ||
1677 | ca->next_read_slot = 0; | ||
1678 | pubca->private = ca; | ||
1679 | |||
1680 | /* register the DVB device */ | ||
1681 | ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA); | ||
1682 | if (ret) | ||
1683 | goto error; | ||
1684 | |||
1685 | /* now initialise each slot */ | ||
1686 | for (i = 0; i < slot_count; i++) { | ||
1687 | memset(&ca->slot_info[i], 0, sizeof(struct dvb_ca_slot)); | ||
1688 | ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; | ||
1689 | atomic_set(&ca->slot_info[i].camchange_count, 0); | ||
1690 | ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; | ||
1691 | mutex_init(&ca->slot_info[i].slot_lock); | ||
1692 | } | ||
1693 | |||
1694 | if (signal_pending(current)) { | ||
1695 | ret = -EINTR; | ||
1696 | goto error; | ||
1697 | } | ||
1698 | mb(); | ||
1699 | |||
1700 | /* create a kthread for monitoring this CA device */ | ||
1701 | ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i", | ||
1702 | ca->dvbdev->adapter->num, ca->dvbdev->id); | ||
1703 | if (IS_ERR(ca->thread)) { | ||
1704 | ret = PTR_ERR(ca->thread); | ||
1705 | printk("dvb_ca_init: failed to start kernel_thread (%d)\n", | ||
1706 | ret); | ||
1707 | goto error; | ||
1708 | } | ||
1709 | return 0; | ||
1710 | |||
1711 | error: | ||
1712 | if (ca != NULL) { | ||
1713 | if (ca->dvbdev != NULL) | ||
1714 | dvb_unregister_device(ca->dvbdev); | ||
1715 | kfree(ca->slot_info); | ||
1716 | kfree(ca); | ||
1717 | } | ||
1718 | pubca->private = NULL; | ||
1719 | return ret; | ||
1720 | } | ||
1721 | EXPORT_SYMBOL(dvb_ca_en50221_release); | ||
1722 | |||
1723 | |||
1724 | |||
1725 | /** | ||
1726 | * Release a DVB CA EN50221 interface device. | ||
1727 | * | ||
1728 | * @param ca_dev The dvb_device_t instance for the CA device. | ||
1729 | * @param ca The associated dvb_ca instance. | ||
1730 | */ | ||
1731 | void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca) | ||
1732 | { | ||
1733 | struct dvb_ca_private *ca = pubca->private; | ||
1734 | int i; | ||
1735 | |||
1736 | dprintk("%s\n", __func__); | ||
1737 | |||
1738 | /* shutdown the thread if there was one */ | ||
1739 | kthread_stop(ca->thread); | ||
1740 | |||
1741 | for (i = 0; i < ca->slot_count; i++) { | ||
1742 | dvb_ca_en50221_slot_shutdown(ca, i); | ||
1743 | vfree(ca->slot_info[i].rx_buffer.data); | ||
1744 | } | ||
1745 | kfree(ca->slot_info); | ||
1746 | dvb_unregister_device(ca->dvbdev); | ||
1747 | kfree(ca); | ||
1748 | pubca->private = NULL; | ||
1749 | } | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h new file mode 100644 index 00000000000..7df2e141187 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h | |||
@@ -0,0 +1,136 @@ | |||
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 new file mode 100644 index 00000000000..faa3671b649 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_demux.c | |||
@@ -0,0 +1,1299 @@ | |||
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 | #define dprintk_tscheck(x...) do { \ | ||
54 | if (dvb_demux_tscheck && printk_ratelimit()) \ | ||
55 | printk(x); \ | ||
56 | } while (0) | ||
57 | |||
58 | /****************************************************************************** | ||
59 | * static inlined helper functions | ||
60 | ******************************************************************************/ | ||
61 | |||
62 | static inline u16 section_length(const u8 *buf) | ||
63 | { | ||
64 | return 3 + ((buf[1] & 0x0f) << 8) + buf[2]; | ||
65 | } | ||
66 | |||
67 | static inline u16 ts_pid(const u8 *buf) | ||
68 | { | ||
69 | return ((buf[1] & 0x1f) << 8) + buf[2]; | ||
70 | } | ||
71 | |||
72 | static inline u8 payload(const u8 *tsp) | ||
73 | { | ||
74 | if (!(tsp[3] & 0x10)) // no payload? | ||
75 | return 0; | ||
76 | |||
77 | if (tsp[3] & 0x20) { // adaptation field? | ||
78 | if (tsp[4] > 183) // corrupted data? | ||
79 | return 0; | ||
80 | else | ||
81 | return 184 - 1 - tsp[4]; | ||
82 | } | ||
83 | |||
84 | return 184; | ||
85 | } | ||
86 | |||
87 | static u32 dvb_dmx_crc32(struct dvb_demux_feed *f, const u8 *src, size_t len) | ||
88 | { | ||
89 | return (f->feed.sec.crc_val = crc32_be(f->feed.sec.crc_val, src, len)); | ||
90 | } | ||
91 | |||
92 | static void dvb_dmx_memcopy(struct dvb_demux_feed *f, u8 *d, const u8 *s, | ||
93 | size_t len) | ||
94 | { | ||
95 | memcpy(d, s, len); | ||
96 | } | ||
97 | |||
98 | /****************************************************************************** | ||
99 | * Software filter functions | ||
100 | ******************************************************************************/ | ||
101 | |||
102 | static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed, | ||
103 | const u8 *buf) | ||
104 | { | ||
105 | int count = payload(buf); | ||
106 | int p; | ||
107 | //int ccok; | ||
108 | //u8 cc; | ||
109 | |||
110 | if (count == 0) | ||
111 | return -1; | ||
112 | |||
113 | p = 188 - count; | ||
114 | |||
115 | /* | ||
116 | cc = buf[3] & 0x0f; | ||
117 | ccok = ((feed->cc + 1) & 0x0f) == cc; | ||
118 | feed->cc = cc; | ||
119 | if (!ccok) | ||
120 | printk("missed packet!\n"); | ||
121 | */ | ||
122 | |||
123 | if (buf[1] & 0x40) // PUSI ? | ||
124 | feed->peslen = 0xfffa; | ||
125 | |||
126 | feed->peslen += count; | ||
127 | |||
128 | return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK); | ||
129 | } | ||
130 | |||
131 | static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed, | ||
132 | struct dvb_demux_filter *f) | ||
133 | { | ||
134 | u8 neq = 0; | ||
135 | int i; | ||
136 | |||
137 | for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) { | ||
138 | u8 xor = f->filter.filter_value[i] ^ feed->feed.sec.secbuf[i]; | ||
139 | |||
140 | if (f->maskandmode[i] & xor) | ||
141 | return 0; | ||
142 | |||
143 | neq |= f->maskandnotmode[i] & xor; | ||
144 | } | ||
145 | |||
146 | if (f->doneq && !neq) | ||
147 | return 0; | ||
148 | |||
149 | return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen, | ||
150 | NULL, 0, &f->filter, DMX_OK); | ||
151 | } | ||
152 | |||
153 | static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed) | ||
154 | { | ||
155 | struct dvb_demux *demux = feed->demux; | ||
156 | struct dvb_demux_filter *f = feed->filter; | ||
157 | struct dmx_section_feed *sec = &feed->feed.sec; | ||
158 | int section_syntax_indicator; | ||
159 | |||
160 | if (!sec->is_filtering) | ||
161 | return 0; | ||
162 | |||
163 | if (!f) | ||
164 | return 0; | ||
165 | |||
166 | if (sec->check_crc) { | ||
167 | section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0); | ||
168 | if (section_syntax_indicator && | ||
169 | demux->check_crc32(feed, sec->secbuf, sec->seclen)) | ||
170 | return -1; | ||
171 | } | ||
172 | |||
173 | do { | ||
174 | if (dvb_dmx_swfilter_sectionfilter(feed, f) < 0) | ||
175 | return -1; | ||
176 | } while ((f = f->next) && sec->is_filtering); | ||
177 | |||
178 | sec->seclen = 0; | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed) | ||
184 | { | ||
185 | struct dmx_section_feed *sec = &feed->feed.sec; | ||
186 | |||
187 | #ifdef DVB_DEMUX_SECTION_LOSS_LOG | ||
188 | if (sec->secbufp < sec->tsfeedp) { | ||
189 | int i, n = sec->tsfeedp - sec->secbufp; | ||
190 | |||
191 | /* | ||
192 | * Section padding is done with 0xff bytes entirely. | ||
193 | * Due to speed reasons, we won't check all of them | ||
194 | * but just first and last. | ||
195 | */ | ||
196 | if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) { | ||
197 | printk("dvb_demux.c section ts padding loss: %d/%d\n", | ||
198 | n, sec->tsfeedp); | ||
199 | printk("dvb_demux.c pad data:"); | ||
200 | for (i = 0; i < n; i++) | ||
201 | printk(" %02x", sec->secbuf[i]); | ||
202 | printk("\n"); | ||
203 | } | ||
204 | } | ||
205 | #endif | ||
206 | |||
207 | sec->tsfeedp = sec->secbufp = sec->seclen = 0; | ||
208 | sec->secbuf = sec->secbuf_base; | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * Losless Section Demux 1.4.1 by Emard | ||
213 | * Valsecchi Patrick: | ||
214 | * - middle of section A (no PUSI) | ||
215 | * - end of section A and start of section B | ||
216 | * (with PUSI pointing to the start of the second section) | ||
217 | * | ||
218 | * In this case, without feed->pusi_seen you'll receive a garbage section | ||
219 | * consisting of the end of section A. Basically because tsfeedp | ||
220 | * is incemented and the use=0 condition is not raised | ||
221 | * when the second packet arrives. | ||
222 | * | ||
223 | * Fix: | ||
224 | * when demux is started, let feed->pusi_seen = 0 to | ||
225 | * prevent initial feeding of garbage from the end of | ||
226 | * previous section. When you for the first time see PUSI=1 | ||
227 | * then set feed->pusi_seen = 1 | ||
228 | */ | ||
229 | static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, | ||
230 | const u8 *buf, u8 len) | ||
231 | { | ||
232 | struct dvb_demux *demux = feed->demux; | ||
233 | struct dmx_section_feed *sec = &feed->feed.sec; | ||
234 | u16 limit, seclen, n; | ||
235 | |||
236 | if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE) | ||
237 | return 0; | ||
238 | |||
239 | if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) { | ||
240 | #ifdef DVB_DEMUX_SECTION_LOSS_LOG | ||
241 | printk("dvb_demux.c section buffer full loss: %d/%d\n", | ||
242 | sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, | ||
243 | DMX_MAX_SECFEED_SIZE); | ||
244 | #endif | ||
245 | len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp; | ||
246 | } | ||
247 | |||
248 | if (len <= 0) | ||
249 | return 0; | ||
250 | |||
251 | demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len); | ||
252 | sec->tsfeedp += len; | ||
253 | |||
254 | /* | ||
255 | * Dump all the sections we can find in the data (Emard) | ||
256 | */ | ||
257 | limit = sec->tsfeedp; | ||
258 | if (limit > DMX_MAX_SECFEED_SIZE) | ||
259 | return -1; /* internal error should never happen */ | ||
260 | |||
261 | /* to be sure always set secbuf */ | ||
262 | sec->secbuf = sec->secbuf_base + sec->secbufp; | ||
263 | |||
264 | for (n = 0; sec->secbufp + 2 < limit; n++) { | ||
265 | seclen = section_length(sec->secbuf); | ||
266 | if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE | ||
267 | || seclen + sec->secbufp > limit) | ||
268 | return 0; | ||
269 | sec->seclen = seclen; | ||
270 | sec->crc_val = ~0; | ||
271 | /* dump [secbuf .. secbuf+seclen) */ | ||
272 | if (feed->pusi_seen) | ||
273 | dvb_dmx_swfilter_section_feed(feed); | ||
274 | #ifdef DVB_DEMUX_SECTION_LOSS_LOG | ||
275 | else | ||
276 | printk("dvb_demux.c pusi not seen, discarding section data\n"); | ||
277 | #endif | ||
278 | sec->secbufp += seclen; /* secbufp and secbuf moving together is */ | ||
279 | sec->secbuf += seclen; /* redundant but saves pointer arithmetic */ | ||
280 | } | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, | ||
286 | const u8 *buf) | ||
287 | { | ||
288 | u8 p, count; | ||
289 | int ccok, dc_i = 0; | ||
290 | u8 cc; | ||
291 | |||
292 | count = payload(buf); | ||
293 | |||
294 | if (count == 0) /* count == 0 if no payload or out of range */ | ||
295 | return -1; | ||
296 | |||
297 | p = 188 - count; /* payload start */ | ||
298 | |||
299 | cc = buf[3] & 0x0f; | ||
300 | ccok = ((feed->cc + 1) & 0x0f) == cc; | ||
301 | feed->cc = cc; | ||
302 | |||
303 | if (buf[3] & 0x20) { | ||
304 | /* adaption field present, check for discontinuity_indicator */ | ||
305 | if ((buf[4] > 0) && (buf[5] & 0x80)) | ||
306 | dc_i = 1; | ||
307 | } | ||
308 | |||
309 | if (!ccok || dc_i) { | ||
310 | #ifdef DVB_DEMUX_SECTION_LOSS_LOG | ||
311 | printk("dvb_demux.c discontinuity detected %d bytes lost\n", | ||
312 | count); | ||
313 | /* | ||
314 | * those bytes under sume circumstances will again be reported | ||
315 | * in the following dvb_dmx_swfilter_section_new | ||
316 | */ | ||
317 | #endif | ||
318 | /* | ||
319 | * Discontinuity detected. Reset pusi_seen = 0 to | ||
320 | * stop feeding of suspicious data until next PUSI=1 arrives | ||
321 | */ | ||
322 | feed->pusi_seen = 0; | ||
323 | dvb_dmx_swfilter_section_new(feed); | ||
324 | } | ||
325 | |||
326 | if (buf[1] & 0x40) { | ||
327 | /* PUSI=1 (is set), section boundary is here */ | ||
328 | if (count > 1 && buf[p] < count) { | ||
329 | const u8 *before = &buf[p + 1]; | ||
330 | u8 before_len = buf[p]; | ||
331 | const u8 *after = &before[before_len]; | ||
332 | u8 after_len = count - 1 - before_len; | ||
333 | |||
334 | dvb_dmx_swfilter_section_copy_dump(feed, before, | ||
335 | before_len); | ||
336 | /* before start of new section, set pusi_seen = 1 */ | ||
337 | feed->pusi_seen = 1; | ||
338 | dvb_dmx_swfilter_section_new(feed); | ||
339 | dvb_dmx_swfilter_section_copy_dump(feed, after, | ||
340 | after_len); | ||
341 | } | ||
342 | #ifdef DVB_DEMUX_SECTION_LOSS_LOG | ||
343 | else if (count > 0) | ||
344 | printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count); | ||
345 | #endif | ||
346 | } else { | ||
347 | /* PUSI=0 (is not set), no section boundary */ | ||
348 | dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count); | ||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, | ||
355 | const u8 *buf) | ||
356 | { | ||
357 | switch (feed->type) { | ||
358 | case DMX_TYPE_TS: | ||
359 | if (!feed->feed.ts.is_filtering) | ||
360 | break; | ||
361 | if (feed->ts_type & TS_PACKET) { | ||
362 | if (feed->ts_type & TS_PAYLOAD_ONLY) | ||
363 | dvb_dmx_swfilter_payload(feed, buf); | ||
364 | else | ||
365 | feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, | ||
366 | DMX_OK); | ||
367 | } | ||
368 | if (feed->ts_type & TS_DECODER) | ||
369 | if (feed->demux->write_to_decoder) | ||
370 | feed->demux->write_to_decoder(feed, buf, 188); | ||
371 | break; | ||
372 | |||
373 | case DMX_TYPE_SEC: | ||
374 | if (!feed->feed.sec.is_filtering) | ||
375 | break; | ||
376 | if (dvb_dmx_swfilter_section_packet(feed, buf) < 0) | ||
377 | feed->feed.sec.seclen = feed->feed.sec.secbufp = 0; | ||
378 | break; | ||
379 | |||
380 | default: | ||
381 | break; | ||
382 | } | ||
383 | } | ||
384 | |||
385 | #define DVR_FEED(f) \ | ||
386 | (((f)->type == DMX_TYPE_TS) && \ | ||
387 | ((f)->feed.ts.is_filtering) && \ | ||
388 | (((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET)) | ||
389 | |||
390 | static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) | ||
391 | { | ||
392 | struct dvb_demux_feed *feed; | ||
393 | u16 pid = ts_pid(buf); | ||
394 | int dvr_done = 0; | ||
395 | |||
396 | if (dvb_demux_speedcheck) { | ||
397 | struct timespec cur_time, delta_time; | ||
398 | u64 speed_bytes, speed_timedelta; | ||
399 | |||
400 | demux->speed_pkts_cnt++; | ||
401 | |||
402 | /* show speed every SPEED_PKTS_INTERVAL packets */ | ||
403 | if (!(demux->speed_pkts_cnt % SPEED_PKTS_INTERVAL)) { | ||
404 | cur_time = current_kernel_time(); | ||
405 | |||
406 | if (demux->speed_last_time.tv_sec != 0 && | ||
407 | demux->speed_last_time.tv_nsec != 0) { | ||
408 | delta_time = timespec_sub(cur_time, | ||
409 | demux->speed_last_time); | ||
410 | speed_bytes = (u64)demux->speed_pkts_cnt | ||
411 | * 188 * 8; | ||
412 | /* convert to 1024 basis */ | ||
413 | speed_bytes = 1000 * div64_u64(speed_bytes, | ||
414 | 1024); | ||
415 | speed_timedelta = | ||
416 | (u64)timespec_to_ns(&delta_time); | ||
417 | speed_timedelta = div64_u64(speed_timedelta, | ||
418 | 1000000); /* nsec -> usec */ | ||
419 | printk(KERN_INFO "TS speed %llu Kbits/sec \n", | ||
420 | div64_u64(speed_bytes, | ||
421 | speed_timedelta)); | ||
422 | }; | ||
423 | |||
424 | demux->speed_last_time = cur_time; | ||
425 | demux->speed_pkts_cnt = 0; | ||
426 | }; | ||
427 | }; | ||
428 | |||
429 | if (demux->cnt_storage && dvb_demux_tscheck) { | ||
430 | /* check pkt counter */ | ||
431 | if (pid < MAX_PID) { | ||
432 | if (buf[1] & 0x80) | ||
433 | dprintk_tscheck("TEI detected. " | ||
434 | "PID=0x%x data1=0x%x\n", | ||
435 | pid, buf[1]); | ||
436 | |||
437 | if ((buf[3] & 0xf) != demux->cnt_storage[pid]) | ||
438 | dprintk_tscheck("TS packet counter mismatch. " | ||
439 | "PID=0x%x expected 0x%x " | ||
440 | "got 0x%x\n", | ||
441 | pid, demux->cnt_storage[pid], | ||
442 | buf[3] & 0xf); | ||
443 | |||
444 | demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf; | ||
445 | }; | ||
446 | /* end check */ | ||
447 | }; | ||
448 | |||
449 | list_for_each_entry(feed, &demux->feed_list, list_head) { | ||
450 | if ((feed->pid != pid) && (feed->pid != 0x2000)) | ||
451 | continue; | ||
452 | |||
453 | /* copy each packet only once to the dvr device, even | ||
454 | * if a PID is in multiple filters (e.g. video + PCR) */ | ||
455 | if ((DVR_FEED(feed)) && (dvr_done++)) | ||
456 | continue; | ||
457 | |||
458 | if (feed->pid == pid) | ||
459 | dvb_dmx_swfilter_packet_type(feed, buf); | ||
460 | else if (feed->pid == 0x2000) | ||
461 | feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK); | ||
462 | } | ||
463 | } | ||
464 | |||
465 | void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, | ||
466 | size_t count) | ||
467 | { | ||
468 | spin_lock(&demux->lock); | ||
469 | |||
470 | while (count--) { | ||
471 | if (buf[0] == 0x47) | ||
472 | dvb_dmx_swfilter_packet(demux, buf); | ||
473 | buf += 188; | ||
474 | } | ||
475 | |||
476 | spin_unlock(&demux->lock); | ||
477 | } | ||
478 | |||
479 | EXPORT_SYMBOL(dvb_dmx_swfilter_packets); | ||
480 | |||
481 | static inline int find_next_packet(const u8 *buf, int pos, size_t count, | ||
482 | const int pktsize) | ||
483 | { | ||
484 | int start = pos, lost; | ||
485 | |||
486 | while (pos < count) { | ||
487 | if (buf[pos] == 0x47 || | ||
488 | (pktsize == 204 && buf[pos] == 0xB8)) | ||
489 | break; | ||
490 | pos++; | ||
491 | } | ||
492 | |||
493 | lost = pos - start; | ||
494 | if (lost) { | ||
495 | /* This garbage is part of a valid packet? */ | ||
496 | int backtrack = pos - pktsize; | ||
497 | if (backtrack >= 0 && (buf[backtrack] == 0x47 || | ||
498 | (pktsize == 204 && buf[backtrack] == 0xB8))) | ||
499 | return backtrack; | ||
500 | } | ||
501 | |||
502 | return pos; | ||
503 | } | ||
504 | |||
505 | /* Filter all pktsize= 188 or 204 sized packets and skip garbage. */ | ||
506 | static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, | ||
507 | size_t count, const int pktsize) | ||
508 | { | ||
509 | int p = 0, i, j; | ||
510 | const u8 *q; | ||
511 | |||
512 | spin_lock(&demux->lock); | ||
513 | |||
514 | if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */ | ||
515 | i = demux->tsbufp; | ||
516 | j = pktsize - i; | ||
517 | if (count < j) { | ||
518 | memcpy(&demux->tsbuf[i], buf, count); | ||
519 | demux->tsbufp += count; | ||
520 | goto bailout; | ||
521 | } | ||
522 | memcpy(&demux->tsbuf[i], buf, j); | ||
523 | if (demux->tsbuf[0] == 0x47) /* double check */ | ||
524 | dvb_dmx_swfilter_packet(demux, demux->tsbuf); | ||
525 | demux->tsbufp = 0; | ||
526 | p += j; | ||
527 | } | ||
528 | |||
529 | while (1) { | ||
530 | p = find_next_packet(buf, p, count, pktsize); | ||
531 | if (p >= count) | ||
532 | break; | ||
533 | if (count - p < pktsize) | ||
534 | break; | ||
535 | |||
536 | q = &buf[p]; | ||
537 | |||
538 | if (pktsize == 204 && (*q == 0xB8)) { | ||
539 | memcpy(demux->tsbuf, q, 188); | ||
540 | demux->tsbuf[0] = 0x47; | ||
541 | q = demux->tsbuf; | ||
542 | } | ||
543 | dvb_dmx_swfilter_packet(demux, q); | ||
544 | p += pktsize; | ||
545 | } | ||
546 | |||
547 | i = count - p; | ||
548 | if (i) { | ||
549 | memcpy(demux->tsbuf, &buf[p], i); | ||
550 | demux->tsbufp = i; | ||
551 | if (pktsize == 204 && demux->tsbuf[0] == 0xB8) | ||
552 | demux->tsbuf[0] = 0x47; | ||
553 | } | ||
554 | |||
555 | bailout: | ||
556 | spin_unlock(&demux->lock); | ||
557 | } | ||
558 | |||
559 | void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) | ||
560 | { | ||
561 | _dvb_dmx_swfilter(demux, buf, count, 188); | ||
562 | } | ||
563 | EXPORT_SYMBOL(dvb_dmx_swfilter); | ||
564 | |||
565 | void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) | ||
566 | { | ||
567 | _dvb_dmx_swfilter(demux, buf, count, 204); | ||
568 | } | ||
569 | EXPORT_SYMBOL(dvb_dmx_swfilter_204); | ||
570 | |||
571 | static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux) | ||
572 | { | ||
573 | int i; | ||
574 | |||
575 | for (i = 0; i < demux->filternum; i++) | ||
576 | if (demux->filter[i].state == DMX_STATE_FREE) | ||
577 | break; | ||
578 | |||
579 | if (i == demux->filternum) | ||
580 | return NULL; | ||
581 | |||
582 | demux->filter[i].state = DMX_STATE_ALLOCATED; | ||
583 | |||
584 | return &demux->filter[i]; | ||
585 | } | ||
586 | |||
587 | static struct dvb_demux_feed *dvb_dmx_feed_alloc(struct dvb_demux *demux) | ||
588 | { | ||
589 | int i; | ||
590 | |||
591 | for (i = 0; i < demux->feednum; i++) | ||
592 | if (demux->feed[i].state == DMX_STATE_FREE) | ||
593 | break; | ||
594 | |||
595 | if (i == demux->feednum) | ||
596 | return NULL; | ||
597 | |||
598 | demux->feed[i].state = DMX_STATE_ALLOCATED; | ||
599 | |||
600 | return &demux->feed[i]; | ||
601 | } | ||
602 | |||
603 | static int dvb_demux_feed_find(struct dvb_demux_feed *feed) | ||
604 | { | ||
605 | struct dvb_demux_feed *entry; | ||
606 | |||
607 | list_for_each_entry(entry, &feed->demux->feed_list, list_head) | ||
608 | if (entry == feed) | ||
609 | return 1; | ||
610 | |||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | static void dvb_demux_feed_add(struct dvb_demux_feed *feed) | ||
615 | { | ||
616 | spin_lock_irq(&feed->demux->lock); | ||
617 | if (dvb_demux_feed_find(feed)) { | ||
618 | printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n", | ||
619 | __func__, feed->type, feed->state, feed->pid); | ||
620 | goto out; | ||
621 | } | ||
622 | |||
623 | list_add(&feed->list_head, &feed->demux->feed_list); | ||
624 | out: | ||
625 | spin_unlock_irq(&feed->demux->lock); | ||
626 | } | ||
627 | |||
628 | static void dvb_demux_feed_del(struct dvb_demux_feed *feed) | ||
629 | { | ||
630 | spin_lock_irq(&feed->demux->lock); | ||
631 | if (!(dvb_demux_feed_find(feed))) { | ||
632 | printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n", | ||
633 | __func__, feed->type, feed->state, feed->pid); | ||
634 | goto out; | ||
635 | } | ||
636 | |||
637 | list_del(&feed->list_head); | ||
638 | out: | ||
639 | spin_unlock_irq(&feed->demux->lock); | ||
640 | } | ||
641 | |||
642 | static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type, | ||
643 | enum dmx_ts_pes pes_type, | ||
644 | size_t circular_buffer_size, struct timespec timeout) | ||
645 | { | ||
646 | struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; | ||
647 | struct dvb_demux *demux = feed->demux; | ||
648 | |||
649 | if (pid > DMX_MAX_PID) | ||
650 | return -EINVAL; | ||
651 | |||
652 | if (mutex_lock_interruptible(&demux->mutex)) | ||
653 | return -ERESTARTSYS; | ||
654 | |||
655 | if (ts_type & TS_DECODER) { | ||
656 | if (pes_type >= DMX_TS_PES_OTHER) { | ||
657 | mutex_unlock(&demux->mutex); | ||
658 | return -EINVAL; | ||
659 | } | ||
660 | |||
661 | if (demux->pesfilter[pes_type] && | ||
662 | demux->pesfilter[pes_type] != feed) { | ||
663 | mutex_unlock(&demux->mutex); | ||
664 | return -EINVAL; | ||
665 | } | ||
666 | |||
667 | demux->pesfilter[pes_type] = feed; | ||
668 | demux->pids[pes_type] = pid; | ||
669 | } | ||
670 | |||
671 | dvb_demux_feed_add(feed); | ||
672 | |||
673 | feed->pid = pid; | ||
674 | feed->buffer_size = circular_buffer_size; | ||
675 | feed->timeout = timeout; | ||
676 | feed->ts_type = ts_type; | ||
677 | feed->pes_type = pes_type; | ||
678 | |||
679 | if (feed->buffer_size) { | ||
680 | #ifdef NOBUFS | ||
681 | feed->buffer = NULL; | ||
682 | #else | ||
683 | feed->buffer = vmalloc(feed->buffer_size); | ||
684 | if (!feed->buffer) { | ||
685 | mutex_unlock(&demux->mutex); | ||
686 | return -ENOMEM; | ||
687 | } | ||
688 | #endif | ||
689 | } | ||
690 | |||
691 | feed->state = DMX_STATE_READY; | ||
692 | mutex_unlock(&demux->mutex); | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed) | ||
698 | { | ||
699 | struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; | ||
700 | struct dvb_demux *demux = feed->demux; | ||
701 | int ret; | ||
702 | |||
703 | if (mutex_lock_interruptible(&demux->mutex)) | ||
704 | return -ERESTARTSYS; | ||
705 | |||
706 | if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) { | ||
707 | mutex_unlock(&demux->mutex); | ||
708 | return -EINVAL; | ||
709 | } | ||
710 | |||
711 | if (!demux->start_feed) { | ||
712 | mutex_unlock(&demux->mutex); | ||
713 | return -ENODEV; | ||
714 | } | ||
715 | |||
716 | if ((ret = demux->start_feed(feed)) < 0) { | ||
717 | mutex_unlock(&demux->mutex); | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | spin_lock_irq(&demux->lock); | ||
722 | ts_feed->is_filtering = 1; | ||
723 | feed->state = DMX_STATE_GO; | ||
724 | spin_unlock_irq(&demux->lock); | ||
725 | mutex_unlock(&demux->mutex); | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) | ||
731 | { | ||
732 | struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; | ||
733 | struct dvb_demux *demux = feed->demux; | ||
734 | int ret; | ||
735 | |||
736 | mutex_lock(&demux->mutex); | ||
737 | |||
738 | if (feed->state < DMX_STATE_GO) { | ||
739 | mutex_unlock(&demux->mutex); | ||
740 | return -EINVAL; | ||
741 | } | ||
742 | |||
743 | if (!demux->stop_feed) { | ||
744 | mutex_unlock(&demux->mutex); | ||
745 | return -ENODEV; | ||
746 | } | ||
747 | |||
748 | ret = demux->stop_feed(feed); | ||
749 | |||
750 | spin_lock_irq(&demux->lock); | ||
751 | ts_feed->is_filtering = 0; | ||
752 | feed->state = DMX_STATE_ALLOCATED; | ||
753 | spin_unlock_irq(&demux->lock); | ||
754 | mutex_unlock(&demux->mutex); | ||
755 | |||
756 | return ret; | ||
757 | } | ||
758 | |||
759 | static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx, | ||
760 | struct dmx_ts_feed **ts_feed, | ||
761 | dmx_ts_cb callback) | ||
762 | { | ||
763 | struct dvb_demux *demux = (struct dvb_demux *)dmx; | ||
764 | struct dvb_demux_feed *feed; | ||
765 | |||
766 | if (mutex_lock_interruptible(&demux->mutex)) | ||
767 | return -ERESTARTSYS; | ||
768 | |||
769 | if (!(feed = dvb_dmx_feed_alloc(demux))) { | ||
770 | mutex_unlock(&demux->mutex); | ||
771 | return -EBUSY; | ||
772 | } | ||
773 | |||
774 | feed->type = DMX_TYPE_TS; | ||
775 | feed->cb.ts = callback; | ||
776 | feed->demux = demux; | ||
777 | feed->pid = 0xffff; | ||
778 | feed->peslen = 0xfffa; | ||
779 | feed->buffer = NULL; | ||
780 | |||
781 | (*ts_feed) = &feed->feed.ts; | ||
782 | (*ts_feed)->parent = dmx; | ||
783 | (*ts_feed)->priv = NULL; | ||
784 | (*ts_feed)->is_filtering = 0; | ||
785 | (*ts_feed)->start_filtering = dmx_ts_feed_start_filtering; | ||
786 | (*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering; | ||
787 | (*ts_feed)->set = dmx_ts_feed_set; | ||
788 | |||
789 | if (!(feed->filter = dvb_dmx_filter_alloc(demux))) { | ||
790 | feed->state = DMX_STATE_FREE; | ||
791 | mutex_unlock(&demux->mutex); | ||
792 | return -EBUSY; | ||
793 | } | ||
794 | |||
795 | feed->filter->type = DMX_TYPE_TS; | ||
796 | feed->filter->feed = feed; | ||
797 | feed->filter->state = DMX_STATE_READY; | ||
798 | |||
799 | mutex_unlock(&demux->mutex); | ||
800 | |||
801 | return 0; | ||
802 | } | ||
803 | |||
804 | static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, | ||
805 | struct dmx_ts_feed *ts_feed) | ||
806 | { | ||
807 | struct dvb_demux *demux = (struct dvb_demux *)dmx; | ||
808 | struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; | ||
809 | |||
810 | mutex_lock(&demux->mutex); | ||
811 | |||
812 | if (feed->state == DMX_STATE_FREE) { | ||
813 | mutex_unlock(&demux->mutex); | ||
814 | return -EINVAL; | ||
815 | } | ||
816 | #ifndef NOBUFS | ||
817 | vfree(feed->buffer); | ||
818 | feed->buffer = NULL; | ||
819 | #endif | ||
820 | |||
821 | feed->state = DMX_STATE_FREE; | ||
822 | feed->filter->state = DMX_STATE_FREE; | ||
823 | |||
824 | dvb_demux_feed_del(feed); | ||
825 | |||
826 | feed->pid = 0xffff; | ||
827 | |||
828 | if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER) | ||
829 | demux->pesfilter[feed->pes_type] = NULL; | ||
830 | |||
831 | mutex_unlock(&demux->mutex); | ||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | /****************************************************************************** | ||
836 | * dmx_section_feed API calls | ||
837 | ******************************************************************************/ | ||
838 | |||
839 | static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed, | ||
840 | struct dmx_section_filter **filter) | ||
841 | { | ||
842 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
843 | struct dvb_demux *dvbdemux = dvbdmxfeed->demux; | ||
844 | struct dvb_demux_filter *dvbdmxfilter; | ||
845 | |||
846 | if (mutex_lock_interruptible(&dvbdemux->mutex)) | ||
847 | return -ERESTARTSYS; | ||
848 | |||
849 | dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux); | ||
850 | if (!dvbdmxfilter) { | ||
851 | mutex_unlock(&dvbdemux->mutex); | ||
852 | return -EBUSY; | ||
853 | } | ||
854 | |||
855 | spin_lock_irq(&dvbdemux->lock); | ||
856 | *filter = &dvbdmxfilter->filter; | ||
857 | (*filter)->parent = feed; | ||
858 | (*filter)->priv = NULL; | ||
859 | dvbdmxfilter->feed = dvbdmxfeed; | ||
860 | dvbdmxfilter->type = DMX_TYPE_SEC; | ||
861 | dvbdmxfilter->state = DMX_STATE_READY; | ||
862 | dvbdmxfilter->next = dvbdmxfeed->filter; | ||
863 | dvbdmxfeed->filter = dvbdmxfilter; | ||
864 | spin_unlock_irq(&dvbdemux->lock); | ||
865 | |||
866 | mutex_unlock(&dvbdemux->mutex); | ||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | static int dmx_section_feed_set(struct dmx_section_feed *feed, | ||
871 | u16 pid, size_t circular_buffer_size, | ||
872 | int check_crc) | ||
873 | { | ||
874 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
875 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
876 | |||
877 | if (pid > 0x1fff) | ||
878 | return -EINVAL; | ||
879 | |||
880 | if (mutex_lock_interruptible(&dvbdmx->mutex)) | ||
881 | return -ERESTARTSYS; | ||
882 | |||
883 | dvb_demux_feed_add(dvbdmxfeed); | ||
884 | |||
885 | dvbdmxfeed->pid = pid; | ||
886 | dvbdmxfeed->buffer_size = circular_buffer_size; | ||
887 | dvbdmxfeed->feed.sec.check_crc = check_crc; | ||
888 | |||
889 | #ifdef NOBUFS | ||
890 | dvbdmxfeed->buffer = NULL; | ||
891 | #else | ||
892 | dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size); | ||
893 | if (!dvbdmxfeed->buffer) { | ||
894 | mutex_unlock(&dvbdmx->mutex); | ||
895 | return -ENOMEM; | ||
896 | } | ||
897 | #endif | ||
898 | |||
899 | dvbdmxfeed->state = DMX_STATE_READY; | ||
900 | mutex_unlock(&dvbdmx->mutex); | ||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed) | ||
905 | { | ||
906 | int i; | ||
907 | struct dvb_demux_filter *f; | ||
908 | struct dmx_section_filter *sf; | ||
909 | u8 mask, mode, doneq; | ||
910 | |||
911 | if (!(f = dvbdmxfeed->filter)) | ||
912 | return; | ||
913 | do { | ||
914 | sf = &f->filter; | ||
915 | doneq = 0; | ||
916 | for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) { | ||
917 | mode = sf->filter_mode[i]; | ||
918 | mask = sf->filter_mask[i]; | ||
919 | f->maskandmode[i] = mask & mode; | ||
920 | doneq |= f->maskandnotmode[i] = mask & ~mode; | ||
921 | } | ||
922 | f->doneq = doneq ? 1 : 0; | ||
923 | } while ((f = f->next)); | ||
924 | } | ||
925 | |||
926 | static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) | ||
927 | { | ||
928 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
929 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
930 | int ret; | ||
931 | |||
932 | if (mutex_lock_interruptible(&dvbdmx->mutex)) | ||
933 | return -ERESTARTSYS; | ||
934 | |||
935 | if (feed->is_filtering) { | ||
936 | mutex_unlock(&dvbdmx->mutex); | ||
937 | return -EBUSY; | ||
938 | } | ||
939 | |||
940 | if (!dvbdmxfeed->filter) { | ||
941 | mutex_unlock(&dvbdmx->mutex); | ||
942 | return -EINVAL; | ||
943 | } | ||
944 | |||
945 | dvbdmxfeed->feed.sec.tsfeedp = 0; | ||
946 | dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; | ||
947 | dvbdmxfeed->feed.sec.secbufp = 0; | ||
948 | dvbdmxfeed->feed.sec.seclen = 0; | ||
949 | |||
950 | if (!dvbdmx->start_feed) { | ||
951 | mutex_unlock(&dvbdmx->mutex); | ||
952 | return -ENODEV; | ||
953 | } | ||
954 | |||
955 | prepare_secfilters(dvbdmxfeed); | ||
956 | |||
957 | if ((ret = dvbdmx->start_feed(dvbdmxfeed)) < 0) { | ||
958 | mutex_unlock(&dvbdmx->mutex); | ||
959 | return ret; | ||
960 | } | ||
961 | |||
962 | spin_lock_irq(&dvbdmx->lock); | ||
963 | feed->is_filtering = 1; | ||
964 | dvbdmxfeed->state = DMX_STATE_GO; | ||
965 | spin_unlock_irq(&dvbdmx->lock); | ||
966 | |||
967 | mutex_unlock(&dvbdmx->mutex); | ||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed) | ||
972 | { | ||
973 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
974 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
975 | int ret; | ||
976 | |||
977 | mutex_lock(&dvbdmx->mutex); | ||
978 | |||
979 | if (!dvbdmx->stop_feed) { | ||
980 | mutex_unlock(&dvbdmx->mutex); | ||
981 | return -ENODEV; | ||
982 | } | ||
983 | |||
984 | ret = dvbdmx->stop_feed(dvbdmxfeed); | ||
985 | |||
986 | spin_lock_irq(&dvbdmx->lock); | ||
987 | dvbdmxfeed->state = DMX_STATE_READY; | ||
988 | feed->is_filtering = 0; | ||
989 | spin_unlock_irq(&dvbdmx->lock); | ||
990 | |||
991 | mutex_unlock(&dvbdmx->mutex); | ||
992 | return ret; | ||
993 | } | ||
994 | |||
995 | static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, | ||
996 | struct dmx_section_filter *filter) | ||
997 | { | ||
998 | struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *)filter, *f; | ||
999 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
1000 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
1001 | |||
1002 | mutex_lock(&dvbdmx->mutex); | ||
1003 | |||
1004 | if (dvbdmxfilter->feed != dvbdmxfeed) { | ||
1005 | mutex_unlock(&dvbdmx->mutex); | ||
1006 | return -EINVAL; | ||
1007 | } | ||
1008 | |||
1009 | if (feed->is_filtering) | ||
1010 | feed->stop_filtering(feed); | ||
1011 | |||
1012 | spin_lock_irq(&dvbdmx->lock); | ||
1013 | f = dvbdmxfeed->filter; | ||
1014 | |||
1015 | if (f == dvbdmxfilter) { | ||
1016 | dvbdmxfeed->filter = dvbdmxfilter->next; | ||
1017 | } else { | ||
1018 | while (f->next != dvbdmxfilter) | ||
1019 | f = f->next; | ||
1020 | f->next = f->next->next; | ||
1021 | } | ||
1022 | |||
1023 | dvbdmxfilter->state = DMX_STATE_FREE; | ||
1024 | spin_unlock_irq(&dvbdmx->lock); | ||
1025 | mutex_unlock(&dvbdmx->mutex); | ||
1026 | return 0; | ||
1027 | } | ||
1028 | |||
1029 | static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, | ||
1030 | struct dmx_section_feed **feed, | ||
1031 | dmx_section_cb callback) | ||
1032 | { | ||
1033 | struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; | ||
1034 | struct dvb_demux_feed *dvbdmxfeed; | ||
1035 | |||
1036 | if (mutex_lock_interruptible(&dvbdmx->mutex)) | ||
1037 | return -ERESTARTSYS; | ||
1038 | |||
1039 | if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) { | ||
1040 | mutex_unlock(&dvbdmx->mutex); | ||
1041 | return -EBUSY; | ||
1042 | } | ||
1043 | |||
1044 | dvbdmxfeed->type = DMX_TYPE_SEC; | ||
1045 | dvbdmxfeed->cb.sec = callback; | ||
1046 | dvbdmxfeed->demux = dvbdmx; | ||
1047 | dvbdmxfeed->pid = 0xffff; | ||
1048 | dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base; | ||
1049 | dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0; | ||
1050 | dvbdmxfeed->feed.sec.tsfeedp = 0; | ||
1051 | dvbdmxfeed->filter = NULL; | ||
1052 | dvbdmxfeed->buffer = NULL; | ||
1053 | |||
1054 | (*feed) = &dvbdmxfeed->feed.sec; | ||
1055 | (*feed)->is_filtering = 0; | ||
1056 | (*feed)->parent = demux; | ||
1057 | (*feed)->priv = NULL; | ||
1058 | |||
1059 | (*feed)->set = dmx_section_feed_set; | ||
1060 | (*feed)->allocate_filter = dmx_section_feed_allocate_filter; | ||
1061 | (*feed)->start_filtering = dmx_section_feed_start_filtering; | ||
1062 | (*feed)->stop_filtering = dmx_section_feed_stop_filtering; | ||
1063 | (*feed)->release_filter = dmx_section_feed_release_filter; | ||
1064 | |||
1065 | mutex_unlock(&dvbdmx->mutex); | ||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | static int dvbdmx_release_section_feed(struct dmx_demux *demux, | ||
1070 | struct dmx_section_feed *feed) | ||
1071 | { | ||
1072 | struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; | ||
1073 | struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; | ||
1074 | |||
1075 | mutex_lock(&dvbdmx->mutex); | ||
1076 | |||
1077 | if (dvbdmxfeed->state == DMX_STATE_FREE) { | ||
1078 | mutex_unlock(&dvbdmx->mutex); | ||
1079 | return -EINVAL; | ||
1080 | } | ||
1081 | #ifndef NOBUFS | ||
1082 | vfree(dvbdmxfeed->buffer); | ||
1083 | dvbdmxfeed->buffer = NULL; | ||
1084 | #endif | ||
1085 | dvbdmxfeed->state = DMX_STATE_FREE; | ||
1086 | |||
1087 | dvb_demux_feed_del(dvbdmxfeed); | ||
1088 | |||
1089 | dvbdmxfeed->pid = 0xffff; | ||
1090 | |||
1091 | mutex_unlock(&dvbdmx->mutex); | ||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
1095 | /****************************************************************************** | ||
1096 | * dvb_demux kernel data API calls | ||
1097 | ******************************************************************************/ | ||
1098 | |||
1099 | static int dvbdmx_open(struct dmx_demux *demux) | ||
1100 | { | ||
1101 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1102 | |||
1103 | if (dvbdemux->users >= MAX_DVB_DEMUX_USERS) | ||
1104 | return -EUSERS; | ||
1105 | |||
1106 | dvbdemux->users++; | ||
1107 | return 0; | ||
1108 | } | ||
1109 | |||
1110 | static int dvbdmx_close(struct dmx_demux *demux) | ||
1111 | { | ||
1112 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1113 | |||
1114 | if (dvbdemux->users == 0) | ||
1115 | return -ENODEV; | ||
1116 | |||
1117 | dvbdemux->users--; | ||
1118 | //FIXME: release any unneeded resources if users==0 | ||
1119 | return 0; | ||
1120 | } | ||
1121 | |||
1122 | static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t count) | ||
1123 | { | ||
1124 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1125 | void *p; | ||
1126 | |||
1127 | if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE)) | ||
1128 | return -EINVAL; | ||
1129 | |||
1130 | p = memdup_user(buf, count); | ||
1131 | if (IS_ERR(p)) | ||
1132 | return PTR_ERR(p); | ||
1133 | if (mutex_lock_interruptible(&dvbdemux->mutex)) { | ||
1134 | kfree(p); | ||
1135 | return -ERESTARTSYS; | ||
1136 | } | ||
1137 | dvb_dmx_swfilter(dvbdemux, p, count); | ||
1138 | kfree(p); | ||
1139 | mutex_unlock(&dvbdemux->mutex); | ||
1140 | |||
1141 | if (signal_pending(current)) | ||
1142 | return -EINTR; | ||
1143 | return count; | ||
1144 | } | ||
1145 | |||
1146 | static int dvbdmx_add_frontend(struct dmx_demux *demux, | ||
1147 | struct dmx_frontend *frontend) | ||
1148 | { | ||
1149 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1150 | struct list_head *head = &dvbdemux->frontend_list; | ||
1151 | |||
1152 | list_add(&(frontend->connectivity_list), head); | ||
1153 | |||
1154 | return 0; | ||
1155 | } | ||
1156 | |||
1157 | static int dvbdmx_remove_frontend(struct dmx_demux *demux, | ||
1158 | struct dmx_frontend *frontend) | ||
1159 | { | ||
1160 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1161 | struct list_head *pos, *n, *head = &dvbdemux->frontend_list; | ||
1162 | |||
1163 | list_for_each_safe(pos, n, head) { | ||
1164 | if (DMX_FE_ENTRY(pos) == frontend) { | ||
1165 | list_del(pos); | ||
1166 | return 0; | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | return -ENODEV; | ||
1171 | } | ||
1172 | |||
1173 | static struct list_head *dvbdmx_get_frontends(struct dmx_demux *demux) | ||
1174 | { | ||
1175 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1176 | |||
1177 | if (list_empty(&dvbdemux->frontend_list)) | ||
1178 | return NULL; | ||
1179 | |||
1180 | return &dvbdemux->frontend_list; | ||
1181 | } | ||
1182 | |||
1183 | static int dvbdmx_connect_frontend(struct dmx_demux *demux, | ||
1184 | struct dmx_frontend *frontend) | ||
1185 | { | ||
1186 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1187 | |||
1188 | if (demux->frontend) | ||
1189 | return -EINVAL; | ||
1190 | |||
1191 | mutex_lock(&dvbdemux->mutex); | ||
1192 | |||
1193 | demux->frontend = frontend; | ||
1194 | mutex_unlock(&dvbdemux->mutex); | ||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | static int dvbdmx_disconnect_frontend(struct dmx_demux *demux) | ||
1199 | { | ||
1200 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1201 | |||
1202 | mutex_lock(&dvbdemux->mutex); | ||
1203 | |||
1204 | demux->frontend = NULL; | ||
1205 | mutex_unlock(&dvbdemux->mutex); | ||
1206 | return 0; | ||
1207 | } | ||
1208 | |||
1209 | static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids) | ||
1210 | { | ||
1211 | struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; | ||
1212 | |||
1213 | memcpy(pids, dvbdemux->pids, 5 * sizeof(u16)); | ||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | int dvb_dmx_init(struct dvb_demux *dvbdemux) | ||
1218 | { | ||
1219 | int i; | ||
1220 | struct dmx_demux *dmx = &dvbdemux->dmx; | ||
1221 | |||
1222 | dvbdemux->cnt_storage = NULL; | ||
1223 | dvbdemux->users = 0; | ||
1224 | dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter)); | ||
1225 | |||
1226 | if (!dvbdemux->filter) | ||
1227 | return -ENOMEM; | ||
1228 | |||
1229 | dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed)); | ||
1230 | if (!dvbdemux->feed) { | ||
1231 | vfree(dvbdemux->filter); | ||
1232 | dvbdemux->filter = NULL; | ||
1233 | return -ENOMEM; | ||
1234 | } | ||
1235 | for (i = 0; i < dvbdemux->filternum; i++) { | ||
1236 | dvbdemux->filter[i].state = DMX_STATE_FREE; | ||
1237 | dvbdemux->filter[i].index = i; | ||
1238 | } | ||
1239 | for (i = 0; i < dvbdemux->feednum; i++) { | ||
1240 | dvbdemux->feed[i].state = DMX_STATE_FREE; | ||
1241 | dvbdemux->feed[i].index = i; | ||
1242 | } | ||
1243 | |||
1244 | dvbdemux->cnt_storage = vmalloc(MAX_PID + 1); | ||
1245 | if (!dvbdemux->cnt_storage) | ||
1246 | printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n"); | ||
1247 | |||
1248 | INIT_LIST_HEAD(&dvbdemux->frontend_list); | ||
1249 | |||
1250 | for (i = 0; i < DMX_TS_PES_OTHER; i++) { | ||
1251 | dvbdemux->pesfilter[i] = NULL; | ||
1252 | dvbdemux->pids[i] = 0xffff; | ||
1253 | } | ||
1254 | |||
1255 | INIT_LIST_HEAD(&dvbdemux->feed_list); | ||
1256 | |||
1257 | dvbdemux->playing = 0; | ||
1258 | dvbdemux->recording = 0; | ||
1259 | dvbdemux->tsbufp = 0; | ||
1260 | |||
1261 | if (!dvbdemux->check_crc32) | ||
1262 | dvbdemux->check_crc32 = dvb_dmx_crc32; | ||
1263 | |||
1264 | if (!dvbdemux->memcopy) | ||
1265 | dvbdemux->memcopy = dvb_dmx_memcopy; | ||
1266 | |||
1267 | dmx->frontend = NULL; | ||
1268 | dmx->priv = dvbdemux; | ||
1269 | dmx->open = dvbdmx_open; | ||
1270 | dmx->close = dvbdmx_close; | ||
1271 | dmx->write = dvbdmx_write; | ||
1272 | dmx->allocate_ts_feed = dvbdmx_allocate_ts_feed; | ||
1273 | dmx->release_ts_feed = dvbdmx_release_ts_feed; | ||
1274 | dmx->allocate_section_feed = dvbdmx_allocate_section_feed; | ||
1275 | dmx->release_section_feed = dvbdmx_release_section_feed; | ||
1276 | |||
1277 | dmx->add_frontend = dvbdmx_add_frontend; | ||
1278 | dmx->remove_frontend = dvbdmx_remove_frontend; | ||
1279 | dmx->get_frontends = dvbdmx_get_frontends; | ||
1280 | dmx->connect_frontend = dvbdmx_connect_frontend; | ||
1281 | dmx->disconnect_frontend = dvbdmx_disconnect_frontend; | ||
1282 | dmx->get_pes_pids = dvbdmx_get_pes_pids; | ||
1283 | |||
1284 | mutex_init(&dvbdemux->mutex); | ||
1285 | spin_lock_init(&dvbdemux->lock); | ||
1286 | |||
1287 | return 0; | ||
1288 | } | ||
1289 | |||
1290 | EXPORT_SYMBOL(dvb_dmx_init); | ||
1291 | |||
1292 | void dvb_dmx_release(struct dvb_demux *dvbdemux) | ||
1293 | { | ||
1294 | vfree(dvbdemux->cnt_storage); | ||
1295 | vfree(dvbdemux->filter); | ||
1296 | vfree(dvbdemux->feed); | ||
1297 | } | ||
1298 | |||
1299 | 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 new file mode 100644 index 00000000000..a7d876fd02d --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_demux.h | |||
@@ -0,0 +1,149 @@ | |||
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 | |||
149 | #endif /* _DVB_DEMUX_H_ */ | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c new file mode 100644 index 00000000000..772003fb182 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_filter.c | |||
@@ -0,0 +1,603 @@ | |||
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 new file mode 100644 index 00000000000..375e3be184b --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_filter.h | |||
@@ -0,0 +1,246 @@ | |||
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 new file mode 100644 index 00000000000..efe9c30605e --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
@@ -0,0 +1,2173 @@ | |||
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 | #include <linux/string.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/wait.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/poll.h> | ||
34 | #include <linux/semaphore.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/list.h> | ||
37 | #include <linux/freezer.h> | ||
38 | #include <linux/jiffies.h> | ||
39 | #include <linux/kthread.h> | ||
40 | #include <asm/processor.h> | ||
41 | |||
42 | #include "dvb_frontend.h" | ||
43 | #include "dvbdev.h" | ||
44 | #include <linux/dvb/version.h> | ||
45 | |||
46 | static int dvb_frontend_debug; | ||
47 | static int dvb_shutdown_timeout; | ||
48 | static int dvb_force_auto_inversion; | ||
49 | static int dvb_override_tune_delay; | ||
50 | static int dvb_powerdown_on_sleep = 1; | ||
51 | static int dvb_mfe_wait_time = 5; | ||
52 | |||
53 | module_param_named(frontend_debug, dvb_frontend_debug, int, 0644); | ||
54 | MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off)."); | ||
55 | module_param(dvb_shutdown_timeout, int, 0644); | ||
56 | MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware"); | ||
57 | module_param(dvb_force_auto_inversion, int, 0644); | ||
58 | MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always"); | ||
59 | module_param(dvb_override_tune_delay, int, 0644); | ||
60 | MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); | ||
61 | module_param(dvb_powerdown_on_sleep, int, 0644); | ||
62 | MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)"); | ||
63 | module_param(dvb_mfe_wait_time, int, 0644); | ||
64 | 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)"); | ||
65 | |||
66 | #define dprintk if (dvb_frontend_debug) printk | ||
67 | |||
68 | #define FESTATE_IDLE 1 | ||
69 | #define FESTATE_RETUNE 2 | ||
70 | #define FESTATE_TUNING_FAST 4 | ||
71 | #define FESTATE_TUNING_SLOW 8 | ||
72 | #define FESTATE_TUNED 16 | ||
73 | #define FESTATE_ZIGZAG_FAST 32 | ||
74 | #define FESTATE_ZIGZAG_SLOW 64 | ||
75 | #define FESTATE_DISEQC 128 | ||
76 | #define FESTATE_ERROR 256 | ||
77 | #define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC) | ||
78 | #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST) | ||
79 | #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW) | ||
80 | #define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW) | ||
81 | |||
82 | #define FE_ALGO_HW 1 | ||
83 | /* | ||
84 | * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling. | ||
85 | * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune. | ||
86 | * FESTATE_TUNING_FAST. Tuning parameters have been supplied and fast zigzag scan is in progress. | ||
87 | * FESTATE_TUNING_SLOW. Tuning parameters have been supplied. Fast zigzag failed, so we're trying again, but slower. | ||
88 | * FESTATE_TUNED. The frontend has successfully locked on. | ||
89 | * FESTATE_ZIGZAG_FAST. The lock has been lost, and a fast zigzag has been initiated to try and regain it. | ||
90 | * FESTATE_ZIGZAG_SLOW. The lock has been lost. Fast zigzag has been failed, so we're trying again, but slower. | ||
91 | * FESTATE_DISEQC. A DISEQC command has just been issued. | ||
92 | * FESTATE_WAITFORLOCK. When we're waiting for a lock. | ||
93 | * FESTATE_SEARCHING_FAST. When we're searching for a signal using a fast zigzag scan. | ||
94 | * FESTATE_SEARCHING_SLOW. When we're searching for a signal using a slow zigzag scan. | ||
95 | * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. | ||
96 | */ | ||
97 | |||
98 | #define DVB_FE_NO_EXIT 0 | ||
99 | #define DVB_FE_NORMAL_EXIT 1 | ||
100 | #define DVB_FE_DEVICE_REMOVED 2 | ||
101 | |||
102 | static DEFINE_MUTEX(frontend_mutex); | ||
103 | |||
104 | struct dvb_frontend_private { | ||
105 | |||
106 | /* thread/frontend values */ | ||
107 | struct dvb_device *dvbdev; | ||
108 | struct dvb_frontend_parameters parameters_in; | ||
109 | struct dvb_frontend_parameters parameters_out; | ||
110 | struct dvb_fe_events events; | ||
111 | struct semaphore sem; | ||
112 | struct list_head list_head; | ||
113 | wait_queue_head_t wait_queue; | ||
114 | struct task_struct *thread; | ||
115 | unsigned long release_jiffies; | ||
116 | unsigned int exit; | ||
117 | unsigned int wakeup; | ||
118 | fe_status_t status; | ||
119 | unsigned long tune_mode_flags; | ||
120 | unsigned int delay; | ||
121 | unsigned int reinitialise; | ||
122 | int tone; | ||
123 | int voltage; | ||
124 | |||
125 | /* swzigzag values */ | ||
126 | unsigned int state; | ||
127 | unsigned int bending; | ||
128 | int lnb_drift; | ||
129 | unsigned int inversion; | ||
130 | unsigned int auto_step; | ||
131 | unsigned int auto_sub_step; | ||
132 | unsigned int started_auto_step; | ||
133 | unsigned int min_delay; | ||
134 | unsigned int max_drift; | ||
135 | unsigned int step_size; | ||
136 | int quality; | ||
137 | unsigned int check_wrapped; | ||
138 | enum dvbfe_search algo_status; | ||
139 | }; | ||
140 | |||
141 | static void dvb_frontend_wakeup(struct dvb_frontend *fe); | ||
142 | |||
143 | static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) | ||
144 | { | ||
145 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
146 | struct dvb_fe_events *events = &fepriv->events; | ||
147 | struct dvb_frontend_event *e; | ||
148 | int wp; | ||
149 | |||
150 | dprintk ("%s\n", __func__); | ||
151 | |||
152 | if (mutex_lock_interruptible (&events->mtx)) | ||
153 | return; | ||
154 | |||
155 | wp = (events->eventw + 1) % MAX_EVENT; | ||
156 | |||
157 | if (wp == events->eventr) { | ||
158 | events->overflow = 1; | ||
159 | events->eventr = (events->eventr + 1) % MAX_EVENT; | ||
160 | } | ||
161 | |||
162 | e = &events->events[events->eventw]; | ||
163 | |||
164 | if (status & FE_HAS_LOCK) | ||
165 | if (fe->ops.get_frontend) | ||
166 | fe->ops.get_frontend(fe, &fepriv->parameters_out); | ||
167 | |||
168 | e->parameters = fepriv->parameters_out; | ||
169 | |||
170 | events->eventw = wp; | ||
171 | |||
172 | mutex_unlock(&events->mtx); | ||
173 | |||
174 | e->status = status; | ||
175 | |||
176 | wake_up_interruptible (&events->wait_queue); | ||
177 | } | ||
178 | |||
179 | static int dvb_frontend_get_event(struct dvb_frontend *fe, | ||
180 | struct dvb_frontend_event *event, int flags) | ||
181 | { | ||
182 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
183 | struct dvb_fe_events *events = &fepriv->events; | ||
184 | |||
185 | dprintk ("%s\n", __func__); | ||
186 | |||
187 | if (events->overflow) { | ||
188 | events->overflow = 0; | ||
189 | return -EOVERFLOW; | ||
190 | } | ||
191 | |||
192 | if (events->eventw == events->eventr) { | ||
193 | int ret; | ||
194 | |||
195 | if (flags & O_NONBLOCK) | ||
196 | return -EWOULDBLOCK; | ||
197 | |||
198 | up(&fepriv->sem); | ||
199 | |||
200 | ret = wait_event_interruptible (events->wait_queue, | ||
201 | events->eventw != events->eventr); | ||
202 | |||
203 | if (down_interruptible (&fepriv->sem)) | ||
204 | return -ERESTARTSYS; | ||
205 | |||
206 | if (ret < 0) | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | if (mutex_lock_interruptible (&events->mtx)) | ||
211 | return -ERESTARTSYS; | ||
212 | |||
213 | memcpy (event, &events->events[events->eventr], | ||
214 | sizeof(struct dvb_frontend_event)); | ||
215 | |||
216 | events->eventr = (events->eventr + 1) % MAX_EVENT; | ||
217 | |||
218 | mutex_unlock(&events->mtx); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static void dvb_frontend_init(struct dvb_frontend *fe) | ||
224 | { | ||
225 | dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n", | ||
226 | fe->dvb->num, | ||
227 | fe->id, | ||
228 | fe->ops.info.name); | ||
229 | |||
230 | if (fe->ops.init) | ||
231 | fe->ops.init(fe); | ||
232 | if (fe->ops.tuner_ops.init) { | ||
233 | if (fe->ops.i2c_gate_ctrl) | ||
234 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
235 | fe->ops.tuner_ops.init(fe); | ||
236 | if (fe->ops.i2c_gate_ctrl) | ||
237 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | void dvb_frontend_reinitialise(struct dvb_frontend *fe) | ||
242 | { | ||
243 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
244 | |||
245 | fepriv->reinitialise = 1; | ||
246 | dvb_frontend_wakeup(fe); | ||
247 | } | ||
248 | EXPORT_SYMBOL(dvb_frontend_reinitialise); | ||
249 | |||
250 | static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked) | ||
251 | { | ||
252 | int q2; | ||
253 | |||
254 | dprintk ("%s\n", __func__); | ||
255 | |||
256 | if (locked) | ||
257 | (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256; | ||
258 | else | ||
259 | (fepriv->quality) = (fepriv->quality * 220 + 0) / 256; | ||
260 | |||
261 | q2 = fepriv->quality - 128; | ||
262 | q2 *= q2; | ||
263 | |||
264 | fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128); | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * Performs automatic twiddling of frontend parameters. | ||
269 | * | ||
270 | * @param fe The frontend concerned. | ||
271 | * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT | ||
272 | * @returns Number of complete iterations that have been performed. | ||
273 | */ | ||
274 | static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped) | ||
275 | { | ||
276 | int autoinversion; | ||
277 | int ready = 0; | ||
278 | int fe_set_err = 0; | ||
279 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
280 | int original_inversion = fepriv->parameters_in.inversion; | ||
281 | u32 original_frequency = fepriv->parameters_in.frequency; | ||
282 | |||
283 | /* are we using autoinversion? */ | ||
284 | autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && | ||
285 | (fepriv->parameters_in.inversion == INVERSION_AUTO)); | ||
286 | |||
287 | /* setup parameters correctly */ | ||
288 | while(!ready) { | ||
289 | /* calculate the lnb_drift */ | ||
290 | fepriv->lnb_drift = fepriv->auto_step * fepriv->step_size; | ||
291 | |||
292 | /* wrap the auto_step if we've exceeded the maximum drift */ | ||
293 | if (fepriv->lnb_drift > fepriv->max_drift) { | ||
294 | fepriv->auto_step = 0; | ||
295 | fepriv->auto_sub_step = 0; | ||
296 | fepriv->lnb_drift = 0; | ||
297 | } | ||
298 | |||
299 | /* perform inversion and +/- zigzag */ | ||
300 | switch(fepriv->auto_sub_step) { | ||
301 | case 0: | ||
302 | /* try with the current inversion and current drift setting */ | ||
303 | ready = 1; | ||
304 | break; | ||
305 | |||
306 | case 1: | ||
307 | if (!autoinversion) break; | ||
308 | |||
309 | fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF; | ||
310 | ready = 1; | ||
311 | break; | ||
312 | |||
313 | case 2: | ||
314 | if (fepriv->lnb_drift == 0) break; | ||
315 | |||
316 | fepriv->lnb_drift = -fepriv->lnb_drift; | ||
317 | ready = 1; | ||
318 | break; | ||
319 | |||
320 | case 3: | ||
321 | if (fepriv->lnb_drift == 0) break; | ||
322 | if (!autoinversion) break; | ||
323 | |||
324 | fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF; | ||
325 | fepriv->lnb_drift = -fepriv->lnb_drift; | ||
326 | ready = 1; | ||
327 | break; | ||
328 | |||
329 | default: | ||
330 | fepriv->auto_step++; | ||
331 | fepriv->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */ | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | if (!ready) fepriv->auto_sub_step++; | ||
336 | } | ||
337 | |||
338 | /* if this attempt would hit where we started, indicate a complete | ||
339 | * iteration has occurred */ | ||
340 | if ((fepriv->auto_step == fepriv->started_auto_step) && | ||
341 | (fepriv->auto_sub_step == 0) && check_wrapped) { | ||
342 | return 1; | ||
343 | } | ||
344 | |||
345 | dprintk("%s: drift:%i inversion:%i auto_step:%i " | ||
346 | "auto_sub_step:%i started_auto_step:%i\n", | ||
347 | __func__, fepriv->lnb_drift, fepriv->inversion, | ||
348 | fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); | ||
349 | |||
350 | /* set the frontend itself */ | ||
351 | fepriv->parameters_in.frequency += fepriv->lnb_drift; | ||
352 | if (autoinversion) | ||
353 | fepriv->parameters_in.inversion = fepriv->inversion; | ||
354 | if (fe->ops.set_frontend) | ||
355 | fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters_in); | ||
356 | fepriv->parameters_out = fepriv->parameters_in; | ||
357 | if (fe_set_err < 0) { | ||
358 | fepriv->state = FESTATE_ERROR; | ||
359 | return fe_set_err; | ||
360 | } | ||
361 | |||
362 | fepriv->parameters_in.frequency = original_frequency; | ||
363 | fepriv->parameters_in.inversion = original_inversion; | ||
364 | |||
365 | fepriv->auto_sub_step++; | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | static void dvb_frontend_swzigzag(struct dvb_frontend *fe) | ||
370 | { | ||
371 | fe_status_t s = 0; | ||
372 | int retval = 0; | ||
373 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
374 | |||
375 | /* if we've got no parameters, just keep idling */ | ||
376 | if (fepriv->state & FESTATE_IDLE) { | ||
377 | fepriv->delay = 3*HZ; | ||
378 | fepriv->quality = 0; | ||
379 | return; | ||
380 | } | ||
381 | |||
382 | /* in SCAN mode, we just set the frontend when asked and leave it alone */ | ||
383 | if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { | ||
384 | if (fepriv->state & FESTATE_RETUNE) { | ||
385 | if (fe->ops.set_frontend) | ||
386 | retval = fe->ops.set_frontend(fe, | ||
387 | &fepriv->parameters_in); | ||
388 | fepriv->parameters_out = fepriv->parameters_in; | ||
389 | if (retval < 0) | ||
390 | fepriv->state = FESTATE_ERROR; | ||
391 | else | ||
392 | fepriv->state = FESTATE_TUNED; | ||
393 | } | ||
394 | fepriv->delay = 3*HZ; | ||
395 | fepriv->quality = 0; | ||
396 | return; | ||
397 | } | ||
398 | |||
399 | /* get the frontend status */ | ||
400 | if (fepriv->state & FESTATE_RETUNE) { | ||
401 | s = 0; | ||
402 | } else { | ||
403 | if (fe->ops.read_status) | ||
404 | fe->ops.read_status(fe, &s); | ||
405 | if (s != fepriv->status) { | ||
406 | dvb_frontend_add_event(fe, s); | ||
407 | fepriv->status = s; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | /* if we're not tuned, and we have a lock, move to the TUNED state */ | ||
412 | if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { | ||
413 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
414 | fepriv->state = FESTATE_TUNED; | ||
415 | |||
416 | /* if we're tuned, then we have determined the correct inversion */ | ||
417 | if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && | ||
418 | (fepriv->parameters_in.inversion == INVERSION_AUTO)) { | ||
419 | fepriv->parameters_in.inversion = fepriv->inversion; | ||
420 | } | ||
421 | return; | ||
422 | } | ||
423 | |||
424 | /* if we are tuned already, check we're still locked */ | ||
425 | if (fepriv->state & FESTATE_TUNED) { | ||
426 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
427 | |||
428 | /* we're tuned, and the lock is still good... */ | ||
429 | if (s & FE_HAS_LOCK) { | ||
430 | return; | ||
431 | } else { /* if we _WERE_ tuned, but now don't have a lock */ | ||
432 | fepriv->state = FESTATE_ZIGZAG_FAST; | ||
433 | fepriv->started_auto_step = fepriv->auto_step; | ||
434 | fepriv->check_wrapped = 0; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | /* don't actually do anything if we're in the LOSTLOCK state, | ||
439 | * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ | ||
440 | if ((fepriv->state & FESTATE_LOSTLOCK) && | ||
441 | (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { | ||
442 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
443 | return; | ||
444 | } | ||
445 | |||
446 | /* don't do anything if we're in the DISEQC state, since this | ||
447 | * might be someone with a motorized dish controlled by DISEQC. | ||
448 | * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */ | ||
449 | if (fepriv->state & FESTATE_DISEQC) { | ||
450 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
451 | return; | ||
452 | } | ||
453 | |||
454 | /* if we're in the RETUNE state, set everything up for a brand | ||
455 | * new scan, keeping the current inversion setting, as the next | ||
456 | * tune is _very_ likely to require the same */ | ||
457 | if (fepriv->state & FESTATE_RETUNE) { | ||
458 | fepriv->lnb_drift = 0; | ||
459 | fepriv->auto_step = 0; | ||
460 | fepriv->auto_sub_step = 0; | ||
461 | fepriv->started_auto_step = 0; | ||
462 | fepriv->check_wrapped = 0; | ||
463 | } | ||
464 | |||
465 | /* fast zigzag. */ | ||
466 | if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) { | ||
467 | fepriv->delay = fepriv->min_delay; | ||
468 | |||
469 | /* perform a tune */ | ||
470 | retval = dvb_frontend_swzigzag_autotune(fe, | ||
471 | fepriv->check_wrapped); | ||
472 | if (retval < 0) { | ||
473 | return; | ||
474 | } else if (retval) { | ||
475 | /* OK, if we've run out of trials at the fast speed. | ||
476 | * Drop back to slow for the _next_ attempt */ | ||
477 | fepriv->state = FESTATE_SEARCHING_SLOW; | ||
478 | fepriv->started_auto_step = fepriv->auto_step; | ||
479 | return; | ||
480 | } | ||
481 | fepriv->check_wrapped = 1; | ||
482 | |||
483 | /* if we've just retuned, enter the ZIGZAG_FAST state. | ||
484 | * This ensures we cannot return from an | ||
485 | * FE_SET_FRONTEND ioctl before the first frontend tune | ||
486 | * occurs */ | ||
487 | if (fepriv->state & FESTATE_RETUNE) { | ||
488 | fepriv->state = FESTATE_TUNING_FAST; | ||
489 | } | ||
490 | } | ||
491 | |||
492 | /* slow zigzag */ | ||
493 | if (fepriv->state & FESTATE_SEARCHING_SLOW) { | ||
494 | dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); | ||
495 | |||
496 | /* Note: don't bother checking for wrapping; we stay in this | ||
497 | * state until we get a lock */ | ||
498 | dvb_frontend_swzigzag_autotune(fe, 0); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | static int dvb_frontend_is_exiting(struct dvb_frontend *fe) | ||
503 | { | ||
504 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
505 | |||
506 | if (fepriv->exit != DVB_FE_NO_EXIT) | ||
507 | return 1; | ||
508 | |||
509 | if (fepriv->dvbdev->writers == 1) | ||
510 | if (time_after(jiffies, fepriv->release_jiffies + | ||
511 | dvb_shutdown_timeout * HZ)) | ||
512 | return 1; | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static int dvb_frontend_should_wakeup(struct dvb_frontend *fe) | ||
518 | { | ||
519 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
520 | |||
521 | if (fepriv->wakeup) { | ||
522 | fepriv->wakeup = 0; | ||
523 | return 1; | ||
524 | } | ||
525 | return dvb_frontend_is_exiting(fe); | ||
526 | } | ||
527 | |||
528 | static void dvb_frontend_wakeup(struct dvb_frontend *fe) | ||
529 | { | ||
530 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
531 | |||
532 | fepriv->wakeup = 1; | ||
533 | wake_up_interruptible(&fepriv->wait_queue); | ||
534 | } | ||
535 | |||
536 | static int dvb_frontend_thread(void *data) | ||
537 | { | ||
538 | struct dvb_frontend *fe = data; | ||
539 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
540 | unsigned long timeout; | ||
541 | fe_status_t s; | ||
542 | enum dvbfe_algo algo; | ||
543 | |||
544 | struct dvb_frontend_parameters *params; | ||
545 | |||
546 | dprintk("%s\n", __func__); | ||
547 | |||
548 | fepriv->check_wrapped = 0; | ||
549 | fepriv->quality = 0; | ||
550 | fepriv->delay = 3*HZ; | ||
551 | fepriv->status = 0; | ||
552 | fepriv->wakeup = 0; | ||
553 | fepriv->reinitialise = 0; | ||
554 | |||
555 | dvb_frontend_init(fe); | ||
556 | |||
557 | set_freezable(); | ||
558 | while (1) { | ||
559 | up(&fepriv->sem); /* is locked when we enter the thread... */ | ||
560 | restart: | ||
561 | timeout = wait_event_interruptible_timeout(fepriv->wait_queue, | ||
562 | dvb_frontend_should_wakeup(fe) || kthread_should_stop() | ||
563 | || freezing(current), | ||
564 | fepriv->delay); | ||
565 | |||
566 | if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { | ||
567 | /* got signal or quitting */ | ||
568 | fepriv->exit = DVB_FE_NORMAL_EXIT; | ||
569 | break; | ||
570 | } | ||
571 | |||
572 | if (try_to_freeze()) | ||
573 | goto restart; | ||
574 | |||
575 | if (down_interruptible(&fepriv->sem)) | ||
576 | break; | ||
577 | |||
578 | if (fepriv->reinitialise) { | ||
579 | dvb_frontend_init(fe); | ||
580 | if (fepriv->tone != -1) { | ||
581 | fe->ops.set_tone(fe, fepriv->tone); | ||
582 | } | ||
583 | if (fepriv->voltage != -1) { | ||
584 | fe->ops.set_voltage(fe, fepriv->voltage); | ||
585 | } | ||
586 | fepriv->reinitialise = 0; | ||
587 | } | ||
588 | |||
589 | /* do an iteration of the tuning loop */ | ||
590 | if (fe->ops.get_frontend_algo) { | ||
591 | algo = fe->ops.get_frontend_algo(fe); | ||
592 | switch (algo) { | ||
593 | case DVBFE_ALGO_HW: | ||
594 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__); | ||
595 | params = NULL; /* have we been asked to RETUNE ? */ | ||
596 | |||
597 | if (fepriv->state & FESTATE_RETUNE) { | ||
598 | dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); | ||
599 | params = &fepriv->parameters_in; | ||
600 | fepriv->state = FESTATE_TUNED; | ||
601 | } | ||
602 | |||
603 | if (fe->ops.tune) | ||
604 | fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); | ||
605 | if (params) | ||
606 | fepriv->parameters_out = *params; | ||
607 | |||
608 | if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { | ||
609 | dprintk("%s: state changed, adding current state\n", __func__); | ||
610 | dvb_frontend_add_event(fe, s); | ||
611 | fepriv->status = s; | ||
612 | } | ||
613 | break; | ||
614 | case DVBFE_ALGO_SW: | ||
615 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__); | ||
616 | dvb_frontend_swzigzag(fe); | ||
617 | break; | ||
618 | case DVBFE_ALGO_CUSTOM: | ||
619 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state); | ||
620 | if (fepriv->state & FESTATE_RETUNE) { | ||
621 | dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__); | ||
622 | fepriv->state = FESTATE_TUNED; | ||
623 | } | ||
624 | /* Case where we are going to search for a carrier | ||
625 | * User asked us to retune again for some reason, possibly | ||
626 | * requesting a search with a new set of parameters | ||
627 | */ | ||
628 | if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) { | ||
629 | if (fe->ops.search) { | ||
630 | fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters_in); | ||
631 | /* We did do a search as was requested, the flags are | ||
632 | * now unset as well and has the flags wrt to search. | ||
633 | */ | ||
634 | } else { | ||
635 | fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN; | ||
636 | } | ||
637 | } | ||
638 | /* Track the carrier if the search was successful */ | ||
639 | if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) { | ||
640 | if (fe->ops.track) | ||
641 | fe->ops.track(fe, &fepriv->parameters_in); | ||
642 | } else { | ||
643 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | ||
644 | fepriv->delay = HZ / 2; | ||
645 | } | ||
646 | fepriv->parameters_out = fepriv->parameters_in; | ||
647 | fe->ops.read_status(fe, &s); | ||
648 | if (s != fepriv->status) { | ||
649 | dvb_frontend_add_event(fe, s); /* update event list */ | ||
650 | fepriv->status = s; | ||
651 | if (!(s & FE_HAS_LOCK)) { | ||
652 | fepriv->delay = HZ / 10; | ||
653 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | ||
654 | } else { | ||
655 | fepriv->delay = 60 * HZ; | ||
656 | } | ||
657 | } | ||
658 | break; | ||
659 | default: | ||
660 | dprintk("%s: UNDEFINED ALGO !\n", __func__); | ||
661 | break; | ||
662 | } | ||
663 | } else { | ||
664 | dvb_frontend_swzigzag(fe); | ||
665 | } | ||
666 | } | ||
667 | |||
668 | if (dvb_powerdown_on_sleep) { | ||
669 | if (fe->ops.set_voltage) | ||
670 | fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); | ||
671 | if (fe->ops.tuner_ops.sleep) { | ||
672 | if (fe->ops.i2c_gate_ctrl) | ||
673 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
674 | fe->ops.tuner_ops.sleep(fe); | ||
675 | if (fe->ops.i2c_gate_ctrl) | ||
676 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
677 | } | ||
678 | if (fe->ops.sleep) | ||
679 | fe->ops.sleep(fe); | ||
680 | } | ||
681 | |||
682 | fepriv->thread = NULL; | ||
683 | if (kthread_should_stop()) | ||
684 | fepriv->exit = DVB_FE_DEVICE_REMOVED; | ||
685 | else | ||
686 | fepriv->exit = DVB_FE_NO_EXIT; | ||
687 | mb(); | ||
688 | |||
689 | dvb_frontend_wakeup(fe); | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | static void dvb_frontend_stop(struct dvb_frontend *fe) | ||
694 | { | ||
695 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
696 | |||
697 | dprintk ("%s\n", __func__); | ||
698 | |||
699 | fepriv->exit = DVB_FE_NORMAL_EXIT; | ||
700 | mb(); | ||
701 | |||
702 | if (!fepriv->thread) | ||
703 | return; | ||
704 | |||
705 | kthread_stop(fepriv->thread); | ||
706 | |||
707 | sema_init(&fepriv->sem, 1); | ||
708 | fepriv->state = FESTATE_IDLE; | ||
709 | |||
710 | /* paranoia check in case a signal arrived */ | ||
711 | if (fepriv->thread) | ||
712 | printk("dvb_frontend_stop: warning: thread %p won't exit\n", | ||
713 | fepriv->thread); | ||
714 | } | ||
715 | |||
716 | s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime) | ||
717 | { | ||
718 | return ((curtime.tv_usec < lasttime.tv_usec) ? | ||
719 | 1000000 - lasttime.tv_usec + curtime.tv_usec : | ||
720 | curtime.tv_usec - lasttime.tv_usec); | ||
721 | } | ||
722 | EXPORT_SYMBOL(timeval_usec_diff); | ||
723 | |||
724 | static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec) | ||
725 | { | ||
726 | curtime->tv_usec += add_usec; | ||
727 | if (curtime->tv_usec >= 1000000) { | ||
728 | curtime->tv_usec -= 1000000; | ||
729 | curtime->tv_sec++; | ||
730 | } | ||
731 | } | ||
732 | |||
733 | /* | ||
734 | * Sleep until gettimeofday() > waketime + add_usec | ||
735 | * This needs to be as precise as possible, but as the delay is | ||
736 | * usually between 2ms and 32ms, it is done using a scheduled msleep | ||
737 | * followed by usleep (normally a busy-wait loop) for the remainder | ||
738 | */ | ||
739 | void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec) | ||
740 | { | ||
741 | struct timeval lasttime; | ||
742 | s32 delta, newdelta; | ||
743 | |||
744 | timeval_usec_add(waketime, add_usec); | ||
745 | |||
746 | do_gettimeofday(&lasttime); | ||
747 | delta = timeval_usec_diff(lasttime, *waketime); | ||
748 | if (delta > 2500) { | ||
749 | msleep((delta - 1500) / 1000); | ||
750 | do_gettimeofday(&lasttime); | ||
751 | newdelta = timeval_usec_diff(lasttime, *waketime); | ||
752 | delta = (newdelta > delta) ? 0 : newdelta; | ||
753 | } | ||
754 | if (delta > 0) | ||
755 | udelay(delta); | ||
756 | } | ||
757 | EXPORT_SYMBOL(dvb_frontend_sleep_until); | ||
758 | |||
759 | static int dvb_frontend_start(struct dvb_frontend *fe) | ||
760 | { | ||
761 | int ret; | ||
762 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
763 | struct task_struct *fe_thread; | ||
764 | |||
765 | dprintk ("%s\n", __func__); | ||
766 | |||
767 | if (fepriv->thread) { | ||
768 | if (fepriv->exit == DVB_FE_NO_EXIT) | ||
769 | return 0; | ||
770 | else | ||
771 | dvb_frontend_stop (fe); | ||
772 | } | ||
773 | |||
774 | if (signal_pending(current)) | ||
775 | return -EINTR; | ||
776 | if (down_interruptible (&fepriv->sem)) | ||
777 | return -EINTR; | ||
778 | |||
779 | fepriv->state = FESTATE_IDLE; | ||
780 | fepriv->exit = DVB_FE_NO_EXIT; | ||
781 | fepriv->thread = NULL; | ||
782 | mb(); | ||
783 | |||
784 | fe_thread = kthread_run(dvb_frontend_thread, fe, | ||
785 | "kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id); | ||
786 | if (IS_ERR(fe_thread)) { | ||
787 | ret = PTR_ERR(fe_thread); | ||
788 | printk("dvb_frontend_start: failed to start kthread (%d)\n", ret); | ||
789 | up(&fepriv->sem); | ||
790 | return ret; | ||
791 | } | ||
792 | fepriv->thread = fe_thread; | ||
793 | return 0; | ||
794 | } | ||
795 | |||
796 | static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe, | ||
797 | u32 *freq_min, u32 *freq_max) | ||
798 | { | ||
799 | *freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min); | ||
800 | |||
801 | if (fe->ops.info.frequency_max == 0) | ||
802 | *freq_max = fe->ops.tuner_ops.info.frequency_max; | ||
803 | else if (fe->ops.tuner_ops.info.frequency_max == 0) | ||
804 | *freq_max = fe->ops.info.frequency_max; | ||
805 | else | ||
806 | *freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max); | ||
807 | |||
808 | if (*freq_min == 0 || *freq_max == 0) | ||
809 | printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", | ||
810 | fe->dvb->num,fe->id); | ||
811 | } | ||
812 | |||
813 | static int dvb_frontend_check_parameters(struct dvb_frontend *fe, | ||
814 | struct dvb_frontend_parameters *parms) | ||
815 | { | ||
816 | u32 freq_min; | ||
817 | u32 freq_max; | ||
818 | |||
819 | /* range check: frequency */ | ||
820 | dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max); | ||
821 | if ((freq_min && parms->frequency < freq_min) || | ||
822 | (freq_max && parms->frequency > freq_max)) { | ||
823 | printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", | ||
824 | fe->dvb->num, fe->id, parms->frequency, freq_min, freq_max); | ||
825 | return -EINVAL; | ||
826 | } | ||
827 | |||
828 | /* range check: symbol rate */ | ||
829 | if (fe->ops.info.type == FE_QPSK) { | ||
830 | if ((fe->ops.info.symbol_rate_min && | ||
831 | parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) || | ||
832 | (fe->ops.info.symbol_rate_max && | ||
833 | parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) { | ||
834 | printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", | ||
835 | fe->dvb->num, fe->id, parms->u.qpsk.symbol_rate, | ||
836 | fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); | ||
837 | return -EINVAL; | ||
838 | } | ||
839 | |||
840 | } else if (fe->ops.info.type == FE_QAM) { | ||
841 | if ((fe->ops.info.symbol_rate_min && | ||
842 | parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) || | ||
843 | (fe->ops.info.symbol_rate_max && | ||
844 | parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) { | ||
845 | printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", | ||
846 | fe->dvb->num, fe->id, parms->u.qam.symbol_rate, | ||
847 | fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); | ||
848 | return -EINVAL; | ||
849 | } | ||
850 | } | ||
851 | |||
852 | /* check for supported modulation */ | ||
853 | if (fe->ops.info.type == FE_QAM && | ||
854 | (parms->u.qam.modulation > QAM_AUTO || | ||
855 | !((1 << (parms->u.qam.modulation + 10)) & fe->ops.info.caps))) { | ||
856 | printk(KERN_WARNING "DVB: adapter %i frontend %i modulation %u not supported\n", | ||
857 | fe->dvb->num, fe->id, parms->u.qam.modulation); | ||
858 | return -EINVAL; | ||
859 | } | ||
860 | |||
861 | return 0; | ||
862 | } | ||
863 | |||
864 | static int dvb_frontend_clear_cache(struct dvb_frontend *fe) | ||
865 | { | ||
866 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
867 | int i; | ||
868 | |||
869 | memset(c, 0, sizeof(struct dtv_frontend_properties)); | ||
870 | |||
871 | c->state = DTV_CLEAR; | ||
872 | c->delivery_system = SYS_UNDEFINED; | ||
873 | c->inversion = INVERSION_AUTO; | ||
874 | c->fec_inner = FEC_AUTO; | ||
875 | c->transmission_mode = TRANSMISSION_MODE_AUTO; | ||
876 | c->bandwidth_hz = BANDWIDTH_AUTO; | ||
877 | c->guard_interval = GUARD_INTERVAL_AUTO; | ||
878 | c->hierarchy = HIERARCHY_AUTO; | ||
879 | c->symbol_rate = QAM_AUTO; | ||
880 | c->code_rate_HP = FEC_AUTO; | ||
881 | c->code_rate_LP = FEC_AUTO; | ||
882 | |||
883 | c->isdbt_partial_reception = -1; | ||
884 | c->isdbt_sb_mode = -1; | ||
885 | c->isdbt_sb_subchannel = -1; | ||
886 | c->isdbt_sb_segment_idx = -1; | ||
887 | c->isdbt_sb_segment_count = -1; | ||
888 | c->isdbt_layer_enabled = 0x7; | ||
889 | for (i = 0; i < 3; i++) { | ||
890 | c->layer[i].fec = FEC_AUTO; | ||
891 | c->layer[i].modulation = QAM_AUTO; | ||
892 | c->layer[i].interleaving = -1; | ||
893 | c->layer[i].segment_count = -1; | ||
894 | } | ||
895 | |||
896 | return 0; | ||
897 | } | ||
898 | |||
899 | #define _DTV_CMD(n, s, b) \ | ||
900 | [n] = { \ | ||
901 | .name = #n, \ | ||
902 | .cmd = n, \ | ||
903 | .set = s,\ | ||
904 | .buffer = b \ | ||
905 | } | ||
906 | |||
907 | static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { | ||
908 | _DTV_CMD(DTV_TUNE, 1, 0), | ||
909 | _DTV_CMD(DTV_CLEAR, 1, 0), | ||
910 | |||
911 | /* Set */ | ||
912 | _DTV_CMD(DTV_FREQUENCY, 1, 0), | ||
913 | _DTV_CMD(DTV_BANDWIDTH_HZ, 1, 0), | ||
914 | _DTV_CMD(DTV_MODULATION, 1, 0), | ||
915 | _DTV_CMD(DTV_INVERSION, 1, 0), | ||
916 | _DTV_CMD(DTV_DISEQC_MASTER, 1, 1), | ||
917 | _DTV_CMD(DTV_SYMBOL_RATE, 1, 0), | ||
918 | _DTV_CMD(DTV_INNER_FEC, 1, 0), | ||
919 | _DTV_CMD(DTV_VOLTAGE, 1, 0), | ||
920 | _DTV_CMD(DTV_TONE, 1, 0), | ||
921 | _DTV_CMD(DTV_PILOT, 1, 0), | ||
922 | _DTV_CMD(DTV_ROLLOFF, 1, 0), | ||
923 | _DTV_CMD(DTV_DELIVERY_SYSTEM, 1, 0), | ||
924 | _DTV_CMD(DTV_HIERARCHY, 1, 0), | ||
925 | _DTV_CMD(DTV_CODE_RATE_HP, 1, 0), | ||
926 | _DTV_CMD(DTV_CODE_RATE_LP, 1, 0), | ||
927 | _DTV_CMD(DTV_GUARD_INTERVAL, 1, 0), | ||
928 | _DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0), | ||
929 | |||
930 | _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0), | ||
931 | _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0), | ||
932 | _DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 1, 0), | ||
933 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 1, 0), | ||
934 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 1, 0), | ||
935 | _DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 1, 0), | ||
936 | _DTV_CMD(DTV_ISDBT_LAYERA_FEC, 1, 0), | ||
937 | _DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 1, 0), | ||
938 | _DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 1, 0), | ||
939 | _DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 1, 0), | ||
940 | _DTV_CMD(DTV_ISDBT_LAYERB_FEC, 1, 0), | ||
941 | _DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 1, 0), | ||
942 | _DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 1, 0), | ||
943 | _DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 1, 0), | ||
944 | _DTV_CMD(DTV_ISDBT_LAYERC_FEC, 1, 0), | ||
945 | _DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 1, 0), | ||
946 | _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0), | ||
947 | _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0), | ||
948 | |||
949 | _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 0, 0), | ||
950 | _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 0, 0), | ||
951 | _DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 0, 0), | ||
952 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 0, 0), | ||
953 | _DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 0, 0), | ||
954 | _DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 0, 0), | ||
955 | _DTV_CMD(DTV_ISDBT_LAYERA_FEC, 0, 0), | ||
956 | _DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 0, 0), | ||
957 | _DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 0, 0), | ||
958 | _DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 0, 0), | ||
959 | _DTV_CMD(DTV_ISDBT_LAYERB_FEC, 0, 0), | ||
960 | _DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 0, 0), | ||
961 | _DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 0, 0), | ||
962 | _DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 0, 0), | ||
963 | _DTV_CMD(DTV_ISDBT_LAYERC_FEC, 0, 0), | ||
964 | _DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 0, 0), | ||
965 | _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 0, 0), | ||
966 | _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0, 0), | ||
967 | |||
968 | _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0), | ||
969 | _DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0), | ||
970 | |||
971 | /* Get */ | ||
972 | _DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1), | ||
973 | _DTV_CMD(DTV_API_VERSION, 0, 0), | ||
974 | _DTV_CMD(DTV_CODE_RATE_HP, 0, 0), | ||
975 | _DTV_CMD(DTV_CODE_RATE_LP, 0, 0), | ||
976 | _DTV_CMD(DTV_GUARD_INTERVAL, 0, 0), | ||
977 | _DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0), | ||
978 | _DTV_CMD(DTV_HIERARCHY, 0, 0), | ||
979 | }; | ||
980 | |||
981 | static void dtv_property_dump(struct dtv_property *tvp) | ||
982 | { | ||
983 | int i; | ||
984 | |||
985 | if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { | ||
986 | printk(KERN_WARNING "%s: tvp.cmd = 0x%08x undefined\n", | ||
987 | __func__, tvp->cmd); | ||
988 | return; | ||
989 | } | ||
990 | |||
991 | dprintk("%s() tvp.cmd = 0x%08x (%s)\n" | ||
992 | ,__func__ | ||
993 | ,tvp->cmd | ||
994 | ,dtv_cmds[ tvp->cmd ].name); | ||
995 | |||
996 | if(dtv_cmds[ tvp->cmd ].buffer) { | ||
997 | |||
998 | dprintk("%s() tvp.u.buffer.len = 0x%02x\n" | ||
999 | ,__func__ | ||
1000 | ,tvp->u.buffer.len); | ||
1001 | |||
1002 | for(i = 0; i < tvp->u.buffer.len; i++) | ||
1003 | dprintk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n" | ||
1004 | ,__func__ | ||
1005 | ,i | ||
1006 | ,tvp->u.buffer.data[i]); | ||
1007 | |||
1008 | } else | ||
1009 | dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data); | ||
1010 | } | ||
1011 | |||
1012 | static int is_legacy_delivery_system(fe_delivery_system_t s) | ||
1013 | { | ||
1014 | if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) || | ||
1015 | (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) || | ||
1016 | (s == SYS_ATSC)) | ||
1017 | return 1; | ||
1018 | |||
1019 | return 0; | ||
1020 | } | ||
1021 | |||
1022 | /* Synchronise the legacy tuning parameters into the cache, so that demodulator | ||
1023 | * drivers can use a single set_frontend tuning function, regardless of whether | ||
1024 | * it's being used for the legacy or new API, reducing code and complexity. | ||
1025 | */ | ||
1026 | static void dtv_property_cache_sync(struct dvb_frontend *fe, | ||
1027 | struct dtv_frontend_properties *c, | ||
1028 | const struct dvb_frontend_parameters *p) | ||
1029 | { | ||
1030 | c->frequency = p->frequency; | ||
1031 | c->inversion = p->inversion; | ||
1032 | |||
1033 | switch (fe->ops.info.type) { | ||
1034 | case FE_QPSK: | ||
1035 | c->modulation = QPSK; /* implied for DVB-S in legacy API */ | ||
1036 | c->rolloff = ROLLOFF_35;/* implied for DVB-S */ | ||
1037 | c->symbol_rate = p->u.qpsk.symbol_rate; | ||
1038 | c->fec_inner = p->u.qpsk.fec_inner; | ||
1039 | c->delivery_system = SYS_DVBS; | ||
1040 | break; | ||
1041 | case FE_QAM: | ||
1042 | c->symbol_rate = p->u.qam.symbol_rate; | ||
1043 | c->fec_inner = p->u.qam.fec_inner; | ||
1044 | c->modulation = p->u.qam.modulation; | ||
1045 | c->delivery_system = SYS_DVBC_ANNEX_AC; | ||
1046 | break; | ||
1047 | case FE_OFDM: | ||
1048 | if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ) | ||
1049 | c->bandwidth_hz = 6000000; | ||
1050 | else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ) | ||
1051 | c->bandwidth_hz = 7000000; | ||
1052 | else if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) | ||
1053 | c->bandwidth_hz = 8000000; | ||
1054 | else | ||
1055 | /* Including BANDWIDTH_AUTO */ | ||
1056 | c->bandwidth_hz = 0; | ||
1057 | c->code_rate_HP = p->u.ofdm.code_rate_HP; | ||
1058 | c->code_rate_LP = p->u.ofdm.code_rate_LP; | ||
1059 | c->modulation = p->u.ofdm.constellation; | ||
1060 | c->transmission_mode = p->u.ofdm.transmission_mode; | ||
1061 | c->guard_interval = p->u.ofdm.guard_interval; | ||
1062 | c->hierarchy = p->u.ofdm.hierarchy_information; | ||
1063 | c->delivery_system = SYS_DVBT; | ||
1064 | break; | ||
1065 | case FE_ATSC: | ||
1066 | c->modulation = p->u.vsb.modulation; | ||
1067 | if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) | ||
1068 | c->delivery_system = SYS_ATSC; | ||
1069 | else | ||
1070 | c->delivery_system = SYS_DVBC_ANNEX_B; | ||
1071 | break; | ||
1072 | } | ||
1073 | } | ||
1074 | |||
1075 | /* Ensure the cached values are set correctly in the frontend | ||
1076 | * legacy tuning structures, for the advanced tuning API. | ||
1077 | */ | ||
1078 | static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) | ||
1079 | { | ||
1080 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1081 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1082 | struct dvb_frontend_parameters *p = &fepriv->parameters_in; | ||
1083 | |||
1084 | p->frequency = c->frequency; | ||
1085 | p->inversion = c->inversion; | ||
1086 | |||
1087 | switch (fe->ops.info.type) { | ||
1088 | case FE_QPSK: | ||
1089 | dprintk("%s() Preparing QPSK req\n", __func__); | ||
1090 | p->u.qpsk.symbol_rate = c->symbol_rate; | ||
1091 | p->u.qpsk.fec_inner = c->fec_inner; | ||
1092 | break; | ||
1093 | case FE_QAM: | ||
1094 | dprintk("%s() Preparing QAM req\n", __func__); | ||
1095 | p->u.qam.symbol_rate = c->symbol_rate; | ||
1096 | p->u.qam.fec_inner = c->fec_inner; | ||
1097 | p->u.qam.modulation = c->modulation; | ||
1098 | break; | ||
1099 | case FE_OFDM: | ||
1100 | dprintk("%s() Preparing OFDM req\n", __func__); | ||
1101 | if (c->bandwidth_hz == 6000000) | ||
1102 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
1103 | else if (c->bandwidth_hz == 7000000) | ||
1104 | p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; | ||
1105 | else if (c->bandwidth_hz == 8000000) | ||
1106 | p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | ||
1107 | else | ||
1108 | p->u.ofdm.bandwidth = BANDWIDTH_AUTO; | ||
1109 | p->u.ofdm.code_rate_HP = c->code_rate_HP; | ||
1110 | p->u.ofdm.code_rate_LP = c->code_rate_LP; | ||
1111 | p->u.ofdm.constellation = c->modulation; | ||
1112 | p->u.ofdm.transmission_mode = c->transmission_mode; | ||
1113 | p->u.ofdm.guard_interval = c->guard_interval; | ||
1114 | p->u.ofdm.hierarchy_information = c->hierarchy; | ||
1115 | break; | ||
1116 | case FE_ATSC: | ||
1117 | dprintk("%s() Preparing VSB req\n", __func__); | ||
1118 | p->u.vsb.modulation = c->modulation; | ||
1119 | break; | ||
1120 | } | ||
1121 | } | ||
1122 | |||
1123 | /* Ensure the cached values are set correctly in the frontend | ||
1124 | * legacy tuning structures, for the legacy tuning API. | ||
1125 | */ | ||
1126 | static void dtv_property_adv_params_sync(struct dvb_frontend *fe) | ||
1127 | { | ||
1128 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1129 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1130 | struct dvb_frontend_parameters *p = &fepriv->parameters_in; | ||
1131 | |||
1132 | p->frequency = c->frequency; | ||
1133 | p->inversion = c->inversion; | ||
1134 | |||
1135 | switch(c->modulation) { | ||
1136 | case PSK_8: | ||
1137 | case APSK_16: | ||
1138 | case APSK_32: | ||
1139 | case QPSK: | ||
1140 | p->u.qpsk.symbol_rate = c->symbol_rate; | ||
1141 | p->u.qpsk.fec_inner = c->fec_inner; | ||
1142 | break; | ||
1143 | default: | ||
1144 | break; | ||
1145 | } | ||
1146 | |||
1147 | /* Fake out a generic DVB-T request so we pass validation in the ioctl */ | ||
1148 | if ((c->delivery_system == SYS_ISDBT) || | ||
1149 | (c->delivery_system == SYS_DVBT2)) { | ||
1150 | p->u.ofdm.constellation = QAM_AUTO; | ||
1151 | p->u.ofdm.code_rate_HP = FEC_AUTO; | ||
1152 | p->u.ofdm.code_rate_LP = FEC_AUTO; | ||
1153 | p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; | ||
1154 | p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; | ||
1155 | p->u.ofdm.hierarchy_information = HIERARCHY_AUTO; | ||
1156 | if (c->bandwidth_hz == 8000000) | ||
1157 | p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | ||
1158 | else if (c->bandwidth_hz == 7000000) | ||
1159 | p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; | ||
1160 | else if (c->bandwidth_hz == 6000000) | ||
1161 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
1162 | else | ||
1163 | p->u.ofdm.bandwidth = BANDWIDTH_AUTO; | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1167 | static void dtv_property_cache_submit(struct dvb_frontend *fe) | ||
1168 | { | ||
1169 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1170 | |||
1171 | /* For legacy delivery systems we don't need the delivery_system to | ||
1172 | * be specified, but we populate the older structures from the cache | ||
1173 | * so we can call set_frontend on older drivers. | ||
1174 | */ | ||
1175 | if(is_legacy_delivery_system(c->delivery_system)) { | ||
1176 | |||
1177 | dprintk("%s() legacy, modulation = %d\n", __func__, c->modulation); | ||
1178 | dtv_property_legacy_params_sync(fe); | ||
1179 | |||
1180 | } else { | ||
1181 | dprintk("%s() adv, modulation = %d\n", __func__, c->modulation); | ||
1182 | |||
1183 | /* For advanced delivery systems / modulation types ... | ||
1184 | * we seed the lecacy dvb_frontend_parameters structure | ||
1185 | * so that the sanity checking code later in the IOCTL processing | ||
1186 | * can validate our basic frequency ranges, symbolrates, modulation | ||
1187 | * etc. | ||
1188 | */ | ||
1189 | dtv_property_adv_params_sync(fe); | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1193 | static int dvb_frontend_ioctl_legacy(struct file *file, | ||
1194 | unsigned int cmd, void *parg); | ||
1195 | static int dvb_frontend_ioctl_properties(struct file *file, | ||
1196 | unsigned int cmd, void *parg); | ||
1197 | |||
1198 | static int dtv_property_process_get(struct dvb_frontend *fe, | ||
1199 | struct dtv_property *tvp, | ||
1200 | struct file *file) | ||
1201 | { | ||
1202 | const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1203 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1204 | struct dtv_frontend_properties cdetected; | ||
1205 | int r; | ||
1206 | |||
1207 | /* | ||
1208 | * If the driver implements a get_frontend function, then convert | ||
1209 | * detected parameters to S2API properties. | ||
1210 | */ | ||
1211 | if (fe->ops.get_frontend) { | ||
1212 | cdetected = *c; | ||
1213 | dtv_property_cache_sync(fe, &cdetected, &fepriv->parameters_out); | ||
1214 | c = &cdetected; | ||
1215 | } | ||
1216 | |||
1217 | switch(tvp->cmd) { | ||
1218 | case DTV_FREQUENCY: | ||
1219 | tvp->u.data = c->frequency; | ||
1220 | break; | ||
1221 | case DTV_MODULATION: | ||
1222 | tvp->u.data = c->modulation; | ||
1223 | break; | ||
1224 | case DTV_BANDWIDTH_HZ: | ||
1225 | tvp->u.data = c->bandwidth_hz; | ||
1226 | break; | ||
1227 | case DTV_INVERSION: | ||
1228 | tvp->u.data = c->inversion; | ||
1229 | break; | ||
1230 | case DTV_SYMBOL_RATE: | ||
1231 | tvp->u.data = c->symbol_rate; | ||
1232 | break; | ||
1233 | case DTV_INNER_FEC: | ||
1234 | tvp->u.data = c->fec_inner; | ||
1235 | break; | ||
1236 | case DTV_PILOT: | ||
1237 | tvp->u.data = c->pilot; | ||
1238 | break; | ||
1239 | case DTV_ROLLOFF: | ||
1240 | tvp->u.data = c->rolloff; | ||
1241 | break; | ||
1242 | case DTV_DELIVERY_SYSTEM: | ||
1243 | tvp->u.data = c->delivery_system; | ||
1244 | break; | ||
1245 | case DTV_VOLTAGE: | ||
1246 | tvp->u.data = c->voltage; | ||
1247 | break; | ||
1248 | case DTV_TONE: | ||
1249 | tvp->u.data = c->sectone; | ||
1250 | break; | ||
1251 | case DTV_API_VERSION: | ||
1252 | tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR; | ||
1253 | break; | ||
1254 | case DTV_CODE_RATE_HP: | ||
1255 | tvp->u.data = c->code_rate_HP; | ||
1256 | break; | ||
1257 | case DTV_CODE_RATE_LP: | ||
1258 | tvp->u.data = c->code_rate_LP; | ||
1259 | break; | ||
1260 | case DTV_GUARD_INTERVAL: | ||
1261 | tvp->u.data = c->guard_interval; | ||
1262 | break; | ||
1263 | case DTV_TRANSMISSION_MODE: | ||
1264 | tvp->u.data = c->transmission_mode; | ||
1265 | break; | ||
1266 | case DTV_HIERARCHY: | ||
1267 | tvp->u.data = c->hierarchy; | ||
1268 | break; | ||
1269 | |||
1270 | /* ISDB-T Support here */ | ||
1271 | case DTV_ISDBT_PARTIAL_RECEPTION: | ||
1272 | tvp->u.data = c->isdbt_partial_reception; | ||
1273 | break; | ||
1274 | case DTV_ISDBT_SOUND_BROADCASTING: | ||
1275 | tvp->u.data = c->isdbt_sb_mode; | ||
1276 | break; | ||
1277 | case DTV_ISDBT_SB_SUBCHANNEL_ID: | ||
1278 | tvp->u.data = c->isdbt_sb_subchannel; | ||
1279 | break; | ||
1280 | case DTV_ISDBT_SB_SEGMENT_IDX: | ||
1281 | tvp->u.data = c->isdbt_sb_segment_idx; | ||
1282 | break; | ||
1283 | case DTV_ISDBT_SB_SEGMENT_COUNT: | ||
1284 | tvp->u.data = c->isdbt_sb_segment_count; | ||
1285 | break; | ||
1286 | case DTV_ISDBT_LAYER_ENABLED: | ||
1287 | tvp->u.data = c->isdbt_layer_enabled; | ||
1288 | break; | ||
1289 | case DTV_ISDBT_LAYERA_FEC: | ||
1290 | tvp->u.data = c->layer[0].fec; | ||
1291 | break; | ||
1292 | case DTV_ISDBT_LAYERA_MODULATION: | ||
1293 | tvp->u.data = c->layer[0].modulation; | ||
1294 | break; | ||
1295 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: | ||
1296 | tvp->u.data = c->layer[0].segment_count; | ||
1297 | break; | ||
1298 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: | ||
1299 | tvp->u.data = c->layer[0].interleaving; | ||
1300 | break; | ||
1301 | case DTV_ISDBT_LAYERB_FEC: | ||
1302 | tvp->u.data = c->layer[1].fec; | ||
1303 | break; | ||
1304 | case DTV_ISDBT_LAYERB_MODULATION: | ||
1305 | tvp->u.data = c->layer[1].modulation; | ||
1306 | break; | ||
1307 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: | ||
1308 | tvp->u.data = c->layer[1].segment_count; | ||
1309 | break; | ||
1310 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: | ||
1311 | tvp->u.data = c->layer[1].interleaving; | ||
1312 | break; | ||
1313 | case DTV_ISDBT_LAYERC_FEC: | ||
1314 | tvp->u.data = c->layer[2].fec; | ||
1315 | break; | ||
1316 | case DTV_ISDBT_LAYERC_MODULATION: | ||
1317 | tvp->u.data = c->layer[2].modulation; | ||
1318 | break; | ||
1319 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: | ||
1320 | tvp->u.data = c->layer[2].segment_count; | ||
1321 | break; | ||
1322 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: | ||
1323 | tvp->u.data = c->layer[2].interleaving; | ||
1324 | break; | ||
1325 | case DTV_ISDBS_TS_ID: | ||
1326 | tvp->u.data = c->isdbs_ts_id; | ||
1327 | break; | ||
1328 | case DTV_DVBT2_PLP_ID: | ||
1329 | tvp->u.data = c->dvbt2_plp_id; | ||
1330 | break; | ||
1331 | default: | ||
1332 | return -EINVAL; | ||
1333 | } | ||
1334 | |||
1335 | /* Allow the frontend to override outgoing properties */ | ||
1336 | if (fe->ops.get_property) { | ||
1337 | r = fe->ops.get_property(fe, tvp); | ||
1338 | if (r < 0) | ||
1339 | return r; | ||
1340 | } | ||
1341 | |||
1342 | dtv_property_dump(tvp); | ||
1343 | |||
1344 | return 0; | ||
1345 | } | ||
1346 | |||
1347 | static int dtv_property_process_set(struct dvb_frontend *fe, | ||
1348 | struct dtv_property *tvp, | ||
1349 | struct file *file) | ||
1350 | { | ||
1351 | int r = 0; | ||
1352 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1353 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1354 | dtv_property_dump(tvp); | ||
1355 | |||
1356 | /* Allow the frontend to validate incoming properties */ | ||
1357 | if (fe->ops.set_property) { | ||
1358 | r = fe->ops.set_property(fe, tvp); | ||
1359 | if (r < 0) | ||
1360 | return r; | ||
1361 | } | ||
1362 | |||
1363 | switch(tvp->cmd) { | ||
1364 | case DTV_CLEAR: | ||
1365 | /* Reset a cache of data specific to the frontend here. This does | ||
1366 | * not effect hardware. | ||
1367 | */ | ||
1368 | dvb_frontend_clear_cache(fe); | ||
1369 | dprintk("%s() Flushing property cache\n", __func__); | ||
1370 | break; | ||
1371 | case DTV_TUNE: | ||
1372 | /* interpret the cache of data, build either a traditional frontend | ||
1373 | * tunerequest so we can pass validation in the FE_SET_FRONTEND | ||
1374 | * ioctl. | ||
1375 | */ | ||
1376 | c->state = tvp->cmd; | ||
1377 | dprintk("%s() Finalised property cache\n", __func__); | ||
1378 | dtv_property_cache_submit(fe); | ||
1379 | |||
1380 | r = dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND, | ||
1381 | &fepriv->parameters_in); | ||
1382 | break; | ||
1383 | case DTV_FREQUENCY: | ||
1384 | c->frequency = tvp->u.data; | ||
1385 | break; | ||
1386 | case DTV_MODULATION: | ||
1387 | c->modulation = tvp->u.data; | ||
1388 | break; | ||
1389 | case DTV_BANDWIDTH_HZ: | ||
1390 | c->bandwidth_hz = tvp->u.data; | ||
1391 | break; | ||
1392 | case DTV_INVERSION: | ||
1393 | c->inversion = tvp->u.data; | ||
1394 | break; | ||
1395 | case DTV_SYMBOL_RATE: | ||
1396 | c->symbol_rate = tvp->u.data; | ||
1397 | break; | ||
1398 | case DTV_INNER_FEC: | ||
1399 | c->fec_inner = tvp->u.data; | ||
1400 | break; | ||
1401 | case DTV_PILOT: | ||
1402 | c->pilot = tvp->u.data; | ||
1403 | break; | ||
1404 | case DTV_ROLLOFF: | ||
1405 | c->rolloff = tvp->u.data; | ||
1406 | break; | ||
1407 | case DTV_DELIVERY_SYSTEM: | ||
1408 | c->delivery_system = tvp->u.data; | ||
1409 | break; | ||
1410 | case DTV_VOLTAGE: | ||
1411 | c->voltage = tvp->u.data; | ||
1412 | r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE, | ||
1413 | (void *)c->voltage); | ||
1414 | break; | ||
1415 | case DTV_TONE: | ||
1416 | c->sectone = tvp->u.data; | ||
1417 | r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE, | ||
1418 | (void *)c->sectone); | ||
1419 | break; | ||
1420 | case DTV_CODE_RATE_HP: | ||
1421 | c->code_rate_HP = tvp->u.data; | ||
1422 | break; | ||
1423 | case DTV_CODE_RATE_LP: | ||
1424 | c->code_rate_LP = tvp->u.data; | ||
1425 | break; | ||
1426 | case DTV_GUARD_INTERVAL: | ||
1427 | c->guard_interval = tvp->u.data; | ||
1428 | break; | ||
1429 | case DTV_TRANSMISSION_MODE: | ||
1430 | c->transmission_mode = tvp->u.data; | ||
1431 | break; | ||
1432 | case DTV_HIERARCHY: | ||
1433 | c->hierarchy = tvp->u.data; | ||
1434 | break; | ||
1435 | |||
1436 | /* ISDB-T Support here */ | ||
1437 | case DTV_ISDBT_PARTIAL_RECEPTION: | ||
1438 | c->isdbt_partial_reception = tvp->u.data; | ||
1439 | break; | ||
1440 | case DTV_ISDBT_SOUND_BROADCASTING: | ||
1441 | c->isdbt_sb_mode = tvp->u.data; | ||
1442 | break; | ||
1443 | case DTV_ISDBT_SB_SUBCHANNEL_ID: | ||
1444 | c->isdbt_sb_subchannel = tvp->u.data; | ||
1445 | break; | ||
1446 | case DTV_ISDBT_SB_SEGMENT_IDX: | ||
1447 | c->isdbt_sb_segment_idx = tvp->u.data; | ||
1448 | break; | ||
1449 | case DTV_ISDBT_SB_SEGMENT_COUNT: | ||
1450 | c->isdbt_sb_segment_count = tvp->u.data; | ||
1451 | break; | ||
1452 | case DTV_ISDBT_LAYER_ENABLED: | ||
1453 | c->isdbt_layer_enabled = tvp->u.data; | ||
1454 | break; | ||
1455 | case DTV_ISDBT_LAYERA_FEC: | ||
1456 | c->layer[0].fec = tvp->u.data; | ||
1457 | break; | ||
1458 | case DTV_ISDBT_LAYERA_MODULATION: | ||
1459 | c->layer[0].modulation = tvp->u.data; | ||
1460 | break; | ||
1461 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: | ||
1462 | c->layer[0].segment_count = tvp->u.data; | ||
1463 | break; | ||
1464 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: | ||
1465 | c->layer[0].interleaving = tvp->u.data; | ||
1466 | break; | ||
1467 | case DTV_ISDBT_LAYERB_FEC: | ||
1468 | c->layer[1].fec = tvp->u.data; | ||
1469 | break; | ||
1470 | case DTV_ISDBT_LAYERB_MODULATION: | ||
1471 | c->layer[1].modulation = tvp->u.data; | ||
1472 | break; | ||
1473 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: | ||
1474 | c->layer[1].segment_count = tvp->u.data; | ||
1475 | break; | ||
1476 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: | ||
1477 | c->layer[1].interleaving = tvp->u.data; | ||
1478 | break; | ||
1479 | case DTV_ISDBT_LAYERC_FEC: | ||
1480 | c->layer[2].fec = tvp->u.data; | ||
1481 | break; | ||
1482 | case DTV_ISDBT_LAYERC_MODULATION: | ||
1483 | c->layer[2].modulation = tvp->u.data; | ||
1484 | break; | ||
1485 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: | ||
1486 | c->layer[2].segment_count = tvp->u.data; | ||
1487 | break; | ||
1488 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: | ||
1489 | c->layer[2].interleaving = tvp->u.data; | ||
1490 | break; | ||
1491 | case DTV_ISDBS_TS_ID: | ||
1492 | c->isdbs_ts_id = tvp->u.data; | ||
1493 | break; | ||
1494 | case DTV_DVBT2_PLP_ID: | ||
1495 | c->dvbt2_plp_id = tvp->u.data; | ||
1496 | break; | ||
1497 | default: | ||
1498 | return -EINVAL; | ||
1499 | } | ||
1500 | |||
1501 | return r; | ||
1502 | } | ||
1503 | |||
1504 | static int dvb_frontend_ioctl(struct file *file, | ||
1505 | unsigned int cmd, void *parg) | ||
1506 | { | ||
1507 | struct dvb_device *dvbdev = file->private_data; | ||
1508 | struct dvb_frontend *fe = dvbdev->priv; | ||
1509 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1510 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1511 | int err = -EOPNOTSUPP; | ||
1512 | |||
1513 | dprintk("%s (%d)\n", __func__, _IOC_NR(cmd)); | ||
1514 | |||
1515 | if (fepriv->exit != DVB_FE_NO_EXIT) | ||
1516 | return -ENODEV; | ||
1517 | |||
1518 | if ((file->f_flags & O_ACCMODE) == O_RDONLY && | ||
1519 | (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT || | ||
1520 | cmd == FE_DISEQC_RECV_SLAVE_REPLY)) | ||
1521 | return -EPERM; | ||
1522 | |||
1523 | if (down_interruptible (&fepriv->sem)) | ||
1524 | return -ERESTARTSYS; | ||
1525 | |||
1526 | if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) | ||
1527 | err = dvb_frontend_ioctl_properties(file, cmd, parg); | ||
1528 | else { | ||
1529 | c->state = DTV_UNDEFINED; | ||
1530 | err = dvb_frontend_ioctl_legacy(file, cmd, parg); | ||
1531 | } | ||
1532 | |||
1533 | up(&fepriv->sem); | ||
1534 | return err; | ||
1535 | } | ||
1536 | |||
1537 | static int dvb_frontend_ioctl_properties(struct file *file, | ||
1538 | unsigned int cmd, void *parg) | ||
1539 | { | ||
1540 | struct dvb_device *dvbdev = file->private_data; | ||
1541 | struct dvb_frontend *fe = dvbdev->priv; | ||
1542 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1543 | int err = 0; | ||
1544 | |||
1545 | struct dtv_properties *tvps = NULL; | ||
1546 | struct dtv_property *tvp = NULL; | ||
1547 | int i; | ||
1548 | |||
1549 | dprintk("%s\n", __func__); | ||
1550 | |||
1551 | if(cmd == FE_SET_PROPERTY) { | ||
1552 | tvps = (struct dtv_properties __user *)parg; | ||
1553 | |||
1554 | dprintk("%s() properties.num = %d\n", __func__, tvps->num); | ||
1555 | dprintk("%s() properties.props = %p\n", __func__, tvps->props); | ||
1556 | |||
1557 | /* Put an arbitrary limit on the number of messages that can | ||
1558 | * be sent at once */ | ||
1559 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) | ||
1560 | return -EINVAL; | ||
1561 | |||
1562 | tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); | ||
1563 | if (!tvp) { | ||
1564 | err = -ENOMEM; | ||
1565 | goto out; | ||
1566 | } | ||
1567 | |||
1568 | if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { | ||
1569 | err = -EFAULT; | ||
1570 | goto out; | ||
1571 | } | ||
1572 | |||
1573 | for (i = 0; i < tvps->num; i++) { | ||
1574 | err = dtv_property_process_set(fe, tvp + i, file); | ||
1575 | if (err < 0) | ||
1576 | goto out; | ||
1577 | (tvp + i)->result = err; | ||
1578 | } | ||
1579 | |||
1580 | if (c->state == DTV_TUNE) | ||
1581 | dprintk("%s() Property cache is full, tuning\n", __func__); | ||
1582 | |||
1583 | } else | ||
1584 | if(cmd == FE_GET_PROPERTY) { | ||
1585 | |||
1586 | tvps = (struct dtv_properties __user *)parg; | ||
1587 | |||
1588 | dprintk("%s() properties.num = %d\n", __func__, tvps->num); | ||
1589 | dprintk("%s() properties.props = %p\n", __func__, tvps->props); | ||
1590 | |||
1591 | /* Put an arbitrary limit on the number of messages that can | ||
1592 | * be sent at once */ | ||
1593 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) | ||
1594 | return -EINVAL; | ||
1595 | |||
1596 | tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); | ||
1597 | if (!tvp) { | ||
1598 | err = -ENOMEM; | ||
1599 | goto out; | ||
1600 | } | ||
1601 | |||
1602 | if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { | ||
1603 | err = -EFAULT; | ||
1604 | goto out; | ||
1605 | } | ||
1606 | |||
1607 | for (i = 0; i < tvps->num; i++) { | ||
1608 | err = dtv_property_process_get(fe, tvp + i, file); | ||
1609 | if (err < 0) | ||
1610 | goto out; | ||
1611 | (tvp + i)->result = err; | ||
1612 | } | ||
1613 | |||
1614 | if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { | ||
1615 | err = -EFAULT; | ||
1616 | goto out; | ||
1617 | } | ||
1618 | |||
1619 | } else | ||
1620 | err = -EOPNOTSUPP; | ||
1621 | |||
1622 | out: | ||
1623 | kfree(tvp); | ||
1624 | return err; | ||
1625 | } | ||
1626 | |||
1627 | static int dvb_frontend_ioctl_legacy(struct file *file, | ||
1628 | unsigned int cmd, void *parg) | ||
1629 | { | ||
1630 | struct dvb_device *dvbdev = file->private_data; | ||
1631 | struct dvb_frontend *fe = dvbdev->priv; | ||
1632 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1633 | int cb_err, err = -EOPNOTSUPP; | ||
1634 | |||
1635 | if (fe->dvb->fe_ioctl_override) { | ||
1636 | cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg, | ||
1637 | DVB_FE_IOCTL_PRE); | ||
1638 | if (cb_err < 0) | ||
1639 | return cb_err; | ||
1640 | if (cb_err > 0) | ||
1641 | return 0; | ||
1642 | /* fe_ioctl_override returning 0 allows | ||
1643 | * dvb-core to continue handling the ioctl */ | ||
1644 | } | ||
1645 | |||
1646 | switch (cmd) { | ||
1647 | case FE_GET_INFO: { | ||
1648 | struct dvb_frontend_info* info = parg; | ||
1649 | memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); | ||
1650 | dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max); | ||
1651 | |||
1652 | /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't | ||
1653 | * do it, it is done for it. */ | ||
1654 | info->caps |= FE_CAN_INVERSION_AUTO; | ||
1655 | err = 0; | ||
1656 | break; | ||
1657 | } | ||
1658 | |||
1659 | case FE_READ_STATUS: { | ||
1660 | fe_status_t* status = parg; | ||
1661 | |||
1662 | /* if retune was requested but hasn't occurred yet, prevent | ||
1663 | * that user get signal state from previous tuning */ | ||
1664 | if (fepriv->state == FESTATE_RETUNE || | ||
1665 | fepriv->state == FESTATE_ERROR) { | ||
1666 | err=0; | ||
1667 | *status = 0; | ||
1668 | break; | ||
1669 | } | ||
1670 | |||
1671 | if (fe->ops.read_status) | ||
1672 | err = fe->ops.read_status(fe, status); | ||
1673 | break; | ||
1674 | } | ||
1675 | case FE_READ_BER: | ||
1676 | if (fe->ops.read_ber) | ||
1677 | err = fe->ops.read_ber(fe, (__u32*) parg); | ||
1678 | break; | ||
1679 | |||
1680 | case FE_READ_SIGNAL_STRENGTH: | ||
1681 | if (fe->ops.read_signal_strength) | ||
1682 | err = fe->ops.read_signal_strength(fe, (__u16*) parg); | ||
1683 | break; | ||
1684 | |||
1685 | case FE_READ_SNR: | ||
1686 | if (fe->ops.read_snr) | ||
1687 | err = fe->ops.read_snr(fe, (__u16*) parg); | ||
1688 | break; | ||
1689 | |||
1690 | case FE_READ_UNCORRECTED_BLOCKS: | ||
1691 | if (fe->ops.read_ucblocks) | ||
1692 | err = fe->ops.read_ucblocks(fe, (__u32*) parg); | ||
1693 | break; | ||
1694 | |||
1695 | |||
1696 | case FE_DISEQC_RESET_OVERLOAD: | ||
1697 | if (fe->ops.diseqc_reset_overload) { | ||
1698 | err = fe->ops.diseqc_reset_overload(fe); | ||
1699 | fepriv->state = FESTATE_DISEQC; | ||
1700 | fepriv->status = 0; | ||
1701 | } | ||
1702 | break; | ||
1703 | |||
1704 | case FE_DISEQC_SEND_MASTER_CMD: | ||
1705 | if (fe->ops.diseqc_send_master_cmd) { | ||
1706 | err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg); | ||
1707 | fepriv->state = FESTATE_DISEQC; | ||
1708 | fepriv->status = 0; | ||
1709 | } | ||
1710 | break; | ||
1711 | |||
1712 | case FE_DISEQC_SEND_BURST: | ||
1713 | if (fe->ops.diseqc_send_burst) { | ||
1714 | err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg); | ||
1715 | fepriv->state = FESTATE_DISEQC; | ||
1716 | fepriv->status = 0; | ||
1717 | } | ||
1718 | break; | ||
1719 | |||
1720 | case FE_SET_TONE: | ||
1721 | if (fe->ops.set_tone) { | ||
1722 | err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg); | ||
1723 | fepriv->tone = (fe_sec_tone_mode_t) parg; | ||
1724 | fepriv->state = FESTATE_DISEQC; | ||
1725 | fepriv->status = 0; | ||
1726 | } | ||
1727 | break; | ||
1728 | |||
1729 | case FE_SET_VOLTAGE: | ||
1730 | if (fe->ops.set_voltage) { | ||
1731 | err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg); | ||
1732 | fepriv->voltage = (fe_sec_voltage_t) parg; | ||
1733 | fepriv->state = FESTATE_DISEQC; | ||
1734 | fepriv->status = 0; | ||
1735 | } | ||
1736 | break; | ||
1737 | |||
1738 | case FE_DISHNETWORK_SEND_LEGACY_CMD: | ||
1739 | if (fe->ops.dishnetwork_send_legacy_command) { | ||
1740 | err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg); | ||
1741 | fepriv->state = FESTATE_DISEQC; | ||
1742 | fepriv->status = 0; | ||
1743 | } else if (fe->ops.set_voltage) { | ||
1744 | /* | ||
1745 | * NOTE: This is a fallback condition. Some frontends | ||
1746 | * (stv0299 for instance) take longer than 8msec to | ||
1747 | * respond to a set_voltage command. Those switches | ||
1748 | * need custom routines to switch properly. For all | ||
1749 | * other frontends, the following should work ok. | ||
1750 | * Dish network legacy switches (as used by Dish500) | ||
1751 | * are controlled by sending 9-bit command words | ||
1752 | * spaced 8msec apart. | ||
1753 | * the actual command word is switch/port dependent | ||
1754 | * so it is up to the userspace application to send | ||
1755 | * the right command. | ||
1756 | * The command must always start with a '0' after | ||
1757 | * initialization, so parg is 8 bits and does not | ||
1758 | * include the initialization or start bit | ||
1759 | */ | ||
1760 | unsigned long swcmd = ((unsigned long) parg) << 1; | ||
1761 | struct timeval nexttime; | ||
1762 | struct timeval tv[10]; | ||
1763 | int i; | ||
1764 | u8 last = 1; | ||
1765 | if (dvb_frontend_debug) | ||
1766 | printk("%s switch command: 0x%04lx\n", __func__, swcmd); | ||
1767 | do_gettimeofday(&nexttime); | ||
1768 | if (dvb_frontend_debug) | ||
1769 | memcpy(&tv[0], &nexttime, sizeof(struct timeval)); | ||
1770 | /* before sending a command, initialize by sending | ||
1771 | * a 32ms 18V to the switch | ||
1772 | */ | ||
1773 | fe->ops.set_voltage(fe, SEC_VOLTAGE_18); | ||
1774 | dvb_frontend_sleep_until(&nexttime, 32000); | ||
1775 | |||
1776 | for (i = 0; i < 9; i++) { | ||
1777 | if (dvb_frontend_debug) | ||
1778 | do_gettimeofday(&tv[i + 1]); | ||
1779 | if ((swcmd & 0x01) != last) { | ||
1780 | /* set voltage to (last ? 13V : 18V) */ | ||
1781 | fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); | ||
1782 | last = (last) ? 0 : 1; | ||
1783 | } | ||
1784 | swcmd = swcmd >> 1; | ||
1785 | if (i != 8) | ||
1786 | dvb_frontend_sleep_until(&nexttime, 8000); | ||
1787 | } | ||
1788 | if (dvb_frontend_debug) { | ||
1789 | printk("%s(%d): switch delay (should be 32k followed by all 8k\n", | ||
1790 | __func__, fe->dvb->num); | ||
1791 | for (i = 1; i < 10; i++) | ||
1792 | printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i])); | ||
1793 | } | ||
1794 | err = 0; | ||
1795 | fepriv->state = FESTATE_DISEQC; | ||
1796 | fepriv->status = 0; | ||
1797 | } | ||
1798 | break; | ||
1799 | |||
1800 | case FE_DISEQC_RECV_SLAVE_REPLY: | ||
1801 | if (fe->ops.diseqc_recv_slave_reply) | ||
1802 | err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg); | ||
1803 | break; | ||
1804 | |||
1805 | case FE_ENABLE_HIGH_LNB_VOLTAGE: | ||
1806 | if (fe->ops.enable_high_lnb_voltage) | ||
1807 | err = fe->ops.enable_high_lnb_voltage(fe, (long) parg); | ||
1808 | break; | ||
1809 | |||
1810 | case FE_SET_FRONTEND: { | ||
1811 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
1812 | struct dvb_frontend_tune_settings fetunesettings; | ||
1813 | |||
1814 | if (c->state == DTV_TUNE) { | ||
1815 | if (dvb_frontend_check_parameters(fe, &fepriv->parameters_in) < 0) { | ||
1816 | err = -EINVAL; | ||
1817 | break; | ||
1818 | } | ||
1819 | } else { | ||
1820 | if (dvb_frontend_check_parameters(fe, parg) < 0) { | ||
1821 | err = -EINVAL; | ||
1822 | break; | ||
1823 | } | ||
1824 | |||
1825 | memcpy (&fepriv->parameters_in, parg, | ||
1826 | sizeof (struct dvb_frontend_parameters)); | ||
1827 | dtv_property_cache_sync(fe, c, &fepriv->parameters_in); | ||
1828 | } | ||
1829 | |||
1830 | memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); | ||
1831 | memcpy(&fetunesettings.parameters, parg, | ||
1832 | sizeof (struct dvb_frontend_parameters)); | ||
1833 | |||
1834 | /* force auto frequency inversion if requested */ | ||
1835 | if (dvb_force_auto_inversion) { | ||
1836 | fepriv->parameters_in.inversion = INVERSION_AUTO; | ||
1837 | fetunesettings.parameters.inversion = INVERSION_AUTO; | ||
1838 | } | ||
1839 | if (fe->ops.info.type == FE_OFDM) { | ||
1840 | /* without hierarchical coding code_rate_LP is irrelevant, | ||
1841 | * so we tolerate the otherwise invalid FEC_NONE setting */ | ||
1842 | if (fepriv->parameters_in.u.ofdm.hierarchy_information == HIERARCHY_NONE && | ||
1843 | fepriv->parameters_in.u.ofdm.code_rate_LP == FEC_NONE) | ||
1844 | fepriv->parameters_in.u.ofdm.code_rate_LP = FEC_AUTO; | ||
1845 | } | ||
1846 | |||
1847 | /* get frontend-specific tuning settings */ | ||
1848 | if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) { | ||
1849 | fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000; | ||
1850 | fepriv->max_drift = fetunesettings.max_drift; | ||
1851 | fepriv->step_size = fetunesettings.step_size; | ||
1852 | } else { | ||
1853 | /* default values */ | ||
1854 | switch(fe->ops.info.type) { | ||
1855 | case FE_QPSK: | ||
1856 | fepriv->min_delay = HZ/20; | ||
1857 | fepriv->step_size = fepriv->parameters_in.u.qpsk.symbol_rate / 16000; | ||
1858 | fepriv->max_drift = fepriv->parameters_in.u.qpsk.symbol_rate / 2000; | ||
1859 | break; | ||
1860 | |||
1861 | case FE_QAM: | ||
1862 | fepriv->min_delay = HZ/20; | ||
1863 | fepriv->step_size = 0; /* no zigzag */ | ||
1864 | fepriv->max_drift = 0; | ||
1865 | break; | ||
1866 | |||
1867 | case FE_OFDM: | ||
1868 | fepriv->min_delay = HZ/20; | ||
1869 | fepriv->step_size = fe->ops.info.frequency_stepsize * 2; | ||
1870 | fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; | ||
1871 | break; | ||
1872 | case FE_ATSC: | ||
1873 | fepriv->min_delay = HZ/20; | ||
1874 | fepriv->step_size = 0; | ||
1875 | fepriv->max_drift = 0; | ||
1876 | break; | ||
1877 | } | ||
1878 | } | ||
1879 | if (dvb_override_tune_delay > 0) | ||
1880 | fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000; | ||
1881 | |||
1882 | fepriv->state = FESTATE_RETUNE; | ||
1883 | |||
1884 | /* Request the search algorithm to search */ | ||
1885 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; | ||
1886 | |||
1887 | dvb_frontend_wakeup(fe); | ||
1888 | dvb_frontend_add_event(fe, 0); | ||
1889 | fepriv->status = 0; | ||
1890 | err = 0; | ||
1891 | break; | ||
1892 | } | ||
1893 | |||
1894 | case FE_GET_EVENT: | ||
1895 | err = dvb_frontend_get_event (fe, parg, file->f_flags); | ||
1896 | break; | ||
1897 | |||
1898 | case FE_GET_FRONTEND: | ||
1899 | if (fe->ops.get_frontend) { | ||
1900 | err = fe->ops.get_frontend(fe, &fepriv->parameters_out); | ||
1901 | memcpy(parg, &fepriv->parameters_out, sizeof(struct dvb_frontend_parameters)); | ||
1902 | } | ||
1903 | break; | ||
1904 | |||
1905 | case FE_SET_FRONTEND_TUNE_MODE: | ||
1906 | fepriv->tune_mode_flags = (unsigned long) parg; | ||
1907 | err = 0; | ||
1908 | break; | ||
1909 | }; | ||
1910 | |||
1911 | if (fe->dvb->fe_ioctl_override) { | ||
1912 | cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg, | ||
1913 | DVB_FE_IOCTL_POST); | ||
1914 | if (cb_err < 0) | ||
1915 | return cb_err; | ||
1916 | } | ||
1917 | |||
1918 | return err; | ||
1919 | } | ||
1920 | |||
1921 | |||
1922 | static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait) | ||
1923 | { | ||
1924 | struct dvb_device *dvbdev = file->private_data; | ||
1925 | struct dvb_frontend *fe = dvbdev->priv; | ||
1926 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1927 | |||
1928 | dprintk ("%s\n", __func__); | ||
1929 | |||
1930 | poll_wait (file, &fepriv->events.wait_queue, wait); | ||
1931 | |||
1932 | if (fepriv->events.eventw != fepriv->events.eventr) | ||
1933 | return (POLLIN | POLLRDNORM | POLLPRI); | ||
1934 | |||
1935 | return 0; | ||
1936 | } | ||
1937 | |||
1938 | static int dvb_frontend_open(struct inode *inode, struct file *file) | ||
1939 | { | ||
1940 | struct dvb_device *dvbdev = file->private_data; | ||
1941 | struct dvb_frontend *fe = dvbdev->priv; | ||
1942 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
1943 | struct dvb_adapter *adapter = fe->dvb; | ||
1944 | int ret; | ||
1945 | |||
1946 | dprintk ("%s\n", __func__); | ||
1947 | if (fepriv->exit == DVB_FE_DEVICE_REMOVED) | ||
1948 | return -ENODEV; | ||
1949 | |||
1950 | if (adapter->mfe_shared) { | ||
1951 | mutex_lock (&adapter->mfe_lock); | ||
1952 | |||
1953 | if (adapter->mfe_dvbdev == NULL) | ||
1954 | adapter->mfe_dvbdev = dvbdev; | ||
1955 | |||
1956 | else if (adapter->mfe_dvbdev != dvbdev) { | ||
1957 | struct dvb_device | ||
1958 | *mfedev = adapter->mfe_dvbdev; | ||
1959 | struct dvb_frontend | ||
1960 | *mfe = mfedev->priv; | ||
1961 | struct dvb_frontend_private | ||
1962 | *mfepriv = mfe->frontend_priv; | ||
1963 | int mferetry = (dvb_mfe_wait_time << 1); | ||
1964 | |||
1965 | mutex_unlock (&adapter->mfe_lock); | ||
1966 | while (mferetry-- && (mfedev->users != -1 || | ||
1967 | mfepriv->thread != NULL)) { | ||
1968 | if(msleep_interruptible(500)) { | ||
1969 | if(signal_pending(current)) | ||
1970 | return -EINTR; | ||
1971 | } | ||
1972 | } | ||
1973 | |||
1974 | mutex_lock (&adapter->mfe_lock); | ||
1975 | if(adapter->mfe_dvbdev != dvbdev) { | ||
1976 | mfedev = adapter->mfe_dvbdev; | ||
1977 | mfe = mfedev->priv; | ||
1978 | mfepriv = mfe->frontend_priv; | ||
1979 | if (mfedev->users != -1 || | ||
1980 | mfepriv->thread != NULL) { | ||
1981 | mutex_unlock (&adapter->mfe_lock); | ||
1982 | return -EBUSY; | ||
1983 | } | ||
1984 | adapter->mfe_dvbdev = dvbdev; | ||
1985 | } | ||
1986 | } | ||
1987 | } | ||
1988 | |||
1989 | if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) { | ||
1990 | if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0) | ||
1991 | goto err0; | ||
1992 | |||
1993 | /* If we took control of the bus, we need to force | ||
1994 | reinitialization. This is because many ts_bus_ctrl() | ||
1995 | functions strobe the RESET pin on the demod, and if the | ||
1996 | frontend thread already exists then the dvb_init() routine | ||
1997 | won't get called (which is what usually does initial | ||
1998 | register configuration). */ | ||
1999 | fepriv->reinitialise = 1; | ||
2000 | } | ||
2001 | |||
2002 | if ((ret = dvb_generic_open (inode, file)) < 0) | ||
2003 | goto err1; | ||
2004 | |||
2005 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
2006 | /* normal tune mode when opened R/W */ | ||
2007 | fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; | ||
2008 | fepriv->tone = -1; | ||
2009 | fepriv->voltage = -1; | ||
2010 | |||
2011 | ret = dvb_frontend_start (fe); | ||
2012 | if (ret) | ||
2013 | goto err2; | ||
2014 | |||
2015 | /* empty event queue */ | ||
2016 | fepriv->events.eventr = fepriv->events.eventw = 0; | ||
2017 | } | ||
2018 | |||
2019 | if (adapter->mfe_shared) | ||
2020 | mutex_unlock (&adapter->mfe_lock); | ||
2021 | return ret; | ||
2022 | |||
2023 | err2: | ||
2024 | dvb_generic_release(inode, file); | ||
2025 | err1: | ||
2026 | if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) | ||
2027 | fe->ops.ts_bus_ctrl(fe, 0); | ||
2028 | err0: | ||
2029 | if (adapter->mfe_shared) | ||
2030 | mutex_unlock (&adapter->mfe_lock); | ||
2031 | return ret; | ||
2032 | } | ||
2033 | |||
2034 | static int dvb_frontend_release(struct inode *inode, struct file *file) | ||
2035 | { | ||
2036 | struct dvb_device *dvbdev = file->private_data; | ||
2037 | struct dvb_frontend *fe = dvbdev->priv; | ||
2038 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2039 | int ret; | ||
2040 | |||
2041 | dprintk ("%s\n", __func__); | ||
2042 | |||
2043 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) | ||
2044 | fepriv->release_jiffies = jiffies; | ||
2045 | |||
2046 | ret = dvb_generic_release (inode, file); | ||
2047 | |||
2048 | if (dvbdev->users == -1) { | ||
2049 | if (fepriv->exit != DVB_FE_NO_EXIT) { | ||
2050 | fops_put(file->f_op); | ||
2051 | file->f_op = NULL; | ||
2052 | wake_up(&dvbdev->wait_queue); | ||
2053 | } | ||
2054 | if (fe->ops.ts_bus_ctrl) | ||
2055 | fe->ops.ts_bus_ctrl(fe, 0); | ||
2056 | } | ||
2057 | |||
2058 | return ret; | ||
2059 | } | ||
2060 | |||
2061 | static const struct file_operations dvb_frontend_fops = { | ||
2062 | .owner = THIS_MODULE, | ||
2063 | .unlocked_ioctl = dvb_generic_ioctl, | ||
2064 | .poll = dvb_frontend_poll, | ||
2065 | .open = dvb_frontend_open, | ||
2066 | .release = dvb_frontend_release, | ||
2067 | .llseek = noop_llseek, | ||
2068 | }; | ||
2069 | |||
2070 | int dvb_register_frontend(struct dvb_adapter* dvb, | ||
2071 | struct dvb_frontend* fe) | ||
2072 | { | ||
2073 | struct dvb_frontend_private *fepriv; | ||
2074 | static const struct dvb_device dvbdev_template = { | ||
2075 | .users = ~0, | ||
2076 | .writers = 1, | ||
2077 | .readers = (~0)-1, | ||
2078 | .fops = &dvb_frontend_fops, | ||
2079 | .kernel_ioctl = dvb_frontend_ioctl | ||
2080 | }; | ||
2081 | |||
2082 | dprintk ("%s\n", __func__); | ||
2083 | |||
2084 | if (mutex_lock_interruptible(&frontend_mutex)) | ||
2085 | return -ERESTARTSYS; | ||
2086 | |||
2087 | fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL); | ||
2088 | if (fe->frontend_priv == NULL) { | ||
2089 | mutex_unlock(&frontend_mutex); | ||
2090 | return -ENOMEM; | ||
2091 | } | ||
2092 | fepriv = fe->frontend_priv; | ||
2093 | |||
2094 | sema_init(&fepriv->sem, 1); | ||
2095 | init_waitqueue_head (&fepriv->wait_queue); | ||
2096 | init_waitqueue_head (&fepriv->events.wait_queue); | ||
2097 | mutex_init(&fepriv->events.mtx); | ||
2098 | fe->dvb = dvb; | ||
2099 | fepriv->inversion = INVERSION_OFF; | ||
2100 | |||
2101 | printk ("DVB: registering adapter %i frontend %i (%s)...\n", | ||
2102 | fe->dvb->num, | ||
2103 | fe->id, | ||
2104 | fe->ops.info.name); | ||
2105 | |||
2106 | dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, | ||
2107 | fe, DVB_DEVICE_FRONTEND); | ||
2108 | |||
2109 | mutex_unlock(&frontend_mutex); | ||
2110 | return 0; | ||
2111 | } | ||
2112 | EXPORT_SYMBOL(dvb_register_frontend); | ||
2113 | |||
2114 | int dvb_unregister_frontend(struct dvb_frontend* fe) | ||
2115 | { | ||
2116 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
2117 | dprintk ("%s\n", __func__); | ||
2118 | |||
2119 | mutex_lock(&frontend_mutex); | ||
2120 | dvb_frontend_stop (fe); | ||
2121 | mutex_unlock(&frontend_mutex); | ||
2122 | |||
2123 | if (fepriv->dvbdev->users < -1) | ||
2124 | wait_event(fepriv->dvbdev->wait_queue, | ||
2125 | fepriv->dvbdev->users==-1); | ||
2126 | |||
2127 | mutex_lock(&frontend_mutex); | ||
2128 | dvb_unregister_device (fepriv->dvbdev); | ||
2129 | |||
2130 | /* fe is invalid now */ | ||
2131 | kfree(fepriv); | ||
2132 | mutex_unlock(&frontend_mutex); | ||
2133 | return 0; | ||
2134 | } | ||
2135 | EXPORT_SYMBOL(dvb_unregister_frontend); | ||
2136 | |||
2137 | #ifdef CONFIG_MEDIA_ATTACH | ||
2138 | void dvb_frontend_detach(struct dvb_frontend* fe) | ||
2139 | { | ||
2140 | void *ptr; | ||
2141 | |||
2142 | if (fe->ops.release_sec) { | ||
2143 | fe->ops.release_sec(fe); | ||
2144 | symbol_put_addr(fe->ops.release_sec); | ||
2145 | } | ||
2146 | if (fe->ops.tuner_ops.release) { | ||
2147 | fe->ops.tuner_ops.release(fe); | ||
2148 | symbol_put_addr(fe->ops.tuner_ops.release); | ||
2149 | } | ||
2150 | if (fe->ops.analog_ops.release) { | ||
2151 | fe->ops.analog_ops.release(fe); | ||
2152 | symbol_put_addr(fe->ops.analog_ops.release); | ||
2153 | } | ||
2154 | ptr = (void*)fe->ops.release; | ||
2155 | if (ptr) { | ||
2156 | fe->ops.release(fe); | ||
2157 | symbol_put_addr(ptr); | ||
2158 | } | ||
2159 | } | ||
2160 | #else | ||
2161 | void dvb_frontend_detach(struct dvb_frontend* fe) | ||
2162 | { | ||
2163 | if (fe->ops.release_sec) | ||
2164 | fe->ops.release_sec(fe); | ||
2165 | if (fe->ops.tuner_ops.release) | ||
2166 | fe->ops.tuner_ops.release(fe); | ||
2167 | if (fe->ops.analog_ops.release) | ||
2168 | fe->ops.analog_ops.release(fe); | ||
2169 | if (fe->ops.release) | ||
2170 | fe->ops.release(fe); | ||
2171 | } | ||
2172 | #endif | ||
2173 | 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 new file mode 100644 index 00000000000..5590eb6eb40 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h | |||
@@ -0,0 +1,392 @@ | |||
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 | struct dvb_frontend_tune_settings { | ||
46 | int min_delay_ms; | ||
47 | int step_size; | ||
48 | int max_drift; | ||
49 | struct dvb_frontend_parameters parameters; | ||
50 | }; | ||
51 | |||
52 | struct dvb_frontend; | ||
53 | |||
54 | struct dvb_tuner_info { | ||
55 | char name[128]; | ||
56 | |||
57 | u32 frequency_min; | ||
58 | u32 frequency_max; | ||
59 | u32 frequency_step; | ||
60 | |||
61 | u32 bandwidth_min; | ||
62 | u32 bandwidth_max; | ||
63 | u32 bandwidth_step; | ||
64 | }; | ||
65 | |||
66 | struct analog_parameters { | ||
67 | unsigned int frequency; | ||
68 | unsigned int mode; | ||
69 | unsigned int audmode; | ||
70 | u64 std; | ||
71 | }; | ||
72 | |||
73 | enum dvbfe_modcod { | ||
74 | DVBFE_MODCOD_DUMMY_PLFRAME = 0, | ||
75 | DVBFE_MODCOD_QPSK_1_4, | ||
76 | DVBFE_MODCOD_QPSK_1_3, | ||
77 | DVBFE_MODCOD_QPSK_2_5, | ||
78 | DVBFE_MODCOD_QPSK_1_2, | ||
79 | DVBFE_MODCOD_QPSK_3_5, | ||
80 | DVBFE_MODCOD_QPSK_2_3, | ||
81 | DVBFE_MODCOD_QPSK_3_4, | ||
82 | DVBFE_MODCOD_QPSK_4_5, | ||
83 | DVBFE_MODCOD_QPSK_5_6, | ||
84 | DVBFE_MODCOD_QPSK_8_9, | ||
85 | DVBFE_MODCOD_QPSK_9_10, | ||
86 | DVBFE_MODCOD_8PSK_3_5, | ||
87 | DVBFE_MODCOD_8PSK_2_3, | ||
88 | DVBFE_MODCOD_8PSK_3_4, | ||
89 | DVBFE_MODCOD_8PSK_5_6, | ||
90 | DVBFE_MODCOD_8PSK_8_9, | ||
91 | DVBFE_MODCOD_8PSK_9_10, | ||
92 | DVBFE_MODCOD_16APSK_2_3, | ||
93 | DVBFE_MODCOD_16APSK_3_4, | ||
94 | DVBFE_MODCOD_16APSK_4_5, | ||
95 | DVBFE_MODCOD_16APSK_5_6, | ||
96 | DVBFE_MODCOD_16APSK_8_9, | ||
97 | DVBFE_MODCOD_16APSK_9_10, | ||
98 | DVBFE_MODCOD_32APSK_3_4, | ||
99 | DVBFE_MODCOD_32APSK_4_5, | ||
100 | DVBFE_MODCOD_32APSK_5_6, | ||
101 | DVBFE_MODCOD_32APSK_8_9, | ||
102 | DVBFE_MODCOD_32APSK_9_10, | ||
103 | DVBFE_MODCOD_RESERVED_1, | ||
104 | DVBFE_MODCOD_BPSK_1_3, | ||
105 | DVBFE_MODCOD_BPSK_1_4, | ||
106 | DVBFE_MODCOD_RESERVED_2 | ||
107 | }; | ||
108 | |||
109 | enum tuner_param { | ||
110 | DVBFE_TUNER_FREQUENCY = (1 << 0), | ||
111 | DVBFE_TUNER_TUNERSTEP = (1 << 1), | ||
112 | DVBFE_TUNER_IFFREQ = (1 << 2), | ||
113 | DVBFE_TUNER_BANDWIDTH = (1 << 3), | ||
114 | DVBFE_TUNER_REFCLOCK = (1 << 4), | ||
115 | DVBFE_TUNER_IQSENSE = (1 << 5), | ||
116 | DVBFE_TUNER_DUMMY = (1 << 31) | ||
117 | }; | ||
118 | |||
119 | /* | ||
120 | * ALGO_HW: (Hardware Algorithm) | ||
121 | * ---------------------------------------------------------------- | ||
122 | * Devices that support this algorithm do everything in hardware | ||
123 | * and no software support is needed to handle them. | ||
124 | * Requesting these devices to LOCK is the only thing required, | ||
125 | * device is supposed to do everything in the hardware. | ||
126 | * | ||
127 | * ALGO_SW: (Software Algorithm) | ||
128 | * ---------------------------------------------------------------- | ||
129 | * These are dumb devices, that require software to do everything | ||
130 | * | ||
131 | * ALGO_CUSTOM: (Customizable Agorithm) | ||
132 | * ---------------------------------------------------------------- | ||
133 | * Devices having this algorithm can be customized to have specific | ||
134 | * algorithms in the frontend driver, rather than simply doing a | ||
135 | * software zig-zag. In this case the zigzag maybe hardware assisted | ||
136 | * or it maybe completely done in hardware. In all cases, usage of | ||
137 | * this algorithm, in conjunction with the search and track | ||
138 | * callbacks, utilizes the driver specific algorithm. | ||
139 | * | ||
140 | * ALGO_RECOVERY: (Recovery Algorithm) | ||
141 | * ---------------------------------------------------------------- | ||
142 | * These devices have AUTO recovery capabilities from LOCK failure | ||
143 | */ | ||
144 | enum dvbfe_algo { | ||
145 | DVBFE_ALGO_HW = (1 << 0), | ||
146 | DVBFE_ALGO_SW = (1 << 1), | ||
147 | DVBFE_ALGO_CUSTOM = (1 << 2), | ||
148 | DVBFE_ALGO_RECOVERY = (1 << 31) | ||
149 | }; | ||
150 | |||
151 | struct tuner_state { | ||
152 | u32 frequency; | ||
153 | u32 tunerstep; | ||
154 | u32 ifreq; | ||
155 | u32 bandwidth; | ||
156 | u32 iqsense; | ||
157 | u32 refclock; | ||
158 | }; | ||
159 | |||
160 | /* | ||
161 | * search callback possible return status | ||
162 | * | ||
163 | * DVBFE_ALGO_SEARCH_SUCCESS | ||
164 | * The frontend search algorithm completed and returned successfully | ||
165 | * | ||
166 | * DVBFE_ALGO_SEARCH_ASLEEP | ||
167 | * The frontend search algorithm is sleeping | ||
168 | * | ||
169 | * DVBFE_ALGO_SEARCH_FAILED | ||
170 | * The frontend search for a signal failed | ||
171 | * | ||
172 | * DVBFE_ALGO_SEARCH_INVALID | ||
173 | * The frontend search algorith was probably supplied with invalid | ||
174 | * parameters and the search is an invalid one | ||
175 | * | ||
176 | * DVBFE_ALGO_SEARCH_ERROR | ||
177 | * The frontend search algorithm failed due to some error | ||
178 | * | ||
179 | * DVBFE_ALGO_SEARCH_AGAIN | ||
180 | * The frontend search algorithm was requested to search again | ||
181 | */ | ||
182 | enum dvbfe_search { | ||
183 | DVBFE_ALGO_SEARCH_SUCCESS = (1 << 0), | ||
184 | DVBFE_ALGO_SEARCH_ASLEEP = (1 << 1), | ||
185 | DVBFE_ALGO_SEARCH_FAILED = (1 << 2), | ||
186 | DVBFE_ALGO_SEARCH_INVALID = (1 << 3), | ||
187 | DVBFE_ALGO_SEARCH_AGAIN = (1 << 4), | ||
188 | DVBFE_ALGO_SEARCH_ERROR = (1 << 31), | ||
189 | }; | ||
190 | |||
191 | |||
192 | struct dvb_tuner_ops { | ||
193 | |||
194 | struct dvb_tuner_info info; | ||
195 | |||
196 | int (*release)(struct dvb_frontend *fe); | ||
197 | int (*init)(struct dvb_frontend *fe); | ||
198 | int (*sleep)(struct dvb_frontend *fe); | ||
199 | |||
200 | /** This is for simple PLLs - set all parameters in one go. */ | ||
201 | int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p); | ||
202 | int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p); | ||
203 | |||
204 | /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */ | ||
205 | int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len); | ||
206 | |||
207 | /** This is to allow setting tuner-specific configs */ | ||
208 | int (*set_config)(struct dvb_frontend *fe, void *priv_cfg); | ||
209 | |||
210 | int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency); | ||
211 | int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth); | ||
212 | |||
213 | #define TUNER_STATUS_LOCKED 1 | ||
214 | #define TUNER_STATUS_STEREO 2 | ||
215 | int (*get_status)(struct dvb_frontend *fe, u32 *status); | ||
216 | int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength); | ||
217 | |||
218 | /** These are provided separately from set_params in order to facilitate silicon | ||
219 | * tuners which require sophisticated tuning loops, controlling each parameter separately. */ | ||
220 | int (*set_frequency)(struct dvb_frontend *fe, u32 frequency); | ||
221 | int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth); | ||
222 | |||
223 | /* | ||
224 | * These are provided separately from set_params in order to facilitate silicon | ||
225 | * tuners which require sophisticated tuning loops, controlling each parameter separately. | ||
226 | */ | ||
227 | int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state); | ||
228 | int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state); | ||
229 | }; | ||
230 | |||
231 | struct analog_demod_info { | ||
232 | char *name; | ||
233 | }; | ||
234 | |||
235 | struct analog_demod_ops { | ||
236 | |||
237 | struct analog_demod_info info; | ||
238 | |||
239 | void (*set_params)(struct dvb_frontend *fe, | ||
240 | struct analog_parameters *params); | ||
241 | int (*has_signal)(struct dvb_frontend *fe); | ||
242 | int (*get_afc)(struct dvb_frontend *fe); | ||
243 | void (*tuner_status)(struct dvb_frontend *fe); | ||
244 | void (*standby)(struct dvb_frontend *fe); | ||
245 | void (*release)(struct dvb_frontend *fe); | ||
246 | int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable); | ||
247 | |||
248 | /** This is to allow setting tuner-specific configuration */ | ||
249 | int (*set_config)(struct dvb_frontend *fe, void *priv_cfg); | ||
250 | }; | ||
251 | |||
252 | struct dvb_frontend_ops { | ||
253 | |||
254 | struct dvb_frontend_info info; | ||
255 | |||
256 | void (*release)(struct dvb_frontend* fe); | ||
257 | void (*release_sec)(struct dvb_frontend* fe); | ||
258 | |||
259 | int (*init)(struct dvb_frontend* fe); | ||
260 | int (*sleep)(struct dvb_frontend* fe); | ||
261 | |||
262 | int (*write)(struct dvb_frontend* fe, const u8 buf[], int len); | ||
263 | |||
264 | /* if this is set, it overrides the default swzigzag */ | ||
265 | int (*tune)(struct dvb_frontend* fe, | ||
266 | struct dvb_frontend_parameters* params, | ||
267 | unsigned int mode_flags, | ||
268 | unsigned int *delay, | ||
269 | fe_status_t *status); | ||
270 | /* get frontend tuning algorithm from the module */ | ||
271 | enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe); | ||
272 | |||
273 | /* these two are only used for the swzigzag code */ | ||
274 | int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); | ||
275 | int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); | ||
276 | |||
277 | int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); | ||
278 | |||
279 | int (*read_status)(struct dvb_frontend* fe, fe_status_t* status); | ||
280 | int (*read_ber)(struct dvb_frontend* fe, u32* ber); | ||
281 | int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength); | ||
282 | int (*read_snr)(struct dvb_frontend* fe, u16* snr); | ||
283 | int (*read_ucblocks)(struct dvb_frontend* fe, u32* ucblocks); | ||
284 | |||
285 | int (*diseqc_reset_overload)(struct dvb_frontend* fe); | ||
286 | int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd); | ||
287 | int (*diseqc_recv_slave_reply)(struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply); | ||
288 | int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd); | ||
289 | int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone); | ||
290 | int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); | ||
291 | int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg); | ||
292 | int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd); | ||
293 | int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable); | ||
294 | int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire); | ||
295 | |||
296 | /* These callbacks are for devices that implement their own | ||
297 | * tuning algorithms, rather than a simple swzigzag | ||
298 | */ | ||
299 | enum dvbfe_search (*search)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p); | ||
300 | int (*track)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p); | ||
301 | |||
302 | struct dvb_tuner_ops tuner_ops; | ||
303 | struct analog_demod_ops analog_ops; | ||
304 | |||
305 | int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); | ||
306 | int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); | ||
307 | }; | ||
308 | |||
309 | #define MAX_EVENT 8 | ||
310 | |||
311 | struct dvb_fe_events { | ||
312 | struct dvb_frontend_event events[MAX_EVENT]; | ||
313 | int eventw; | ||
314 | int eventr; | ||
315 | int overflow; | ||
316 | wait_queue_head_t wait_queue; | ||
317 | struct mutex mtx; | ||
318 | }; | ||
319 | |||
320 | struct dtv_frontend_properties { | ||
321 | |||
322 | /* Cache State */ | ||
323 | u32 state; | ||
324 | |||
325 | u32 frequency; | ||
326 | fe_modulation_t modulation; | ||
327 | |||
328 | fe_sec_voltage_t voltage; | ||
329 | fe_sec_tone_mode_t sectone; | ||
330 | fe_spectral_inversion_t inversion; | ||
331 | fe_code_rate_t fec_inner; | ||
332 | fe_transmit_mode_t transmission_mode; | ||
333 | u32 bandwidth_hz; /* 0 = AUTO */ | ||
334 | fe_guard_interval_t guard_interval; | ||
335 | fe_hierarchy_t hierarchy; | ||
336 | u32 symbol_rate; | ||
337 | fe_code_rate_t code_rate_HP; | ||
338 | fe_code_rate_t code_rate_LP; | ||
339 | |||
340 | fe_pilot_t pilot; | ||
341 | fe_rolloff_t rolloff; | ||
342 | |||
343 | fe_delivery_system_t delivery_system; | ||
344 | |||
345 | /* ISDB-T specifics */ | ||
346 | u8 isdbt_partial_reception; | ||
347 | u8 isdbt_sb_mode; | ||
348 | u8 isdbt_sb_subchannel; | ||
349 | u32 isdbt_sb_segment_idx; | ||
350 | u32 isdbt_sb_segment_count; | ||
351 | u8 isdbt_layer_enabled; | ||
352 | struct { | ||
353 | u8 segment_count; | ||
354 | fe_code_rate_t fec; | ||
355 | fe_modulation_t modulation; | ||
356 | u8 interleaving; | ||
357 | } layer[3]; | ||
358 | |||
359 | /* ISDB-T specifics */ | ||
360 | u32 isdbs_ts_id; | ||
361 | |||
362 | /* DVB-T2 specifics */ | ||
363 | u32 dvbt2_plp_id; | ||
364 | }; | ||
365 | |||
366 | struct dvb_frontend { | ||
367 | struct dvb_frontend_ops ops; | ||
368 | struct dvb_adapter *dvb; | ||
369 | void *demodulator_priv; | ||
370 | void *tuner_priv; | ||
371 | void *frontend_priv; | ||
372 | void *sec_priv; | ||
373 | void *analog_demod_priv; | ||
374 | struct dtv_frontend_properties dtv_property_cache; | ||
375 | #define DVB_FRONTEND_COMPONENT_TUNER 0 | ||
376 | int (*callback)(void *adapter_priv, int component, int cmd, int arg); | ||
377 | int id; | ||
378 | }; | ||
379 | |||
380 | extern int dvb_register_frontend(struct dvb_adapter *dvb, | ||
381 | struct dvb_frontend *fe); | ||
382 | |||
383 | extern int dvb_unregister_frontend(struct dvb_frontend *fe); | ||
384 | |||
385 | extern void dvb_frontend_detach(struct dvb_frontend *fe); | ||
386 | |||
387 | extern void dvb_frontend_reinitialise(struct dvb_frontend *fe); | ||
388 | |||
389 | extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec); | ||
390 | extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime); | ||
391 | |||
392 | #endif | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb/dvb-core/dvb_math.c new file mode 100644 index 00000000000..beb7c93aa6c --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_math.c | |||
@@ -0,0 +1,145 @@ | |||
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 new file mode 100644 index 00000000000..aecc867e940 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_math.h | |||
@@ -0,0 +1,58 @@ | |||
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 new file mode 100644 index 00000000000..51752a9ef7a --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_net.c | |||
@@ -0,0 +1,1518 @@ | |||
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_multicast_list = 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 | dvb_register_device (adap, &dvbnet->dvbdev, &dvbdev_net, | ||
1514 | dvbnet, DVB_DEVICE_NET); | ||
1515 | |||
1516 | return 0; | ||
1517 | } | ||
1518 | 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 new file mode 100644 index 00000000000..1e53acd50cf --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_net.h | |||
@@ -0,0 +1,66 @@ | |||
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 new file mode 100644 index 00000000000..a5712cd7c65 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c | |||
@@ -0,0 +1,299 @@ | |||
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 new file mode 100644 index 00000000000..41f04dae69b --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h | |||
@@ -0,0 +1,186 @@ | |||
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 new file mode 100644 index 00000000000..f7328777595 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvbdev.c | |||
@@ -0,0 +1,506 @@ | |||
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 | mutex_unlock(&dvbdev_register_lock); | ||
247 | return -EINVAL; | ||
248 | } | ||
249 | #else | ||
250 | minor = nums2minor(adap->num, type, id); | ||
251 | #endif | ||
252 | |||
253 | dvbdev->minor = minor; | ||
254 | dvb_minors[minor] = dvbdev; | ||
255 | up_write(&minor_rwsem); | ||
256 | |||
257 | mutex_unlock(&dvbdev_register_lock); | ||
258 | |||
259 | clsdev = device_create(dvb_class, adap->device, | ||
260 | MKDEV(DVB_MAJOR, minor), | ||
261 | dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id); | ||
262 | if (IS_ERR(clsdev)) { | ||
263 | printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n", | ||
264 | __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); | ||
265 | return PTR_ERR(clsdev); | ||
266 | } | ||
267 | |||
268 | dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", | ||
269 | adap->num, dnames[type], id, minor, minor); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | EXPORT_SYMBOL(dvb_register_device); | ||
274 | |||
275 | |||
276 | void dvb_unregister_device(struct dvb_device *dvbdev) | ||
277 | { | ||
278 | if (!dvbdev) | ||
279 | return; | ||
280 | |||
281 | down_write(&minor_rwsem); | ||
282 | dvb_minors[dvbdev->minor] = NULL; | ||
283 | up_write(&minor_rwsem); | ||
284 | |||
285 | device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); | ||
286 | |||
287 | list_del (&dvbdev->list_head); | ||
288 | kfree (dvbdev->fops); | ||
289 | kfree (dvbdev); | ||
290 | } | ||
291 | EXPORT_SYMBOL(dvb_unregister_device); | ||
292 | |||
293 | static int dvbdev_check_free_adapter_num(int num) | ||
294 | { | ||
295 | struct list_head *entry; | ||
296 | list_for_each(entry, &dvb_adapter_list) { | ||
297 | struct dvb_adapter *adap; | ||
298 | adap = list_entry(entry, struct dvb_adapter, list_head); | ||
299 | if (adap->num == num) | ||
300 | return 0; | ||
301 | } | ||
302 | return 1; | ||
303 | } | ||
304 | |||
305 | static int dvbdev_get_free_adapter_num (void) | ||
306 | { | ||
307 | int num = 0; | ||
308 | |||
309 | while (num < DVB_MAX_ADAPTERS) { | ||
310 | if (dvbdev_check_free_adapter_num(num)) | ||
311 | return num; | ||
312 | num++; | ||
313 | } | ||
314 | |||
315 | return -ENFILE; | ||
316 | } | ||
317 | |||
318 | |||
319 | int dvb_register_adapter(struct dvb_adapter *adap, const char *name, | ||
320 | struct module *module, struct device *device, | ||
321 | short *adapter_nums) | ||
322 | { | ||
323 | int i, num; | ||
324 | |||
325 | mutex_lock(&dvbdev_register_lock); | ||
326 | |||
327 | for (i = 0; i < DVB_MAX_ADAPTERS; ++i) { | ||
328 | num = adapter_nums[i]; | ||
329 | if (num >= 0 && num < DVB_MAX_ADAPTERS) { | ||
330 | /* use the one the driver asked for */ | ||
331 | if (dvbdev_check_free_adapter_num(num)) | ||
332 | break; | ||
333 | } else { | ||
334 | num = dvbdev_get_free_adapter_num(); | ||
335 | break; | ||
336 | } | ||
337 | num = -1; | ||
338 | } | ||
339 | |||
340 | if (num < 0) { | ||
341 | mutex_unlock(&dvbdev_register_lock); | ||
342 | return -ENFILE; | ||
343 | } | ||
344 | |||
345 | memset (adap, 0, sizeof(struct dvb_adapter)); | ||
346 | INIT_LIST_HEAD (&adap->device_list); | ||
347 | |||
348 | printk(KERN_INFO "DVB: registering new adapter (%s)\n", name); | ||
349 | |||
350 | adap->num = num; | ||
351 | adap->name = name; | ||
352 | adap->module = module; | ||
353 | adap->device = device; | ||
354 | adap->mfe_shared = 0; | ||
355 | adap->mfe_dvbdev = NULL; | ||
356 | mutex_init (&adap->mfe_lock); | ||
357 | |||
358 | list_add_tail (&adap->list_head, &dvb_adapter_list); | ||
359 | |||
360 | mutex_unlock(&dvbdev_register_lock); | ||
361 | |||
362 | return num; | ||
363 | } | ||
364 | EXPORT_SYMBOL(dvb_register_adapter); | ||
365 | |||
366 | |||
367 | int dvb_unregister_adapter(struct dvb_adapter *adap) | ||
368 | { | ||
369 | mutex_lock(&dvbdev_register_lock); | ||
370 | list_del (&adap->list_head); | ||
371 | mutex_unlock(&dvbdev_register_lock); | ||
372 | return 0; | ||
373 | } | ||
374 | EXPORT_SYMBOL(dvb_unregister_adapter); | ||
375 | |||
376 | /* if the miracle happens and "generic_usercopy()" is included into | ||
377 | the kernel, then this can vanish. please don't make the mistake and | ||
378 | define this as video_usercopy(). this will introduce a dependecy | ||
379 | to the v4l "videodev.o" module, which is unnecessary for some | ||
380 | cards (ie. the budget dvb-cards don't need the v4l module...) */ | ||
381 | int dvb_usercopy(struct file *file, | ||
382 | unsigned int cmd, unsigned long arg, | ||
383 | int (*func)(struct file *file, | ||
384 | unsigned int cmd, void *arg)) | ||
385 | { | ||
386 | char sbuf[128]; | ||
387 | void *mbuf = NULL; | ||
388 | void *parg = NULL; | ||
389 | int err = -EINVAL; | ||
390 | |||
391 | /* Copy arguments into temp kernel buffer */ | ||
392 | switch (_IOC_DIR(cmd)) { | ||
393 | case _IOC_NONE: | ||
394 | /* | ||
395 | * For this command, the pointer is actually an integer | ||
396 | * argument. | ||
397 | */ | ||
398 | parg = (void *) arg; | ||
399 | break; | ||
400 | case _IOC_READ: /* some v4l ioctls are marked wrong ... */ | ||
401 | case _IOC_WRITE: | ||
402 | case (_IOC_WRITE | _IOC_READ): | ||
403 | if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { | ||
404 | parg = sbuf; | ||
405 | } else { | ||
406 | /* too big to allocate from stack */ | ||
407 | mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); | ||
408 | if (NULL == mbuf) | ||
409 | return -ENOMEM; | ||
410 | parg = mbuf; | ||
411 | } | ||
412 | |||
413 | err = -EFAULT; | ||
414 | if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) | ||
415 | goto out; | ||
416 | break; | ||
417 | } | ||
418 | |||
419 | /* call driver */ | ||
420 | mutex_lock(&dvbdev_mutex); | ||
421 | if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) | ||
422 | err = -EINVAL; | ||
423 | mutex_unlock(&dvbdev_mutex); | ||
424 | |||
425 | if (err < 0) | ||
426 | goto out; | ||
427 | |||
428 | /* Copy results into user buffer */ | ||
429 | switch (_IOC_DIR(cmd)) | ||
430 | { | ||
431 | case _IOC_READ: | ||
432 | case (_IOC_WRITE | _IOC_READ): | ||
433 | if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) | ||
434 | err = -EFAULT; | ||
435 | break; | ||
436 | } | ||
437 | |||
438 | out: | ||
439 | kfree(mbuf); | ||
440 | return err; | ||
441 | } | ||
442 | |||
443 | static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
444 | { | ||
445 | struct dvb_device *dvbdev = dev_get_drvdata(dev); | ||
446 | |||
447 | add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num); | ||
448 | add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]); | ||
449 | add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id); | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | static char *dvb_devnode(struct device *dev, mode_t *mode) | ||
454 | { | ||
455 | struct dvb_device *dvbdev = dev_get_drvdata(dev); | ||
456 | |||
457 | return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d", | ||
458 | dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); | ||
459 | } | ||
460 | |||
461 | |||
462 | static int __init init_dvbdev(void) | ||
463 | { | ||
464 | int retval; | ||
465 | dev_t dev = MKDEV(DVB_MAJOR, 0); | ||
466 | |||
467 | if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) { | ||
468 | printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR); | ||
469 | return retval; | ||
470 | } | ||
471 | |||
472 | cdev_init(&dvb_device_cdev, &dvb_device_fops); | ||
473 | if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) { | ||
474 | printk(KERN_ERR "dvb-core: unable register character device\n"); | ||
475 | goto error; | ||
476 | } | ||
477 | |||
478 | dvb_class = class_create(THIS_MODULE, "dvb"); | ||
479 | if (IS_ERR(dvb_class)) { | ||
480 | retval = PTR_ERR(dvb_class); | ||
481 | goto error; | ||
482 | } | ||
483 | dvb_class->dev_uevent = dvb_uevent; | ||
484 | dvb_class->devnode = dvb_devnode; | ||
485 | return 0; | ||
486 | |||
487 | error: | ||
488 | cdev_del(&dvb_device_cdev); | ||
489 | unregister_chrdev_region(dev, MAX_DVB_MINORS); | ||
490 | return retval; | ||
491 | } | ||
492 | |||
493 | |||
494 | static void __exit exit_dvbdev(void) | ||
495 | { | ||
496 | class_destroy(dvb_class); | ||
497 | cdev_del(&dvb_device_cdev); | ||
498 | unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); | ||
499 | } | ||
500 | |||
501 | subsys_initcall(init_dvbdev); | ||
502 | module_exit(exit_dvbdev); | ||
503 | |||
504 | MODULE_DESCRIPTION("DVB Core Driver"); | ||
505 | MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler"); | ||
506 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h new file mode 100644 index 00000000000..fcc6ae98745 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvbdev.h | |||
@@ -0,0 +1,172 @@ | |||
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 | /* Allow the adapter/bridge driver to perform an action before and/or | ||
76 | * after the core handles an ioctl: | ||
77 | * | ||
78 | * DVB_FE_IOCTL_PRE indicates that the ioctl has not yet been handled. | ||
79 | * DVB_FE_IOCTL_POST indicates that the ioctl has been handled. | ||
80 | * | ||
81 | * When DVB_FE_IOCTL_PRE is passed to the callback as the stage arg: | ||
82 | * | ||
83 | * return 0 to allow dvb-core to handle the ioctl. | ||
84 | * return a positive int to prevent dvb-core from handling the ioctl, | ||
85 | * and exit without error. | ||
86 | * return a negative int to prevent dvb-core from handling the ioctl, | ||
87 | * and return that value as an error. | ||
88 | * | ||
89 | * When DVB_FE_IOCTL_POST is passed to the callback as the stage arg: | ||
90 | * | ||
91 | * return 0 to allow the dvb_frontend ioctl handler to exit normally. | ||
92 | * return a negative int to cause the dvb_frontend ioctl handler to | ||
93 | * return that value as an error. | ||
94 | */ | ||
95 | #define DVB_FE_IOCTL_PRE 0 | ||
96 | #define DVB_FE_IOCTL_POST 1 | ||
97 | int (*fe_ioctl_override)(struct dvb_frontend *fe, | ||
98 | unsigned int cmd, void *parg, | ||
99 | unsigned int stage); | ||
100 | }; | ||
101 | |||
102 | |||
103 | struct dvb_device { | ||
104 | struct list_head list_head; | ||
105 | const struct file_operations *fops; | ||
106 | struct dvb_adapter *adapter; | ||
107 | int type; | ||
108 | int minor; | ||
109 | u32 id; | ||
110 | |||
111 | /* in theory, 'users' can vanish now, | ||
112 | but I don't want to change too much now... */ | ||
113 | int readers; | ||
114 | int writers; | ||
115 | int users; | ||
116 | |||
117 | wait_queue_head_t wait_queue; | ||
118 | /* don't really need those !? -- FIXME: use video_usercopy */ | ||
119 | int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg); | ||
120 | |||
121 | void *priv; | ||
122 | }; | ||
123 | |||
124 | |||
125 | extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name, | ||
126 | struct module *module, struct device *device, | ||
127 | short *adapter_nums); | ||
128 | extern int dvb_unregister_adapter (struct dvb_adapter *adap); | ||
129 | |||
130 | extern int dvb_register_device (struct dvb_adapter *adap, | ||
131 | struct dvb_device **pdvbdev, | ||
132 | const struct dvb_device *template, | ||
133 | void *priv, | ||
134 | int type); | ||
135 | |||
136 | extern void dvb_unregister_device (struct dvb_device *dvbdev); | ||
137 | |||
138 | extern int dvb_generic_open (struct inode *inode, struct file *file); | ||
139 | extern int dvb_generic_release (struct inode *inode, struct file *file); | ||
140 | extern long dvb_generic_ioctl (struct file *file, | ||
141 | unsigned int cmd, unsigned long arg); | ||
142 | |||
143 | /* we don't mess with video_usercopy() any more, | ||
144 | we simply define out own dvb_usercopy(), which will hopefully become | ||
145 | generic_usercopy() someday... */ | ||
146 | |||
147 | extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, | ||
148 | int (*func)(struct file *file, unsigned int cmd, void *arg)); | ||
149 | |||
150 | /** generic DVB attach function. */ | ||
151 | #ifdef CONFIG_MEDIA_ATTACH | ||
152 | #define dvb_attach(FUNCTION, ARGS...) ({ \ | ||
153 | void *__r = NULL; \ | ||
154 | typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ | ||
155 | if (__a) { \ | ||
156 | __r = (void *) __a(ARGS); \ | ||
157 | if (__r == NULL) \ | ||
158 | symbol_put(FUNCTION); \ | ||
159 | } else { \ | ||
160 | printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \ | ||
161 | } \ | ||
162 | __r; \ | ||
163 | }) | ||
164 | |||
165 | #else | ||
166 | #define dvb_attach(FUNCTION, ARGS...) ({ \ | ||
167 | FUNCTION(ARGS); \ | ||
168 | }) | ||
169 | |||
170 | #endif | ||
171 | |||
172 | #endif /* #ifndef _DVBDEV_H_ */ | ||