* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <OS.h>
#include "DVBCard.h"
DVBCard::DVBCard(const char *path)
: fInitStatus(B_OK)
, fDev(-1)
{
printf("DVBCard opening %s\n", path);
fDev = open(path, O_RDWR);
if (fDev < 0) {
printf("DVBCard opening %s failed\n", path);
fInitStatus = B_ERROR;
return;
}
dvb_frequency_info_t info;
if (do_ioctl(fDev, DVB_GET_FREQUENCY_INFO, &info) < 0) {
printf("DVB_GET_FREQUENCY_INFO failed with error %s\n", strerror(errno));
}
fFreqMin = info.frequency_min;
fFreqMax = info.frequency_max;
fFreqStep = info.frequency_step;
fCaptureActive = false;
}
DVBCard::~DVBCard()
{
if (fDev > 0)
close(fDev);
}
status_t
DVBCard::InitCheck()
{
return fInitStatus;
}
status_t
DVBCard::GetCardType(dvb_type_t *type)
{
dvb_interface_info_t info;
if (do_ioctl(fDev, DVB_GET_INTERFACE_INFO, &info) < 0) {
printf("DVB_GET_INTERFACE_INFO failed with error %s\n", strerror(errno));
return errno;
}
if (info.version < 1) {
printf("DVBCard::GetCardInfo wrong API version\n");
return B_ERROR;
}
*type = info.type;
return B_OK;
}
status_t
DVBCard::GetCardInfo(char *_name, int max_name_len, char *_info, int max_info_len)
{
dvb_interface_info_t info;
if (do_ioctl(fDev, DVB_GET_INTERFACE_INFO, &info) < 0) {
printf("DVB_GET_INTERFACE_INFO failed with error %s\n", strerror(errno));
return errno;
}
strcpy(_name, info.name);
strcpy(_info, info.info);
if (info.version < 1) {
printf("DVBCard::GetCardInfo wrong API version\n");
return B_ERROR;
}
return B_OK;
}
status_t
DVBCard::SetTuningParameter(const dvb_tuning_parameters_t& param)
{
if (fDev < 0)
return B_NO_INIT;
printf("DVBCard::SetTuningParameter:\n");
printf("frequency %lld\n", param.frequency);
printf("inversion %d\n", param.inversion);
printf("bandwidth %d\n", param.bandwidth);
printf("modulation %d\n", param.modulation);
printf("hierarchy %d\n", param.hierarchy);
printf("code_rate_hp %d\n", param.code_rate_hp);
printf("code_rate_lp %d\n", param.code_rate_lp);
printf("transmission_mode %d\n", param.transmission_mode);
printf("guard_interval %d\n", param.guard_interval);
printf("symbolrate %d\n", param.symbolrate);
printf("polarity %d\n", param.polarity);
printf("agc_inversion %d\n", param.agc_inversion);
*/
params = param;
if (ioctl(fDev, DVB_SET_TUNING_PARAMETERS, (void *)(¶m)) < 0) {
printf("DVB_SET_TUNING_PARAMETERS failed with error %s\n", strerror(errno));
return errno;
}
dvb_status_t status;
bigtime_t start = system_time();
bool has_lock = false;
bool has_signal = false;
bool has_carrier = false;
do {
if (do_ioctl(fDev, DVB_GET_STATUS, &status) < 0) {
printf("DVB_GET_STATUS failed with error %s\n", strerror(errno));
return errno;
}
if (!has_signal && status & DVB_STATUS_SIGNAL) {
has_signal = true;
printf("got signal after %.6f\n", (system_time() - start) / 1e6);
}
if (!has_carrier && status & DVB_STATUS_CARRIER) {
has_carrier = true;
printf("got carrier after %.6f\n", (system_time() - start) / 1e6);
}
if (!has_lock && status & DVB_STATUS_LOCK) {
has_lock = true;
printf("got lock after %.6f\n", (system_time() - start) / 1e6);
}
if ((status & (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK)) == (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK))
break;
snooze(25000);
} while ((system_time() - start) < 5000000);
if ((status & (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK)) != (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK)) {
printf("DVB tuning failed! need these status flags: DVB_STATUS_SIGNAL, DVB_STATUS_CARRIER, DVB_STATUS_LOCK\n");
return B_ERROR;
}
return B_OK;
}
status_t
DVBCard::GetTuningParameter(dvb_tuning_parameters_t *param)
{
*param = params;
return B_OK;
}
status_t
DVBCard::GetSignalInfo(uint32 *ss, uint32 *ber, uint32 *snr)
{
if (do_ioctl(fDev, DVB_GET_SS, ss) < 0) {
printf("DVB_GET_SS failed with error %s\n", strerror(errno));
return errno;
}
if (do_ioctl(fDev, DVB_GET_BER, ber) < 0) {
printf("DVB_GET_BER failed with error %s\n", strerror(errno));
return errno;
}
if (do_ioctl(fDev, DVB_GET_SNR, snr) < 0) {
printf("DVB_GET_SNR failed with error %s\n", strerror(errno));
return errno;
}
printf("ss %08lx, ber %08lx, snr %08lx\n", *ss, *ber, *snr);
printf("ss %lu%%, ber %lu%%, snr %lu%%\n", *ss / (0xffffffff / 100), *ber / (0xffffffff / 100), *snr / (0xffffffff / 100));
return B_OK;
}
status_t
DVBCard::CaptureStart()
{
printf("DVBCard::CaptureStart\n");
if (fCaptureActive) {
printf("CaptureStart already called, doing nothing\n");
return B_OK;
}
if (do_ioctl(fDev, DVB_START_CAPTURE, 0) < 0) {
printf("DVB_START_CAPTURE failed with error %s\n", strerror(errno));
return errno;
}
fCaptureActive = true;
return B_OK;
}
status_t
DVBCard::CaptureStop()
{
printf("DVBCard::CaptureStop\n");
if (!fCaptureActive) {
printf("CaptureStop already called, doing nothing\n");
return B_OK;
}
if (do_ioctl(fDev, DVB_STOP_CAPTURE, 0) < 0) {
printf("DVB_STOP_CAPTURE failed with error %s\n", strerror(errno));
return errno;
}
fCaptureActive = false;
return B_OK;
}
status_t
DVBCard::Capture(void **data, size_t *size, bigtime_t *end_time)
{
dvb_capture_t cap;
if (ioctl(fDev, DVB_CAPTURE, &cap) < 0)
return errno;
*data = cap.data;
*size = cap.size;
*end_time = cap.end_time;
return B_OK;
}
int
DVBCard::do_ioctl(int fDev, ulong op, void *arg)
{
int res = 0;
int i;
for (i = 0; i < 20; i++) {
res = ioctl(fDev, op, arg);
if (res >= 0)
break;
}
if (i != 0) printf("ioctl %lx repeated %d times\n", op, i);
return res;
}