1 /*
2  * libdvbdemux - a DVB demux library
3  *
4  * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
19  */
20 
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <sys/param.h>
25 #include <sys/ioctl.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <ctype.h>
29 #include <errno.h>
30 #include <linux/dvb/dmx.h>
31 #include "dvbdemux.h"
32 
33 
dvbdemux_open_demux(int adapter,int demuxdevice,int nonblocking)34 int dvbdemux_open_demux(int adapter, int demuxdevice, int nonblocking)
35 {
36 	char filename[PATH_MAX+1];
37 	int flags = O_RDWR;
38 	int fd;
39 
40 	if (nonblocking)
41 		flags |= O_NONBLOCK;
42 
43 	sprintf(filename, "/dev/dvb/adapter%i/demux%i", adapter, demuxdevice);
44 	if ((fd = open(filename, flags)) < 0) {
45 		// if that failed, try a flat /dev structure
46 		sprintf(filename, "/dev/dvb%i.demux%i", adapter, demuxdevice);
47 		fd = open(filename, flags);
48 	}
49 
50 	return fd;
51 }
52 
dvbdemux_open_dvr(int adapter,int dvrdevice,int readonly,int nonblocking)53 int dvbdemux_open_dvr(int adapter, int dvrdevice, int readonly, int nonblocking)
54 {
55 	char filename[PATH_MAX+1];
56 	int flags = O_RDWR;
57 	int fd;
58 
59 	if (readonly)
60 		flags = O_RDONLY;
61 	if (nonblocking)
62 		flags |= O_NONBLOCK;
63 
64 	sprintf(filename, "/dev/dvb/adapter%i/dvr%i", adapter, dvrdevice);
65 	if ((fd = open(filename, flags)) < 0) {
66 		// if that failed, try a flat /dev structure
67 		sprintf(filename, "/dev/dvb%i.dvr%i", adapter, dvrdevice);
68 		fd = open(filename, flags);
69 	}
70 
71 	return fd;
72 }
73 
dvbdemux_set_section_filter(int fd,int pid,uint8_t filter[18],uint8_t mask[18],int start,int checkcrc)74 int dvbdemux_set_section_filter(int fd, int pid,
75 				uint8_t filter[18], uint8_t mask[18],
76 				int start, int checkcrc)
77 {
78 	struct dmx_sct_filter_params sctfilter;
79 
80 	memset(&sctfilter, 0, sizeof(sctfilter));
81 	sctfilter.pid = pid;
82 	memcpy(sctfilter.filter.filter, filter, 1);
83 	memcpy(sctfilter.filter.filter+1, filter+3, 15);
84 	memcpy(sctfilter.filter.mask, mask, 1);
85 	memcpy(sctfilter.filter.mask+1, mask+3, 15);
86 	memset(sctfilter.filter.mode, 0, 16);
87 	if (start)
88 		sctfilter.flags |= DMX_IMMEDIATE_START;
89 	if (checkcrc)
90 		sctfilter.flags |= DMX_CHECK_CRC;
91 
92 	return ioctl(fd, DMX_SET_FILTER, &sctfilter);
93 }
94 
dvbdemux_set_pes_filter(int fd,int pid,int input,int output,int pestype,int start)95 int dvbdemux_set_pes_filter(int fd, int pid,
96 			    int input, int output,
97 			    int pestype,
98 			    int start)
99 {
100 	struct dmx_pes_filter_params filter;
101 
102 	memset(&filter, 0, sizeof(filter));
103 	filter.pid = pid;
104 
105 	switch(input) {
106 	case DVBDEMUX_INPUT_FRONTEND:
107 		filter.input = DMX_IN_FRONTEND;
108 		break;
109 
110 	case DVBDEMUX_INPUT_DVR:
111 		filter.input = DMX_IN_DVR;
112 		break;
113 
114 	default:
115 		return -EINVAL;
116 	}
117 
118 	switch(output) {
119 	case DVBDEMUX_OUTPUT_DECODER:
120 		filter.output = DMX_OUT_DECODER;
121 		break;
122 
123 	case DVBDEMUX_OUTPUT_DEMUX:
124 		filter.output = DMX_OUT_TAP;
125 		break;
126 
127 	case DVBDEMUX_OUTPUT_DVR:
128 		filter.output = DMX_OUT_TS_TAP;
129 		break;
130 
131 #ifdef DMX_OUT_TSDEMUX_TAP
132 	case DVBDEMUX_OUTPUT_TS_DEMUX:
133 		filter.output = DMX_OUT_TSDEMUX_TAP;
134 		break;
135 #endif
136 
137 	default:
138 		return -EINVAL;
139 	}
140 
141 	switch(pestype) {
142 	case DVBDEMUX_PESTYPE_AUDIO:
143 		filter.pes_type = DMX_PES_AUDIO;
144 		break;
145 
146 	case DVBDEMUX_PESTYPE_VIDEO:
147 		filter.pes_type = DMX_PES_VIDEO;
148 		break;
149 
150 	case DVBDEMUX_PESTYPE_TELETEXT:
151 		filter.pes_type = DMX_PES_TELETEXT;
152 		break;
153 
154 	case DVBDEMUX_PESTYPE_SUBTITLE:
155 		filter.pes_type = DMX_PES_SUBTITLE;
156 		break;
157 
158 	case DVBDEMUX_PESTYPE_PCR:
159 		filter.pes_type = DMX_PES_PCR;
160 		break;
161 
162 	default:
163 		return -EINVAL;
164 	}
165 
166 	if (start)
167 		filter.flags |= DMX_IMMEDIATE_START;
168 
169 	return ioctl(fd, DMX_SET_PES_FILTER, &filter);
170 }
171 
dvbdemux_set_pid_filter(int fd,int pid,int input,int output,int start)172 int dvbdemux_set_pid_filter(int fd, int pid,
173 			    int input, int output,
174 			    int start)
175 {
176 	struct dmx_pes_filter_params filter;
177 
178 	memset(&filter, 0, sizeof(filter));
179 	if (pid == -1)
180 		filter.pid = 0x2000;
181 	else
182 		filter.pid = pid;
183 
184 	switch(input) {
185 	case DVBDEMUX_INPUT_FRONTEND:
186 		filter.input = DMX_IN_FRONTEND;
187 		break;
188 
189 	case DVBDEMUX_INPUT_DVR:
190 		filter.input = DMX_IN_DVR;
191 		break;
192 
193 	default:
194 		return -EINVAL;
195 	}
196 
197 	switch(output) {
198 	case DVBDEMUX_OUTPUT_DECODER:
199 		filter.output = DMX_OUT_DECODER;
200 		break;
201 
202 	case DVBDEMUX_OUTPUT_DEMUX:
203 		filter.output = DMX_OUT_TAP;
204 		break;
205 
206 	case DVBDEMUX_OUTPUT_DVR:
207 		filter.output = DMX_OUT_TS_TAP;
208 		break;
209 
210 #ifdef DMX_OUT_TSDEMUX_TAP
211 	case DVBDEMUX_OUTPUT_TS_DEMUX:
212 		filter.output = DMX_OUT_TSDEMUX_TAP;
213 		break;
214 #endif
215 
216 	default:
217 		return -EINVAL;
218 	}
219 
220 	filter.pes_type = DMX_PES_OTHER;
221 
222 	if (start)
223 		filter.flags |= DMX_IMMEDIATE_START;
224 
225 	return ioctl(fd, DMX_SET_PES_FILTER, &filter);
226 }
227 
dvbdemux_start(int fd)228 int dvbdemux_start(int fd)
229 {
230 	return ioctl(fd, DMX_START);
231 }
232 
dvbdemux_stop(int fd)233 int dvbdemux_stop(int fd)
234 {
235 	return ioctl(fd, DMX_STOP);
236 }
237 
dvbdemux_get_stc(int fd,uint64_t * stc)238 int dvbdemux_get_stc(int fd, uint64_t *stc)
239 {
240 	struct dmx_stc _stc;
241 	int result;
242 
243 	memset(stc, 0, sizeof(_stc));
244 	if ((result = ioctl(fd, DMX_GET_STC, &_stc)) != 0) {
245 		return result;
246 	}
247 
248 	*stc = _stc.stc / _stc.base;
249 	return 0;
250 }
251 
dvbdemux_set_buffer(int fd,int bufsize)252 int dvbdemux_set_buffer(int fd, int bufsize)
253 {
254 	return ioctl(fd, DMX_SET_BUFFER_SIZE, bufsize);
255 }
256