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 %Ld\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 *>(¶m)) < 0) { 148 // if (do_ioctl(fDev, DVB_SET_TUNING_PARAMETERS, (void *)(¶m)) < 0) { 149 if (ioctl(fDev, DVB_SET_TUNING_PARAMETERS, (void *)(¶m)) < 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