dtv_demux.c revision 1.6 1 1.6 jmcneill /* $NetBSD: dtv_demux.c,v 1.6 2014/08/09 13:34:10 jmcneill Exp $ */
2 1.1 jmcneill
3 1.1 jmcneill /*-
4 1.1 jmcneill * Copyright (c) 2011 Jared D. McNeill <jmcneill (at) invisible.ca>
5 1.1 jmcneill * All rights reserved.
6 1.1 jmcneill *
7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without
8 1.1 jmcneill * modification, are permitted provided that the following conditions
9 1.1 jmcneill * are met:
10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright
11 1.1 jmcneill * notice, this list of conditions and the following disclaimer.
12 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the
14 1.1 jmcneill * documentation and/or other materials provided with the distribution.
15 1.1 jmcneill * 3. All advertising materials mentioning features or use of this software
16 1.1 jmcneill * must display the following acknowledgement:
17 1.1 jmcneill * This product includes software developed by Jared D. McNeill.
18 1.1 jmcneill * 4. Neither the name of The NetBSD Foundation nor the names of its
19 1.1 jmcneill * contributors may be used to endorse or promote products derived
20 1.1 jmcneill * from this software without specific prior written permission.
21 1.1 jmcneill *
22 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 1.1 jmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 1.1 jmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 1.1 jmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 1.1 jmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 1.1 jmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 1.1 jmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 1.1 jmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 1.1 jmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 1.1 jmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 1.1 jmcneill * POSSIBILITY OF SUCH DAMAGE.
33 1.1 jmcneill */
34 1.1 jmcneill
35 1.4 jmcneill /*
36 1.4 jmcneill * This file contains support for the /dev/dvb/adapter<n>/demux0 device.
37 1.4 jmcneill *
38 1.4 jmcneill * The demux device is implemented as a cloning device. Each instance can
39 1.4 jmcneill * be in one of three modes: unconfigured (NONE), section filter (SECTION),
40 1.4 jmcneill * or PID filter (PES).
41 1.4 jmcneill *
42 1.4 jmcneill * An instance in section filter mode extracts PSI sections based on a
43 1.4 jmcneill * filter configured by the DMX_SET_FILTER ioctl. When an entire section is
44 1.4 jmcneill * received, it is made available to userspace via read method. Data is fed
45 1.4 jmcneill * into the section filter using the dtv_demux_write function.
46 1.4 jmcneill *
47 1.4 jmcneill * An instance in PID filter mode extracts TS packets that match the
48 1.4 jmcneill * specified PID filter configured by the DMX_SET_PES_FILTER, DMX_ADD_PID,
49 1.4 jmcneill * and DMX_REMOVE_PID ioctls. As this driver only implements the
50 1.4 jmcneill * DMX_OUT_TS_TAP output, these TS packets are made available to userspace
51 1.4 jmcneill * by calling read on the /dev/dvb/adapter<n>/dvr0 device.
52 1.4 jmcneill */
53 1.4 jmcneill
54 1.1 jmcneill #include <sys/cdefs.h>
55 1.6 jmcneill __KERNEL_RCSID(0, "$NetBSD: dtv_demux.c,v 1.6 2014/08/09 13:34:10 jmcneill Exp $");
56 1.1 jmcneill
57 1.1 jmcneill #include <sys/param.h>
58 1.1 jmcneill #include <sys/types.h>
59 1.1 jmcneill #include <sys/conf.h>
60 1.1 jmcneill #include <sys/kmem.h>
61 1.1 jmcneill #include <sys/device.h>
62 1.1 jmcneill #include <sys/select.h>
63 1.1 jmcneill #include <sys/filedesc.h>
64 1.1 jmcneill #include <sys/file.h>
65 1.1 jmcneill #include <sys/poll.h>
66 1.1 jmcneill #include <sys/vnode.h>
67 1.1 jmcneill #include <sys/queue.h>
68 1.1 jmcneill
69 1.1 jmcneill #include <dev/dtv/dtvvar.h>
70 1.1 jmcneill
71 1.1 jmcneill static int dtv_demux_read(struct file *, off_t *, struct uio *,
72 1.1 jmcneill kauth_cred_t, int);
73 1.1 jmcneill static int dtv_demux_ioctl(struct file *, u_long, void *);
74 1.1 jmcneill static int dtv_demux_poll(struct file *, int);
75 1.1 jmcneill static int dtv_demux_close(struct file *);
76 1.1 jmcneill
77 1.1 jmcneill static const struct fileops dtv_demux_fileops = {
78 1.1 jmcneill .fo_read = dtv_demux_read,
79 1.1 jmcneill .fo_write = fbadop_write,
80 1.1 jmcneill .fo_ioctl = dtv_demux_ioctl,
81 1.1 jmcneill .fo_fcntl = fnullop_fcntl,
82 1.1 jmcneill .fo_poll = dtv_demux_poll,
83 1.1 jmcneill .fo_stat = fbadop_stat,
84 1.1 jmcneill .fo_close = dtv_demux_close,
85 1.1 jmcneill .fo_kqfilter = fnullop_kqfilter,
86 1.1 jmcneill .fo_restart = fnullop_restart,
87 1.1 jmcneill };
88 1.1 jmcneill
89 1.1 jmcneill static uint32_t crc_table[256] = {
90 1.1 jmcneill 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
91 1.1 jmcneill 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
92 1.1 jmcneill 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
93 1.1 jmcneill 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
94 1.1 jmcneill 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
95 1.1 jmcneill 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
96 1.1 jmcneill 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
97 1.1 jmcneill 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
98 1.1 jmcneill 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
99 1.1 jmcneill 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
100 1.1 jmcneill 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
101 1.1 jmcneill 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
102 1.1 jmcneill 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
103 1.1 jmcneill 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
104 1.1 jmcneill 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
105 1.1 jmcneill 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
106 1.1 jmcneill 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
107 1.1 jmcneill 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
108 1.1 jmcneill 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
109 1.1 jmcneill 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
110 1.1 jmcneill 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
111 1.1 jmcneill 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
112 1.1 jmcneill 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
113 1.1 jmcneill 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
114 1.1 jmcneill 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
115 1.1 jmcneill 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
116 1.1 jmcneill 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
117 1.1 jmcneill 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
118 1.1 jmcneill 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
119 1.1 jmcneill 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
120 1.1 jmcneill 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
121 1.1 jmcneill 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
122 1.1 jmcneill 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
123 1.1 jmcneill 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
124 1.1 jmcneill 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
125 1.1 jmcneill 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
126 1.1 jmcneill 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
127 1.1 jmcneill 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
128 1.1 jmcneill 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
129 1.1 jmcneill 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
130 1.1 jmcneill 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
131 1.1 jmcneill 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
132 1.1 jmcneill 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
133 1.1 jmcneill 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
134 1.1 jmcneill 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
135 1.1 jmcneill 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
136 1.1 jmcneill 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
137 1.1 jmcneill 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
138 1.1 jmcneill 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
139 1.1 jmcneill 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
140 1.1 jmcneill 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
141 1.1 jmcneill 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
142 1.1 jmcneill 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
143 1.1 jmcneill 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
144 1.1 jmcneill 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
145 1.1 jmcneill 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
146 1.1 jmcneill 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
147 1.1 jmcneill 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
148 1.1 jmcneill 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
149 1.1 jmcneill 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
150 1.1 jmcneill 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
151 1.1 jmcneill 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
152 1.1 jmcneill 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
153 1.1 jmcneill 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
154 1.1 jmcneill };
155 1.1 jmcneill
156 1.4 jmcneill /* ISO/IEC 13818-1 Annex A "CRC Decoder Model" */
157 1.1 jmcneill static uint32_t
158 1.1 jmcneill dtv_demux_crc32(uint8_t *buf, int len)
159 1.1 jmcneill {
160 1.1 jmcneill const uint32_t *crc_tab = crc_table;
161 1.1 jmcneill uint32_t CRC = 0xffffffff;
162 1.1 jmcneill int i;
163 1.1 jmcneill
164 1.1 jmcneill for (i = 0; i < len; i++)
165 1.1 jmcneill CRC = (CRC << 8) ^ crc_tab[((CRC >> 24) ^ *buf++) & 0xff];
166 1.1 jmcneill
167 1.1 jmcneill return CRC;
168 1.1 jmcneill }
169 1.1 jmcneill
170 1.4 jmcneill /*
171 1.4 jmcneill * Start running the demux.
172 1.4 jmcneill */
173 1.4 jmcneill static int
174 1.4 jmcneill dtv_demux_start(struct dtv_demux *demux)
175 1.4 jmcneill {
176 1.4 jmcneill struct dtv_softc *sc = demux->dd_sc;
177 1.4 jmcneill int error = 0;
178 1.4 jmcneill bool dostart = false;
179 1.4 jmcneill
180 1.4 jmcneill /*
181 1.4 jmcneill * If the demux is not running, mark it as running and update the
182 1.4 jmcneill * global demux run counter.
183 1.4 jmcneill */
184 1.4 jmcneill mutex_enter(&sc->sc_lock);
185 1.4 jmcneill KASSERT(sc->sc_demux_runcnt >= 0);
186 1.4 jmcneill if (demux->dd_running == false) {
187 1.4 jmcneill sc->sc_demux_runcnt++;
188 1.4 jmcneill demux->dd_running = true;
189 1.4 jmcneill /* If this is the first demux running, trigger device start */
190 1.4 jmcneill dostart = sc->sc_demux_runcnt == 1;
191 1.4 jmcneill }
192 1.4 jmcneill mutex_exit(&sc->sc_lock);
193 1.4 jmcneill
194 1.4 jmcneill if (dostart) {
195 1.4 jmcneill /* Setup receive buffers and trigger device start */
196 1.4 jmcneill error = dtv_buffer_setup(sc);
197 1.4 jmcneill if (error == 0)
198 1.4 jmcneill error = dtv_device_start_transfer(sc);
199 1.4 jmcneill }
200 1.4 jmcneill
201 1.4 jmcneill /*
202 1.4 jmcneill * If something went wrong, restore the run counter and mark this
203 1.4 jmcneill * demux instance as halted.
204 1.4 jmcneill */
205 1.4 jmcneill if (error) {
206 1.4 jmcneill mutex_enter(&sc->sc_lock);
207 1.4 jmcneill sc->sc_demux_runcnt--;
208 1.4 jmcneill demux->dd_running = false;
209 1.4 jmcneill mutex_exit(&sc->sc_lock);
210 1.4 jmcneill }
211 1.4 jmcneill
212 1.4 jmcneill return error;
213 1.4 jmcneill }
214 1.4 jmcneill
215 1.4 jmcneill /*
216 1.4 jmcneill * Stop running the demux.
217 1.4 jmcneill */
218 1.4 jmcneill static int
219 1.4 jmcneill dtv_demux_stop(struct dtv_demux *demux)
220 1.4 jmcneill {
221 1.4 jmcneill struct dtv_softc *sc = demux->dd_sc;
222 1.4 jmcneill int error = 0;
223 1.4 jmcneill bool dostop = false;
224 1.4 jmcneill
225 1.4 jmcneill /*
226 1.4 jmcneill * If the demux is running, mark it as halted and update the
227 1.4 jmcneill * global demux run counter.
228 1.4 jmcneill */
229 1.4 jmcneill mutex_enter(&sc->sc_lock);
230 1.4 jmcneill if (demux->dd_running == true) {
231 1.4 jmcneill KASSERT(sc->sc_demux_runcnt > 0);
232 1.4 jmcneill demux->dd_running = false;
233 1.4 jmcneill sc->sc_demux_runcnt--;
234 1.4 jmcneill /* If this was the last demux running, trigger device stop */
235 1.4 jmcneill dostop = sc->sc_demux_runcnt == 0;
236 1.4 jmcneill }
237 1.4 jmcneill mutex_exit(&sc->sc_lock);
238 1.4 jmcneill
239 1.4 jmcneill if (dostop) {
240 1.4 jmcneill /* Trigger device stop */
241 1.4 jmcneill error = dtv_device_stop_transfer(sc);
242 1.4 jmcneill }
243 1.4 jmcneill
244 1.4 jmcneill /*
245 1.4 jmcneill * If something went wrong, restore the run counter and mark this
246 1.4 jmcneill * demux instance as running.
247 1.4 jmcneill */
248 1.4 jmcneill if (error) {
249 1.4 jmcneill mutex_enter(&sc->sc_lock);
250 1.4 jmcneill sc->sc_demux_runcnt++;
251 1.4 jmcneill demux->dd_running = true;
252 1.4 jmcneill mutex_exit(&sc->sc_lock);
253 1.4 jmcneill }
254 1.4 jmcneill
255 1.4 jmcneill return error;
256 1.4 jmcneill }
257 1.4 jmcneill
258 1.4 jmcneill /*
259 1.4 jmcneill * Put the demux into PID filter mode and update the PID filter table.
260 1.4 jmcneill */
261 1.4 jmcneill static int
262 1.4 jmcneill dtv_demux_set_pidfilter(struct dtv_demux *demux, uint16_t pid, bool onoff)
263 1.4 jmcneill {
264 1.4 jmcneill struct dtv_softc *sc = demux->dd_sc;
265 1.4 jmcneill
266 1.4 jmcneill /*
267 1.4 jmcneill * TS PID is 13 bits; demux device uses special PID 0x2000 to mean
268 1.4 jmcneill * "all PIDs". Verify that the requested PID is in range.
269 1.4 jmcneill */
270 1.4 jmcneill if (pid > 0x2000)
271 1.4 jmcneill return EINVAL;
272 1.4 jmcneill
273 1.4 jmcneill /* Set demux mode */
274 1.4 jmcneill demux->dd_mode = DTV_DEMUX_MODE_PES;
275 1.4 jmcneill /*
276 1.4 jmcneill * If requesting "all PIDs", set the on/off flag for all PIDs in
277 1.4 jmcneill * the PID map, otherwise set the on/off flag for the requested
278 1.4 jmcneill * PID.
279 1.4 jmcneill */
280 1.4 jmcneill if (pid == 0x2000) {
281 1.4 jmcneill memset(sc->sc_ts.ts_pidfilter, onoff,
282 1.4 jmcneill sizeof(sc->sc_ts.ts_pidfilter));
283 1.4 jmcneill } else {
284 1.4 jmcneill sc->sc_ts.ts_pidfilter[pid] = onoff;
285 1.4 jmcneill }
286 1.4 jmcneill
287 1.4 jmcneill return 0;
288 1.4 jmcneill }
289 1.4 jmcneill
290 1.4 jmcneill /*
291 1.4 jmcneill * Open a new instance of the demux cloning device.
292 1.4 jmcneill */
293 1.1 jmcneill int
294 1.1 jmcneill dtv_demux_open(struct dtv_softc *sc, int flags, int mode, lwp_t *l)
295 1.1 jmcneill {
296 1.1 jmcneill struct file *fp;
297 1.1 jmcneill struct dtv_demux *demux;
298 1.1 jmcneill int error, fd;
299 1.1 jmcneill
300 1.4 jmcneill /* Allocate private storage */
301 1.1 jmcneill demux = kmem_zalloc(sizeof(*demux), KM_SLEEP);
302 1.1 jmcneill if (demux == NULL)
303 1.1 jmcneill return ENOMEM;
304 1.1 jmcneill demux->dd_sc = sc;
305 1.4 jmcneill /* Default operation mode is unconfigured */
306 1.1 jmcneill demux->dd_mode = DTV_DEMUX_MODE_NONE;
307 1.1 jmcneill selinit(&demux->dd_sel);
308 1.6 jmcneill mutex_init(&demux->dd_lock, MUTEX_DEFAULT, IPL_SCHED);
309 1.1 jmcneill cv_init(&demux->dd_section_cv, "dtvsec");
310 1.1 jmcneill
311 1.1 jmcneill error = fd_allocfile(&fp, &fd);
312 1.1 jmcneill if (error) {
313 1.1 jmcneill kmem_free(demux, sizeof(*demux));
314 1.1 jmcneill return error;
315 1.1 jmcneill }
316 1.1 jmcneill
317 1.4 jmcneill /* Add the demux to the list of demux instances */
318 1.1 jmcneill mutex_enter(&sc->sc_demux_lock);
319 1.1 jmcneill TAILQ_INSERT_TAIL(&sc->sc_demux_list, demux, dd_entries);
320 1.1 jmcneill mutex_exit(&sc->sc_demux_lock);
321 1.1 jmcneill
322 1.1 jmcneill return fd_clone(fp, fd, flags, &dtv_demux_fileops, demux);
323 1.1 jmcneill }
324 1.1 jmcneill
325 1.4 jmcneill /*
326 1.4 jmcneill * Close the instance of the demux cloning device.
327 1.4 jmcneill */
328 1.1 jmcneill int
329 1.1 jmcneill dtv_demux_close(struct file *fp)
330 1.1 jmcneill {
331 1.1 jmcneill struct dtv_demux *demux = fp->f_data;
332 1.1 jmcneill struct dtv_softc *sc;
333 1.4 jmcneill int error;
334 1.1 jmcneill
335 1.1 jmcneill if (demux == NULL)
336 1.1 jmcneill return ENXIO;
337 1.1 jmcneill
338 1.1 jmcneill fp->f_data = NULL;
339 1.1 jmcneill
340 1.1 jmcneill sc = demux->dd_sc;
341 1.1 jmcneill
342 1.4 jmcneill /* If the demux is still running, stop it */
343 1.4 jmcneill if (demux->dd_running) {
344 1.4 jmcneill error = dtv_demux_stop(demux);
345 1.4 jmcneill if (error)
346 1.4 jmcneill return error;
347 1.4 jmcneill }
348 1.4 jmcneill
349 1.4 jmcneill /* Remove the demux from the list of demux instances */
350 1.1 jmcneill mutex_enter(&sc->sc_demux_lock);
351 1.1 jmcneill TAILQ_REMOVE(&sc->sc_demux_list, demux, dd_entries);
352 1.1 jmcneill mutex_exit(&sc->sc_demux_lock);
353 1.1 jmcneill
354 1.1 jmcneill mutex_destroy(&demux->dd_lock);
355 1.1 jmcneill cv_destroy(&demux->dd_section_cv);
356 1.1 jmcneill kmem_free(demux, sizeof(*demux));
357 1.1 jmcneill
358 1.4 jmcneill /* Update the global device open count */
359 1.4 jmcneill dtv_common_close(sc);
360 1.1 jmcneill
361 1.1 jmcneill return 0;
362 1.1 jmcneill }
363 1.1 jmcneill
364 1.4 jmcneill /*
365 1.4 jmcneill * Handle demux ioctl requests
366 1.4 jmcneill */
367 1.1 jmcneill static int
368 1.4 jmcneill dtv_demux_ioctl(struct file *fp, u_long cmd, void *data)
369 1.1 jmcneill {
370 1.4 jmcneill struct dtv_demux *demux = fp->f_data;
371 1.1 jmcneill struct dmx_pes_filter_params *pesfilt;
372 1.1 jmcneill struct dmx_sct_filter_params *sctfilt;
373 1.1 jmcneill uint16_t pid;
374 1.1 jmcneill int error;
375 1.1 jmcneill
376 1.1 jmcneill if (demux == NULL)
377 1.1 jmcneill return ENXIO;
378 1.1 jmcneill
379 1.1 jmcneill switch (cmd) {
380 1.1 jmcneill case DMX_START:
381 1.4 jmcneill return dtv_demux_start(demux);
382 1.1 jmcneill case DMX_STOP:
383 1.4 jmcneill return dtv_demux_stop(demux);
384 1.1 jmcneill case DMX_SET_BUFFER_SIZE:
385 1.4 jmcneill /*
386 1.4 jmcneill * The demux driver doesn't support configurable buffer sizes,
387 1.4 jmcneill * but software relies on this command succeeding.
388 1.4 jmcneill */
389 1.1 jmcneill return 0;
390 1.1 jmcneill case DMX_SET_FILTER:
391 1.1 jmcneill sctfilt = data;
392 1.1 jmcneill
393 1.4 jmcneill /* Verify that the requested PID is in range. */
394 1.1 jmcneill if (sctfilt->pid >= 0x2000)
395 1.1 jmcneill return EINVAL;
396 1.1 jmcneill
397 1.4 jmcneill /*
398 1.4 jmcneill * Update section filter parameters, reset read/write ptrs,
399 1.4 jmcneill * clear section count and overflow flag, and set the
400 1.4 jmcneill * demux instance mode to section filter.
401 1.4 jmcneill */
402 1.1 jmcneill demux->dd_secfilt.params = *sctfilt;
403 1.1 jmcneill demux->dd_secfilt.rp = demux->dd_secfilt.wp = 0;
404 1.1 jmcneill demux->dd_secfilt.nsections = 0;
405 1.1 jmcneill demux->dd_secfilt.overflow = false;
406 1.1 jmcneill demux->dd_mode = DTV_DEMUX_MODE_SECTION;
407 1.1 jmcneill
408 1.4 jmcneill /*
409 1.4 jmcneill * If the DMX_IMMEDIATE_START flag is present in the request,
410 1.4 jmcneill * start running the demux immediately (no need for a
411 1.4 jmcneill * subsequent DMX_START ioctl).
412 1.4 jmcneill */
413 1.1 jmcneill if (sctfilt->flags & DMX_IMMEDIATE_START) {
414 1.4 jmcneill error = dtv_demux_start(demux);
415 1.1 jmcneill if (error)
416 1.1 jmcneill return error;
417 1.1 jmcneill }
418 1.1 jmcneill
419 1.1 jmcneill return 0;
420 1.1 jmcneill case DMX_SET_PES_FILTER:
421 1.1 jmcneill pesfilt = data;
422 1.1 jmcneill
423 1.4 jmcneill /* The driver only supports input from the frontend */
424 1.1 jmcneill if (pesfilt->input != DMX_IN_FRONTEND)
425 1.1 jmcneill return EINVAL;
426 1.4 jmcneill /*
427 1.4 jmcneill * The driver only supports output to the TS TAP in PID
428 1.4 jmcneill * filter mode.
429 1.4 jmcneill */
430 1.1 jmcneill if (pesfilt->output != DMX_OUT_TS_TAP)
431 1.1 jmcneill return EINVAL;
432 1.1 jmcneill
433 1.4 jmcneill /* Update PID filter table */
434 1.4 jmcneill error = dtv_demux_set_pidfilter(demux, pesfilt->pid, true);
435 1.1 jmcneill if (error)
436 1.1 jmcneill return error;
437 1.1 jmcneill
438 1.4 jmcneill /*
439 1.4 jmcneill * If the DMX_IMMEDIATE_START flag is present in the request,
440 1.4 jmcneill * start running the demux immediately (no need for a
441 1.4 jmcneill * subsequent DMX_START ioctl).
442 1.4 jmcneill */
443 1.1 jmcneill if (pesfilt->flags & DMX_IMMEDIATE_START) {
444 1.4 jmcneill error = dtv_demux_start(demux);
445 1.1 jmcneill if (error)
446 1.1 jmcneill return error;
447 1.1 jmcneill }
448 1.1 jmcneill return 0;
449 1.1 jmcneill case DMX_ADD_PID:
450 1.1 jmcneill pid = *(uint16_t *)data;
451 1.4 jmcneill return dtv_demux_set_pidfilter(demux, pid, true);
452 1.1 jmcneill case DMX_REMOVE_PID:
453 1.1 jmcneill pid = *(uint16_t *)data;
454 1.4 jmcneill return dtv_demux_set_pidfilter(demux, pid, false);
455 1.1 jmcneill default:
456 1.1 jmcneill return EINVAL;
457 1.1 jmcneill }
458 1.1 jmcneill }
459 1.1 jmcneill
460 1.4 jmcneill /*
461 1.4 jmcneill * Test for I/O readiness
462 1.4 jmcneill */
463 1.1 jmcneill static int
464 1.1 jmcneill dtv_demux_poll(struct file *fp, int events)
465 1.1 jmcneill {
466 1.1 jmcneill struct dtv_demux *demux = fp->f_data;
467 1.1 jmcneill int revents = 0;
468 1.1 jmcneill
469 1.1 jmcneill if (demux == NULL)
470 1.1 jmcneill return POLLERR;
471 1.1 jmcneill
472 1.4 jmcneill /*
473 1.4 jmcneill * If the demux instance is in section filter mode, wait for an
474 1.4 jmcneill * entire section to become ready.
475 1.4 jmcneill */
476 1.1 jmcneill mutex_enter(&demux->dd_lock);
477 1.4 jmcneill if (demux->dd_mode == DTV_DEMUX_MODE_SECTION &&
478 1.4 jmcneill demux->dd_secfilt.nsections > 0) {
479 1.1 jmcneill revents |= POLLIN;
480 1.1 jmcneill } else {
481 1.1 jmcneill selrecord(curlwp, &demux->dd_sel);
482 1.1 jmcneill }
483 1.1 jmcneill mutex_exit(&demux->dd_lock);
484 1.1 jmcneill
485 1.1 jmcneill return revents;
486 1.1 jmcneill }
487 1.1 jmcneill
488 1.4 jmcneill /*
489 1.4 jmcneill * Read from the demux instance
490 1.4 jmcneill */
491 1.1 jmcneill static int
492 1.1 jmcneill dtv_demux_read(struct file *fp, off_t *offp, struct uio *uio,
493 1.1 jmcneill kauth_cred_t cred, int flags)
494 1.1 jmcneill {
495 1.1 jmcneill struct dtv_demux *demux = fp->f_data;
496 1.1 jmcneill struct dtv_ts_section sec;
497 1.1 jmcneill int error;
498 1.1 jmcneill
499 1.1 jmcneill if (demux == NULL)
500 1.1 jmcneill return ENXIO;
501 1.1 jmcneill
502 1.4 jmcneill /* Only support read if the instance is in section filter mode */
503 1.1 jmcneill if (demux->dd_mode != DTV_DEMUX_MODE_SECTION)
504 1.1 jmcneill return EIO;
505 1.1 jmcneill
506 1.4 jmcneill /* Wait for a complete PSI section */
507 1.1 jmcneill mutex_enter(&demux->dd_lock);
508 1.1 jmcneill while (demux->dd_secfilt.nsections == 0) {
509 1.1 jmcneill if (flags & IO_NDELAY) {
510 1.1 jmcneill mutex_exit(&demux->dd_lock);
511 1.4 jmcneill /* No data available */
512 1.1 jmcneill return EWOULDBLOCK;
513 1.1 jmcneill }
514 1.1 jmcneill error = cv_wait_sig(&demux->dd_section_cv, &demux->dd_lock);
515 1.1 jmcneill if (error) {
516 1.1 jmcneill mutex_exit(&demux->dd_lock);
517 1.1 jmcneill return error;
518 1.1 jmcneill }
519 1.1 jmcneill }
520 1.4 jmcneill /* Copy the completed PSI section */
521 1.1 jmcneill sec = demux->dd_secfilt.section[demux->dd_secfilt.rp];
522 1.4 jmcneill /* Update read pointer */
523 1.1 jmcneill demux->dd_secfilt.rp++;
524 1.1 jmcneill if (demux->dd_secfilt.rp >= __arraycount(demux->dd_secfilt.section))
525 1.1 jmcneill demux->dd_secfilt.rp = 0;
526 1.4 jmcneill /* Update section count */
527 1.1 jmcneill demux->dd_secfilt.nsections--;
528 1.1 jmcneill mutex_exit(&demux->dd_lock);
529 1.1 jmcneill
530 1.4 jmcneill /*
531 1.4 jmcneill * If the filter parameters specify the DMX_ONESHOT flag, stop
532 1.4 jmcneill * the demux after one PSI section is received.
533 1.4 jmcneill */
534 1.4 jmcneill if (demux->dd_secfilt.params.flags & DMX_ONESHOT)
535 1.4 jmcneill dtv_demux_stop(demux);
536 1.4 jmcneill
537 1.4 jmcneill /*
538 1.4 jmcneill * Copy the PSI section to userspace. If the receiving buffer is
539 1.4 jmcneill * too small, the rest of the payload will be discarded. Although
540 1.4 jmcneill * this behaviour differs from the Linux implementation, in practice
541 1.4 jmcneill * it should not be an issue as PSI sections have a max size of 4KB
542 1.4 jmcneill * (and callers will generally provide a big enough buffer).
543 1.4 jmcneill */
544 1.1 jmcneill return uiomove(sec.sec_buf, sec.sec_length, uio);
545 1.1 jmcneill }
546 1.1 jmcneill
547 1.4 jmcneill /*
548 1.4 jmcneill * Verify the CRC of a PSI section.
549 1.4 jmcneill */
550 1.1 jmcneill static bool
551 1.1 jmcneill dtv_demux_check_crc(struct dtv_demux *demux, struct dtv_ts_section *sec)
552 1.1 jmcneill {
553 1.1 jmcneill uint32_t crc, sec_crc;
554 1.1 jmcneill
555 1.4 jmcneill /*
556 1.4 jmcneill * If section_syntax_indicator is not set, the PSI section does
557 1.4 jmcneill * not include a CRC field.
558 1.4 jmcneill */
559 1.1 jmcneill if ((sec->sec_buf[1] & 0x80) == 0)
560 1.1 jmcneill return false;
561 1.1 jmcneill
562 1.1 jmcneill sec_crc = be32dec(&sec->sec_buf[sec->sec_length - 4]);
563 1.1 jmcneill crc = dtv_demux_crc32(&sec->sec_buf[0], sec->sec_length - 4);
564 1.1 jmcneill
565 1.1 jmcneill return crc == sec_crc;
566 1.1 jmcneill }
567 1.1 jmcneill
568 1.4 jmcneill /*
569 1.4 jmcneill * Process a single TS packet and extract PSI sections based on the
570 1.4 jmcneill * instance's section filter.
571 1.4 jmcneill */
572 1.4 jmcneill static int
573 1.4 jmcneill dtv_demux_process(struct dtv_demux *demux, const uint8_t *tspkt,
574 1.4 jmcneill size_t tspktlen)
575 1.1 jmcneill {
576 1.1 jmcneill struct dtv_ts_section *sec;
577 1.1 jmcneill dmx_filter_t *dmxfilt = &demux->dd_secfilt.params.filter;
578 1.1 jmcneill const uint8_t *p;
579 1.1 jmcneill uint16_t section_length;
580 1.1 jmcneill int brem, avail;
581 1.1 jmcneill
582 1.1 jmcneill KASSERT(tspktlen == TS_PKTLEN);
583 1.1 jmcneill
584 1.4 jmcneill /* If the demux instance is not running, ignore the packet */
585 1.4 jmcneill if (demux->dd_running == false)
586 1.4 jmcneill return 0;
587 1.4 jmcneill
588 1.4 jmcneill /*
589 1.4 jmcneill * If the demux instance is not in section filter mode, ignore
590 1.4 jmcneill * the packet
591 1.4 jmcneill */
592 1.1 jmcneill if (demux->dd_mode != DTV_DEMUX_MODE_SECTION)
593 1.1 jmcneill return 0;
594 1.4 jmcneill /*
595 1.4 jmcneill * If the packet's TS PID does not match the section filter PID,
596 1.4 jmcneill * ignore the packet
597 1.4 jmcneill */
598 1.1 jmcneill if (TS_PID(tspkt) != demux->dd_secfilt.params.pid)
599 1.1 jmcneill return 0;
600 1.4 jmcneill /*
601 1.4 jmcneill * If the TS packet does not contain a payload, ignore the packet
602 1.4 jmcneill */
603 1.1 jmcneill if (TS_HAS_PAYLOAD(tspkt) == 0)
604 1.1 jmcneill return 0;
605 1.1 jmcneill
606 1.1 jmcneill mutex_enter(&demux->dd_lock);
607 1.4 jmcneill
608 1.4 jmcneill /* If the section buffer is full, set the overflow flag and return */
609 1.1 jmcneill if (demux->dd_secfilt.nsections ==
610 1.1 jmcneill __arraycount(demux->dd_secfilt.section)) {
611 1.1 jmcneill demux->dd_secfilt.overflow = true;
612 1.1 jmcneill goto done;
613 1.1 jmcneill }
614 1.1 jmcneill sec = &demux->dd_secfilt.section[demux->dd_secfilt.wp];
615 1.1 jmcneill /* If we have no bytes in our buffer, wait for payload unit start */
616 1.1 jmcneill if (sec->sec_bytesused == 0 && TS_HAS_PUSI(tspkt) == 0)
617 1.1 jmcneill goto done;
618 1.1 jmcneill
619 1.1 jmcneill /* find payload start */
620 1.1 jmcneill p = tspkt + 4;
621 1.1 jmcneill if (TS_HAS_AF(tspkt)) {
622 1.1 jmcneill if (*p > 182) /* AF length with payload is between 0-182 */
623 1.1 jmcneill goto done;
624 1.1 jmcneill p += (1 + *p);
625 1.1 jmcneill }
626 1.1 jmcneill if (TS_HAS_PUSI(tspkt)) {
627 1.1 jmcneill p += (1 + *p);
628 1.1 jmcneill }
629 1.1 jmcneill
630 1.1 jmcneill brem = tspktlen - (p - tspkt);
631 1.1 jmcneill
632 1.1 jmcneill if (TS_HAS_PUSI(tspkt)) {
633 1.1 jmcneill if (brem < 16)
634 1.2 jmcneill goto done;
635 1.1 jmcneill
636 1.1 jmcneill section_length = ((p[1] & 0xf) << 8) | p[2];
637 1.1 jmcneill
638 1.1 jmcneill /* table_id filter */
639 1.1 jmcneill if (dmxfilt->mask[0]) {
640 1.1 jmcneill if ((p[0] & dmxfilt->mask[0]) != dmxfilt->filter[0])
641 1.1 jmcneill goto done;
642 1.1 jmcneill }
643 1.1 jmcneill /* table_id_ext filter */
644 1.1 jmcneill if (dmxfilt->mask[1] && dmxfilt->mask[2]) {
645 1.4 jmcneill /*
646 1.4 jmcneill * table_id_ext is only valid if
647 1.4 jmcneill * section_syntax_indicator is set
648 1.4 jmcneill */
649 1.1 jmcneill if (section_length < 2 || (p[1] & 0x80) == 0)
650 1.1 jmcneill goto done;
651 1.1 jmcneill if ((p[3] & dmxfilt->mask[1]) != dmxfilt->filter[1])
652 1.1 jmcneill goto done;
653 1.1 jmcneill if ((p[4] & dmxfilt->mask[2]) != dmxfilt->filter[2])
654 1.1 jmcneill goto done;
655 1.1 jmcneill }
656 1.1 jmcneill
657 1.1 jmcneill sec->sec_length = section_length + 3;
658 1.3 jmcneill
659 1.3 jmcneill /* maximum section length is 4KB */
660 1.3 jmcneill if (sec->sec_length > sizeof(sec->sec_buf)) {
661 1.3 jmcneill sec->sec_bytesused = sec->sec_length = 0;
662 1.3 jmcneill goto done;
663 1.3 jmcneill }
664 1.3 jmcneill
665 1.1 jmcneill }
666 1.1 jmcneill
667 1.1 jmcneill /* If we have bytes pending and we see payload unit start, flush buf */
668 1.1 jmcneill if (sec->sec_bytesused > 0 && TS_HAS_PUSI(tspkt))
669 1.1 jmcneill sec->sec_bytesused = sec->sec_length = 0;
670 1.1 jmcneill
671 1.4 jmcneill /* Copy data into section buffer */
672 1.1 jmcneill avail = min(sec->sec_length - sec->sec_bytesused, brem);
673 1.1 jmcneill if (avail < 0)
674 1.2 jmcneill goto done;
675 1.1 jmcneill memcpy(&sec->sec_buf[sec->sec_bytesused], p, avail);
676 1.1 jmcneill sec->sec_bytesused += avail;
677 1.1 jmcneill
678 1.4 jmcneill /*
679 1.4 jmcneill * If a complete section has been received, update section count
680 1.4 jmcneill * and notify readers.
681 1.4 jmcneill */
682 1.1 jmcneill if (sec->sec_bytesused == sec->sec_length) {
683 1.4 jmcneill /*
684 1.4 jmcneill * If the DMX_CHECK_CRC flag was present in the DMX_SET_FILTER
685 1.4 jmcneill * parameters, verify the PSI section checksum. If the
686 1.4 jmcneill * checksum is invalid, discard the entire corrupt section.
687 1.4 jmcneill */
688 1.1 jmcneill if ((demux->dd_secfilt.params.flags & DMX_CHECK_CRC) &&
689 1.1 jmcneill dtv_demux_check_crc(demux, sec) == false) {
690 1.4 jmcneill /* discard section */
691 1.1 jmcneill sec->sec_bytesused = sec->sec_length = 0;
692 1.1 jmcneill goto done;
693 1.1 jmcneill }
694 1.1 jmcneill
695 1.1 jmcneill demux->dd_secfilt.wp++;
696 1.1 jmcneill if (demux->dd_secfilt.wp >=
697 1.1 jmcneill __arraycount(demux->dd_secfilt.section))
698 1.1 jmcneill demux->dd_secfilt.wp = 0;
699 1.1 jmcneill demux->dd_secfilt.nsections++;
700 1.1 jmcneill cv_broadcast(&demux->dd_section_cv);
701 1.1 jmcneill selnotify(&demux->dd_sel, 0, 0);
702 1.1 jmcneill }
703 1.1 jmcneill
704 1.1 jmcneill done:
705 1.1 jmcneill mutex_exit(&demux->dd_lock);
706 1.1 jmcneill return 0;
707 1.1 jmcneill }
708 1.1 jmcneill
709 1.4 jmcneill /*
710 1.4 jmcneill * Submit TS data to all demux instances
711 1.4 jmcneill */
712 1.4 jmcneill void
713 1.4 jmcneill dtv_demux_write(struct dtv_softc *sc, const uint8_t *tspkt, size_t tspktlen)
714 1.4 jmcneill {
715 1.4 jmcneill struct dtv_demux *demux;
716 1.4 jmcneill
717 1.4 jmcneill mutex_enter(&sc->sc_demux_lock);
718 1.4 jmcneill TAILQ_FOREACH(demux, &sc->sc_demux_list, dd_entries) {
719 1.4 jmcneill dtv_demux_process(demux, tspkt, tspktlen);
720 1.4 jmcneill }
721 1.4 jmcneill mutex_exit(&sc->sc_demux_lock);
722 1.4 jmcneill }
723