xref: /haiku/src/add-ons/media/media-add-ons/dvb/DVBCard.cpp (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
1 /*
2  * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify,
8  * merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <sys/ioctl.h>
31 #include <errno.h> // required on BeOS R5
32 #include <OS.h>
33 
34 #include "DVBCard.h"
35 
36 
37 DVBCard::DVBCard(const char *path)
38  :	fInitStatus(B_OK)
39  ,	fDev(-1)
40 {
41 	printf("DVBCard opening %s\n", path);
42 
43 	fDev = open(path, O_RDWR);
44 	if (fDev < 0) {
45 		printf("DVBCard opening %s failed\n", path);
46 		fInitStatus = B_ERROR;
47 		return;
48 	}
49 
50 	dvb_frequency_info_t info;
51 	if (do_ioctl(fDev, DVB_GET_FREQUENCY_INFO, &info) < 0) {
52 		printf("DVB_GET_FREQUENCY_INFO failed with error %s\n", strerror(errno));
53 //		close(fDev);
54 //		fDev = -1;
55 //		return;
56 	}
57 
58 	fFreqMin  = info.frequency_min;
59 	fFreqMax  = info.frequency_max;
60 	fFreqStep = info.frequency_step;
61 
62 	fCaptureActive = false;
63 }
64 
65 
66 DVBCard::~DVBCard()
67 {
68 	if (fDev > 0)
69 		close(fDev);
70 }
71 
72 
73 status_t
74 DVBCard::InitCheck()
75 {
76 	return fInitStatus;
77 }
78 
79 
80 status_t
81 DVBCard::GetCardType(dvb_type_t *type)
82 {
83 	dvb_interface_info_t info;
84 
85 	if (do_ioctl(fDev, DVB_GET_INTERFACE_INFO, &info) < 0) {
86 		printf("DVB_GET_INTERFACE_INFO failed with error %s\n", strerror(errno));
87 		return errno;
88 	}
89 
90 	if (info.version < 1) {
91 		printf("DVBCard::GetCardInfo wrong API version\n");
92 		return B_ERROR;
93 	}
94 
95 	*type = info.type;
96 	return B_OK;
97 }
98 
99 
100 status_t
101 DVBCard::GetCardInfo(char *_name, int max_name_len, char *_info, int max_info_len)
102 {
103 	dvb_interface_info_t info;
104 
105 	if (do_ioctl(fDev, DVB_GET_INTERFACE_INFO, &info) < 0) {
106 		printf("DVB_GET_INTERFACE_INFO failed with error %s\n", strerror(errno));
107 		return errno;
108 	}
109 
110 //	strlcpy(_name, info.name, max_name_len);
111 //	strlcpy(_info, info.info, max_info_len);
112 	strcpy(_name, info.name);
113 	strcpy(_info, info.info);
114 
115 	if (info.version < 1) {
116 		printf("DVBCard::GetCardInfo wrong API version\n");
117 		return B_ERROR;
118 	}
119 
120 	return B_OK;
121 }
122 
123 
124 status_t
125 DVBCard::SetTuningParameter(const dvb_tuning_parameters_t& param)
126 {
127 	if (fDev < 0)
128 		return B_NO_INIT;
129 
130 	printf("DVBCard::SetTuningParameter:\n");
131 /*
132 	printf("frequency %lld\n", param.frequency);
133 	printf("inversion %d\n", param.inversion);
134 	printf("bandwidth %d\n", param.bandwidth);
135 	printf("modulation %d\n", param.modulation);
136 	printf("hierarchy %d\n", param.hierarchy);
137 	printf("code_rate_hp %d\n", param.code_rate_hp);
138 	printf("code_rate_lp %d\n", param.code_rate_lp);
139 	printf("transmission_mode %d\n", param.transmission_mode);
140 	printf("guard_interval %d\n", param.guard_interval);
141 	printf("symbolrate %d\n", param.symbolrate);
142 	printf("polarity %d\n", param.polarity);
143 	printf("agc_inversion %d\n", param.agc_inversion);
144 */
145 	params = param;// XXX temporary!
146 
147 //	if (do_ioctl(fDev, DVB_SET_TUNING_PARAMETERS, const_cast<void *>(&param)) < 0) {
148 //	if (do_ioctl(fDev, DVB_SET_TUNING_PARAMETERS, (void *)(&param)) < 0) {
149 	if (ioctl(fDev, DVB_SET_TUNING_PARAMETERS, (void *)(&param)) < 0) {
150 		printf("DVB_SET_TUNING_PARAMETERS failed with error %s\n", strerror(errno));
151 		return errno;
152 	}
153 
154 	dvb_status_t status;
155 
156 	bigtime_t start = system_time();
157 	bool has_lock = false;
158 	bool has_signal = false;
159 	bool has_carrier = false;
160 	do {
161 		if (do_ioctl(fDev, DVB_GET_STATUS, &status) < 0) {
162 			printf("DVB_GET_STATUS failed with error %s\n", strerror(errno));
163 			return errno;
164 		}
165 		if (!has_signal && status & DVB_STATUS_SIGNAL) {
166 			has_signal = true;
167 			printf("got signal after %.6f\n", (system_time() - start) / 1e6);
168 		}
169 		if (!has_carrier && status & DVB_STATUS_CARRIER) {
170 			has_carrier = true;
171 			printf("got carrier after %.6f\n", (system_time() - start) / 1e6);
172 		}
173 		if (!has_lock && status & DVB_STATUS_LOCK) {
174 			has_lock = true;
175 			printf("got lock after %.6f\n", (system_time() - start) / 1e6);
176 		}
177 
178 		if ((status & (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK)) == (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK))
179 			break;
180 		snooze(25000);
181 	} while ((system_time() - start) < 5000000);
182 
183 
184 	if ((status & (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK)) != (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK)) {
185 		printf("DVB tuning failed! need these status flags: DVB_STATUS_SIGNAL, DVB_STATUS_CARRIER, DVB_STATUS_LOCK\n");
186 		return B_ERROR;
187 	}
188 
189 	return B_OK;
190 }
191 
192 
193 status_t
194 DVBCard::GetTuningParameter(dvb_tuning_parameters_t *param)
195 {
196 	// XXX get from CARD
197 	*param = params;
198 	return B_OK;
199 }
200 
201 
202 status_t
203 DVBCard::GetSignalInfo(uint32 *ss, uint32 *ber, uint32 *snr)
204 {
205 	if (do_ioctl(fDev, DVB_GET_SS, ss) < 0) {
206 		printf("DVB_GET_SS failed with error %s\n", strerror(errno));
207 		return errno;
208 	}
209 	if (do_ioctl(fDev, DVB_GET_BER, ber) < 0) {
210 		printf("DVB_GET_BER failed with error %s\n", strerror(errno));
211 		return errno;
212 	}
213 	if (do_ioctl(fDev, DVB_GET_SNR, snr) < 0) {
214 		printf("DVB_GET_SNR failed with error %s\n", strerror(errno));
215 		return errno;
216 	}
217 
218 	printf("ss %08lx, ber %08lx, snr %08lx\n", *ss, *ber, *snr);
219 	printf("ss %lu%%, ber %lu%%, snr %lu%%\n", *ss / (0xffffffff / 100), *ber / (0xffffffff / 100), *snr / (0xffffffff / 100));
220 	return B_OK;
221 }
222 
223 
224 status_t
225 DVBCard::CaptureStart()
226 {
227 	printf("DVBCard::CaptureStart\n");
228 
229 	if (fCaptureActive) {
230 		printf("CaptureStart already called, doing nothing\n");
231 		return B_OK;
232 	}
233 
234 	if (do_ioctl(fDev, DVB_START_CAPTURE, 0) < 0) {
235 		printf("DVB_START_CAPTURE failed with error %s\n", strerror(errno));
236 		return errno;
237 	}
238 
239 	fCaptureActive = true;
240 	return B_OK;
241 }
242 
243 
244 status_t
245 DVBCard::CaptureStop()
246 {
247 	printf("DVBCard::CaptureStop\n");
248 
249 	if (!fCaptureActive) {
250 		printf("CaptureStop already called, doing nothing\n");
251 		return B_OK;
252 	}
253 
254 	if (do_ioctl(fDev, DVB_STOP_CAPTURE, 0) < 0) {
255 		printf("DVB_STOP_CAPTURE failed with error %s\n", strerror(errno));
256 		return errno;
257 	}
258 
259 	fCaptureActive = false;
260 	return B_OK;
261 }
262 
263 
264 status_t
265 DVBCard::Capture(void **data, size_t *size, bigtime_t *end_time)
266 {
267 	dvb_capture_t cap;
268 
269 	if (ioctl(fDev, DVB_CAPTURE, &cap) < 0)
270 		return errno;
271 
272 	*data	  = cap.data;
273 	*size	  = cap.size;
274 	*end_time = cap.end_time;
275 
276 	return B_OK;
277 }
278 
279 
280 int
281 DVBCard::do_ioctl(int fDev, ulong op, void *arg)
282 {
283 	int res = 0; // silence stupid compiler warning
284 	int i;
285 	for (i = 0; i < 20; i++) {
286 		res = ioctl(fDev, op, arg);
287 		if (res >= 0)
288 			break;
289 	}
290 	if (i != 0)	printf("ioctl %lx repeated %d times\n", op, i);
291 	return res;
292 }
293