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