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