• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU Lesser General Public License as published by
4  * the Free Software Foundation version 2.1 of the License.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  * GNU Lesser General Public License for more details.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this program; if not, write to the Free Software
13  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14  * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
15  *
16  * These routines were written as part of the dvb-apps, as:
17  *	util functions for various ?zap implementations
18  *
19  *	Copyright (C) 2001 Johannes Stezenbach (js@convergence.de)
20  *	for convergence integrated media
21  *
22  *	Originally licensed as GPLv2 or upper
23  *
24  * All subsequent changes are under GPLv2 only and are:
25  *	Copyright (c) 2011-2012 - Mauro Carvalho Chehab
26  *
27  */
28 
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <time.h>
33 #include <errno.h>
34 
35 #include <sys/ioctl.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <stdlib.h> /* free */
40 
41 #include <libdvbv5/dvb-demux.h>
42 #include <libdvbv5/dvb-dev.h>
43 
44 #define MAX_TIME		10	/* 1.0 seconds */
45 
46 #define xioctl(fh, request, arg...) ({					\
47 	int __rc;							\
48 	struct timespec __start, __end;					\
49 									\
50 	clock_gettime(CLOCK_MONOTONIC, &__start);			\
51 	do {								\
52 		__rc = ioctl(fh, request, ##arg);			\
53 		if (__rc != -1)						\
54 			break;						\
55 		if ((errno != EINTR) && (errno != EAGAIN))		\
56 			break;						\
57 		clock_gettime(CLOCK_MONOTONIC, &__end);			\
58 		if (__end.tv_sec * 10 + __end.tv_nsec / 100000000 >	\
59 		    __start.tv_sec * 10 + __start.tv_nsec / 100000000 +	\
60 		    MAX_TIME)						\
61 			break;						\
62 	} while (1);							\
63 									\
64 	__rc;								\
65 })
66 
dvb_dmx_open(int adapter,int demux)67 int dvb_dmx_open(int adapter, int demux)
68 {
69 	int fd_demux;
70 	struct dvb_device *dvb;
71 	struct dvb_dev_list *dvb_dev;
72 
73 	dvb = dvb_dev_alloc();
74 	dvb_dev_find(dvb, NULL, NULL);
75 	dvb_dev = dvb_dev_seek_by_adapter(dvb, adapter, demux, DVB_DEVICE_DEMUX);
76 	if (!dvb_dev) {
77 		dvb_dev_free(dvb);
78 		return -1;
79 	}
80 
81 	fd_demux = open(dvb_dev->path, O_RDWR | O_NONBLOCK);
82 	dvb_dev_free(dvb);
83 	return fd_demux;
84 }
85 
dvb_dmx_close(int dmx_fd)86 void dvb_dmx_close(int dmx_fd)
87 {
88 	(void)xioctl(dmx_fd, DMX_STOP);
89 	close(dmx_fd);
90 }
91 
dvb_dmx_stop(int dmx_fd)92 void dvb_dmx_stop(int dmx_fd)
93 {
94 	(void)xioctl(dmx_fd, DMX_STOP);
95 }
96 
dvb_set_pesfilter(int dmxfd,int pid,dmx_pes_type_t type,dmx_output_t output,int buffersize)97 int dvb_set_pesfilter(int dmxfd, int pid, dmx_pes_type_t type,
98 		      dmx_output_t output, int buffersize)
99 {
100 	struct dmx_pes_filter_params pesfilter;
101 
102 	if (buffersize) {
103 		if (xioctl(dmxfd, DMX_SET_BUFFER_SIZE, buffersize) == -1)
104 			perror("DMX_SET_BUFFER_SIZE failed");
105 	}
106 
107 	memset(&pesfilter, 0, sizeof(pesfilter));
108 
109 	pesfilter.pid = pid;
110 	pesfilter.input = DMX_IN_FRONTEND;
111 	pesfilter.output = output;
112 	pesfilter.pes_type = type;
113 	pesfilter.flags = DMX_IMMEDIATE_START;
114 
115 	if (xioctl(dmxfd, DMX_SET_PES_FILTER, &pesfilter) == -1) {
116 		fprintf(stderr, "DMX_SET_PES_FILTER failed "
117 		"(PID = 0x%04x): %d %m\n", pid, errno);
118 		return -1;
119 	}
120 
121 	return 0;
122 }
123 
dvb_set_section_filter(int dmxfd,int pid,unsigned filtsize,unsigned char * filter,unsigned char * mask,unsigned char * mode,unsigned int flags)124 int dvb_set_section_filter(int dmxfd, int pid, unsigned filtsize,
125 			   unsigned char *filter,
126 			   unsigned char *mask,
127 			   unsigned char *mode,
128 			   unsigned int flags)
129 {
130 	struct dmx_sct_filter_params sctfilter;
131 
132 	if (filtsize > DMX_FILTER_SIZE)
133 		filtsize = DMX_FILTER_SIZE;
134 
135 	memset(&sctfilter, 0, sizeof(sctfilter));
136 
137 	sctfilter.pid = pid;
138 
139 	if (filter)
140 		memcpy(sctfilter.filter.filter, filter, filtsize);
141 	if (mask)
142 		memcpy(sctfilter.filter.mask, mask, filtsize);
143 	if (mode)
144 		memcpy(sctfilter.filter.mode, mode, filtsize);
145 
146 	sctfilter.flags = flags;
147 
148 	if (xioctl(dmxfd, DMX_SET_FILTER, &sctfilter) == -1) {
149 		fprintf(stderr, "DMX_SET_FILTER failed (PID = 0x%04x): %d %m\n",
150 			pid, errno);
151 		return -1;
152 	}
153 
154 	return 0;
155 }
156 
dvb_get_pmt_pid(int patfd,int sid)157 int dvb_get_pmt_pid(int patfd, int sid)
158 {
159 	int count;
160 	int pmt_pid = 0;
161 	int patread = 0;
162 	int section_length;
163 	unsigned char buft[4096];
164 	unsigned char *buf = buft;
165 	struct dmx_sct_filter_params f;
166 
167 	memset(&f, 0, sizeof(f));
168 	f.pid = 0;
169 	f.filter.filter[0] = 0x00;
170 	f.filter.mask[0] = 0xff;
171 	f.timeout = 0;
172 	f.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC;
173 
174 	if (xioctl(patfd, DMX_SET_FILTER, &f) == -1) {
175 		perror("ioctl DMX_SET_FILTER failed");
176 		return -1;
177 	}
178 
179 	while (!patread){
180 		if (((count = read(patfd, buf, sizeof(buft))) < 0) && errno == EOVERFLOW)
181 			count = read(patfd, buf, sizeof(buft));
182 
183 		if (count < 0) {
184 			perror("read_sections: read error");
185 			return -1;
186 		}
187 
188 		section_length = ((buf[1] & 0x0f) << 8) | buf[2];
189 		if (count != section_length + 3)
190 			continue;
191 
192 		buf += 8;
193 		section_length -= 8;
194 
195 		patread = 1; /* assumes one section contains the whole pat */
196 		while (section_length > 0) {
197 		int service_id = (buf[0] << 8) | buf[1];
198 		if (service_id == sid) {
199 			pmt_pid = ((buf[2] & 0x1f) << 8) | buf[3];
200 			section_length = 0;
201 		}
202 		buf += 4;
203 		section_length -= 4;
204 		}
205 	}
206 
207 	return pmt_pid;
208 }
209