11abddd9f6225298066094e20a6c29061b6af4590Nick Chalko/*
21abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Copyright (C) 2015 The Android Open Source Project
31abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *
41abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License");
51abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * you may not use this file except in compliance with the License.
61abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * You may obtain a copy of the License at
71abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *
81abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *      http://www.apache.org/licenses/LICENSE-2.0
91abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *
101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Unless required by applicable law or agreed to in writing, software
111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS,
121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * See the License for the specific language governing permissions and
141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * limitations under the License.
151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */
161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include <stdio.h>
181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include <stdlib.h>
191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include <errno.h>
201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include <unistd.h>
211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include <limits.h>
221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include <string.h>
231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include <fcntl.h>
241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include <sys/poll.h>
251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include <sys/ioctl.h>
261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include <linux/dvb/dmx.h>
271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include <linux/dvb/frontend.h>
281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#define LOG_TAG "DvbManager"
301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include "logging.h"
311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko#include "DvbManager.h"
331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
341abddd9f6225298066094e20a6c29061b6af4590Nick Chalkostatic double currentTimeMillis() {
351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    struct timeval tv;
361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    gettimeofday(&tv, (struct timezone *) NULL);
371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
401abddd9f6225298066094e20a6c29061b6af4590Nick ChalkoDvbManager::DvbManager(JNIEnv *env, jobject)
411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        : mFeFd(-1),
421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko          mDemuxFd(-1),
431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko          mDvrFd(-1),
441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko          mPatFilterFd(-1),
456ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko          mDvbApiVersion(DVB_API_VERSION_UNDEFINED),
466ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko          mDeliverySystemType(-1),
4765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko          mFeHasLock(false),
4865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko          mHasPendingTune(false) {
491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    jclass clazz = env->FindClass(
5065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        "com/android/tv/tuner/TunerHal");
511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mOpenDvbFrontEndMethodID = env->GetMethodID(
521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        clazz, "openDvbFrontEndFd", "()I");
531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mOpenDvbDemuxMethodID = env->GetMethodID(
541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        clazz, "openDvbDemuxFd", "()I");
551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mOpenDvbDvrMethodID = env->GetMethodID(
561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        clazz, "openDvbDvrFd", "()I");
571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
591abddd9f6225298066094e20a6c29061b6af4590Nick ChalkoDvbManager::~DvbManager() {
601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    reset();
611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
631abddd9f6225298066094e20a6c29061b6af4590Nick Chalkobool DvbManager::isFeLocked() {
646ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    if (mDvbApiVersion == DVB_API_VERSION5) {
656ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        fe_status_t status;
666ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (ioctl(mFeFd, FE_READ_STATUS, &status) < 0) {
676ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            return false;
686ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
696ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (status & FE_HAS_LOCK) {
706ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            return true;
716ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
726ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    } else {
736ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        struct pollfd pollFd;
746ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        pollFd.fd = mFeFd;
756ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        pollFd.events = POLLIN;
766ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        pollFd.revents = 0;
776ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        int poll_result = poll(&pollFd, NUM_POLLFDS, FE_POLL_TIMEOUT_MS);
786ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (poll_result > 0 && (pollFd.revents & POLLIN)) {
796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            struct dvb_frontend_event kevent;
806ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            memset(&kevent, 0, sizeof(kevent));
816ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            if (ioctl(mFeFd, FE_GET_EVENT, &kevent) == 0) {
826ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                return (kevent.status & FE_HAS_LOCK);
836ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            }
8465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return false;
871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
89ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoint DvbManager::tune(JNIEnv *env, jobject thiz,
901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        const int frequency, const char *modulationStr, int timeout_ms) {
911abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    resetExceptFe();
921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (openDvbFe(env, thiz) != 0) {
941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    if (mDvbApiVersion == DVB_API_VERSION_UNDEFINED) {
976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        struct dtv_property testProps[1] = {
986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            { .cmd = DTV_DELIVERY_SYSTEM }
996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        };
1006ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        struct dtv_properties feProp = {
1016ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            .num = 1, .props = testProps
1026ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        };
1036ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        // On fugu, DVB_API_VERSION is 5 but it doesn't support FE_SET_PROPERTY. Checking the device
1046ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        // support FE_GET_PROPERTY or not to determine the DVB API version is greater than 5 or not.
1056ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (ioctl(mFeFd, FE_GET_PROPERTY, &feProp) == -1) {
1066ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            ALOGD("FE_GET_PROPERTY failed, %s", strerror(errno));
1076ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mDvbApiVersion = DVB_API_VERSION3;
1086ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        } else {
1096ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mDvbApiVersion = DVB_API_VERSION5;
1101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1136ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    if (mDvbApiVersion == DVB_API_VERSION5) {
1146ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        struct dtv_property deliverySystemProperty = {
1156ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            .cmd = DTV_DELIVERY_SYSTEM, .u.data = SYS_ATSC
1166ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        };
1176ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        struct dtv_property frequencyProperty = {
1186ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            .cmd = DTV_FREQUENCY, .u.data = frequency
1196ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        };
1206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        struct dtv_property modulationProperty = { .cmd = DTV_MODULATION };
1216ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (strncmp(modulationStr, "QAM", 3) == 0) {
1226ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            modulationProperty.u.data = QAM_AUTO;
1236ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        } else if (strcmp(modulationStr, "8VSB") == 0) {
1246ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            modulationProperty.u.data = VSB_8;
1256ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        } else {
1266ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            ALOGE("Unrecognized modulation mode : %s", modulationStr);
1276ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            return -1;
1286ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
1296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        struct dtv_property tuneProperty = { .cmd = DTV_TUNE };
1306ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
1316ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        struct dtv_property props[] = {
1326ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                deliverySystemProperty, frequencyProperty, modulationProperty, tuneProperty
1336ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        };
1346ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        struct dtv_properties dtvProperty = {
1356ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            .num = 4, .props = props
1366ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        };
1376ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
1386ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (mHasPendingTune) {
1396ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            return -1;
1406ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
1416ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (ioctl(mFeFd, FE_SET_PROPERTY, &dtvProperty) != 0) {
1426ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            ALOGD("Can't set Frontend : %s", strerror(errno));
1436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            return -1;
1446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
1456ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    } else {
1466ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        struct dvb_frontend_parameters feParams;
1476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        memset(&feParams, 0, sizeof(struct dvb_frontend_parameters));
1486ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        feParams.frequency = frequency;
1496ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        feParams.inversion = INVERSION_AUTO;
1506ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        /* Check frontend capability */
1516ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        struct dvb_frontend_info feInfo;
1526ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (ioctl(mFeFd, FE_GET_INFO, &feInfo) != -1) {
1536ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            if (!(feInfo.caps & FE_CAN_INVERSION_AUTO)) {
1546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                // FE can't do INVERSION_AUTO, trying INVERSION_OFF instead
1556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                feParams.inversion = INVERSION_OFF;
1566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            }
1576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
1586ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        switch (feInfo.type) {
1596ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            case FE_ATSC:
1606ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                if (strcmp(modulationStr, "8VSB") == 0) {
1616ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    feParams.u.vsb.modulation = VSB_8;
1626ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                } else if (strncmp(modulationStr, "QAM", 3) == 0) {
1636ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    feParams.u.vsb.modulation = QAM_AUTO;
1646ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                } else {
1656ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    ALOGE("Unrecognized modulation mode : %s", modulationStr);
1666ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    return -1;
1676ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                }
1686ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                break;
1696ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            case FE_OFDM:
1706ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                if (strcmp(modulationStr, "8VSB") == 0) {
1716ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    feParams.u.ofdm.constellation = VSB_8;
1726ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                } else if (strcmp(modulationStr, "QAM16") == 0) {
1736ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    feParams.u.ofdm.constellation = QAM_16;
1746ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                } else if (strcmp(modulationStr, "QAM64") == 0) {
1756ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    feParams.u.ofdm.constellation = QAM_64;
1766ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                } else if (strcmp(modulationStr, "QAM256") == 0) {
1776ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    feParams.u.ofdm.constellation = QAM_256;
1786ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                } else if (strcmp(modulationStr, "QPSK") == 0) {
1796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    feParams.u.ofdm.constellation = QPSK;
1806ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                } else {
1816ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    ALOGE("Unrecognized modulation mode : %s", modulationStr);
1826ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    return -1;
1836ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                }
1846ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                break;
1856ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            default:
1866ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                ALOGE("Unsupported delivery system.");
1876ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                return -1;
1886ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
1896ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
1906ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (mHasPendingTune) {
1916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            return -1;
1926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
1936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
1946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (ioctl(mFeFd, FE_SET_FRONTEND, &feParams) != 0) {
1956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            ALOGD("Can't set Frontend : %s", strerror(errno));
1966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            return -1;
1976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
1981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int lockSuccessCount = 0;
2011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    double tuneClock = currentTimeMillis();
2021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    while (currentTimeMillis() - tuneClock < timeout_ms) {
20365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mHasPendingTune) {
20465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            // Return 0 here since we already call FE_SET_FRONTEND, and return due to having pending
20565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            // tune request. And the frontend setting could be successful.
20665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mFeHasLock = true;
20765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            return 0;
20865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
2091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        bool lockStatus = isFeLocked();
2101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (lockStatus) {
2111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            lockSuccessCount++;
2121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        } else {
2131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            lockSuccessCount = 0;
2141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGI("Lock status : %s", lockStatus ? "true" : "false");
2161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (lockSuccessCount >= FE_CONSECUTIVE_LOCK_SUCCESS_COUNT) {
2171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mFeHasLock = true;
2181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            openDvbDvr(env, thiz);
2191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            return 0;
2201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return -1;
2241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2261abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::stopTune() {
2271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    reset();
2281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    usleep(DVB_TUNE_STOP_DELAY_MS);
2291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return 0;
2301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2321abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::openDvbFeFromSystemApi(JNIEnv *env, jobject thiz) {
2331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int fd = (int) env->CallIntMethod(thiz, mOpenDvbFrontEndMethodID);
2341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
2351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return fd;
2361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2381abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::openDvbDemuxFromSystemApi(JNIEnv *env, jobject thiz) {
2391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int fd = (int) env->CallIntMethod(thiz, mOpenDvbDemuxMethodID);
2401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
2411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return fd;
2421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2441abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::openDvbDvrFromSystemApi(JNIEnv *env, jobject thiz) {
2451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int fd = (int) env->CallIntMethod(thiz, mOpenDvbDvrMethodID);
2461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
2471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return fd;
2481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2501abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::openDvbFe(JNIEnv *env, jobject thiz) {
2511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mFeFd == -1) {
2521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if ((mFeFd = openDvbFeFromSystemApi(env, thiz)) < 0) {
2531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            ALOGD("Can't open FE file : %s", strerror(errno));
2541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            return -1;
2551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    struct dvb_frontend_info info;
2591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (ioctl(mFeFd, FE_GET_INFO, &info) == 0) {
2601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        const char *types;
2611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        switch (info.type) {
2621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            case FE_QPSK:
2631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                types = "DVB-S";
2641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                break;
2651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            case FE_QAM:
2661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                types = "DVB-C";
2671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                break;
2681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            case FE_OFDM:
2691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                types = "DVB-T";
2701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                break;
2711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            case FE_ATSC:
2721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                types = "ATSC";
2731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                break;
2741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            default:
2751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                types = "Unknown";
2761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGI("Using frontend \"%s\", type %s", info.name, types);
2781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return 0;
2801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2821abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::startTsPidFilter(JNIEnv *env, jobject thiz, int pid, int filterType) {
2831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    Mutex::Autolock autoLock(mFilterLock);
2841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mPidFilters.find(pid) != mPidFilters.end() || (mPatFilterFd != -1 && pid == PAT_PID)) {
2861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return 0;
2871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
28965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    if (mHasPendingTune) {
29065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return -1;
29165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
29265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
2931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int demuxFd;
2941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if ((demuxFd = openDvbDemuxFromSystemApi(env, thiz)) < 0) {
2951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGD("Can't open DEMUX file : %s", strerror(errno));
2961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
2971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    struct dmx_pes_filter_params filter;
3001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    memset(&filter, 0, sizeof(filter));
3011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    filter.pid = pid;
3021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    filter.input = DMX_IN_FRONTEND;
3031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    switch (filterType) {
3041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        case FILTER_TYPE_AUDIO:
3051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            filter.pes_type = DMX_PES_AUDIO;
3061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            break;
3071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        case FILTER_TYPE_VIDEO:
3081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            filter.pes_type = DMX_PES_VIDEO;
3091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            break;
3101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        case FILTER_TYPE_PCR:
3111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            filter.pes_type = DMX_PES_PCR;
3121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            break;
3131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        default:
3141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            filter.pes_type = DMX_PES_OTHER;
3151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            break;
3161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    filter.output = DMX_OUT_TS_TAP;
3181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    filter.flags |= (DMX_CHECK_CRC | DMX_IMMEDIATE_START);
3191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    // create a pes filter
3211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (ioctl(demuxFd, DMX_SET_PES_FILTER, &filter)) {
3221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        close(demuxFd);
3231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
3241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3266ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    if (mDvbApiVersion == DVB_API_VERSION5) {
3276ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        ioctl(demuxFd, DMX_START, 0);
3286ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    }
3296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
3301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (pid != PAT_PID) {
3311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPidFilters.insert(std::pair<int, int>(pid, demuxFd));
3321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    } else {
3331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPatFilterFd = demuxFd;
3341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return 0;
3371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
3381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3391abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::closeAllDvbPidFilter() {
3401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    // Close all dvb pid filters except PAT filter to maintain the opening status of the device.
3411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    Mutex::Autolock autoLock(mFilterLock);
3421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    for (std::map<int, int>::iterator it(mPidFilters.begin());
3441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                it != mPidFilters.end(); it++) {
3451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        close(it->second);
3461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mPidFilters.clear();
34865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    // Close mDvrFd to make sure there is not buffer from previous channel left.
34965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    closeDvbDvr();
3501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
3511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3521abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::closePatFilter() {
3531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    Mutex::Autolock autoLock(mFilterLock);
3541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mPatFilterFd != -1) {
3561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        close(mPatFilterFd);
3571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPatFilterFd = -1;
3581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
3601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3611abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::openDvbDvr(JNIEnv *env, jobject thiz) {
3621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if ((mDvrFd = openDvbDvrFromSystemApi(env, thiz)) < 0) {
3631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGD("Can't open DVR file : %s", strerror(errno));
3641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
3651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return 0;
3671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
3681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3691abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::closeDvbFe() {
3701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mFeFd != -1) {
3711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        close(mFeFd);
3721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mFeFd = -1;
3731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
3751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3761abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::closeDvbDvr() {
3771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mDvrFd != -1) {
3781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        close(mDvrFd);
3791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mDvrFd = -1;
3801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
3821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3831abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::reset() {
3841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mFeHasLock = false;
3851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closeDvbDvr();
3861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closeAllDvbPidFilter();
3871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closePatFilter();
3881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closeDvbFe();
3891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
3901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3911abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::resetExceptFe() {
3921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mFeHasLock = false;
3931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closeDvbDvr();
3941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closeAllDvbPidFilter();
3951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closePatFilter();
3961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
3971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3981abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::readTsStream(JNIEnv *env, jobject thiz,
3991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        uint8_t *tsBuffer, int tsBufferSize, int timeout_ms) {
4001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (!mFeHasLock) {
4011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        usleep(DVB_ERROR_RETRY_INTERVAL_MS);
4021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
4031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
4041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mDvrFd == -1) {
4061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        openDvbDvr(env, thiz);
4071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
4081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    struct pollfd pollFd;
4101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    pollFd.fd = mDvrFd;
4111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    pollFd.events = POLLIN|POLLPRI|POLLERR;
4121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    pollFd.revents = 0;
4131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int poll_result = poll(&pollFd, NUM_POLLFDS, timeout_ms);
4141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (poll_result == 0) {
4151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return 0;
4161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    } else if (poll_result == -1 || pollFd.revents & POLLERR) {
4171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGD("Can't read DVR : %s", strerror(errno));
4181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        // TODO: Find how to recover this situation correctly.
4191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        closeDvbDvr();
4201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        usleep(DVB_ERROR_RETRY_INTERVAL_MS);
4211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
4221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
4231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return read(mDvrFd, tsBuffer, tsBufferSize);
4241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
42565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
42665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkovoid DvbManager::setHasPendingTune(bool hasPendingTune) {
42765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    mHasPendingTune = hasPendingTune;
42865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko}
4296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
4306ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoint DvbManager::getDeliverySystemType(JNIEnv *env, jobject thiz) {
4316ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    if (mDeliverySystemType != -1) {
4326ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        return mDeliverySystemType;
4336ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    }
4346ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    if (mFeFd == -1) {
4356ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if ((mFeFd = openDvbFeFromSystemApi(env, thiz)) < 0) {
4366ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            ALOGD("Can't open FE file : %s", strerror(errno));
4376ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            return DELIVERY_SYSTEM_UNDEFINED;
4386ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
4396ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    }
4406ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    struct dtv_property testProps[1] = {
4416ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        { .cmd = DTV_DELIVERY_SYSTEM }
4426ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    };
4436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    struct dtv_properties feProp = {
4446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        .num = 1, .props = testProps
4456ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    };
4466ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    mDeliverySystemType = DELIVERY_SYSTEM_UNDEFINED;
4476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    if (ioctl(mFeFd, FE_GET_PROPERTY, &feProp) == -1) {
4486ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        mDvbApiVersion = DVB_API_VERSION3;
4496ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (openDvbFe(env, thiz) == 0) {
4506ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            struct dvb_frontend_info info;
4516ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            if (ioctl(mFeFd, FE_GET_INFO, &info) == 0) {
4526ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                switch (info.type) {
4536ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    case FE_QPSK:
4546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        mDeliverySystemType = DELIVERY_SYSTEM_DVBS;
4556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        break;
4566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    case FE_QAM:
4576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        mDeliverySystemType = DELIVERY_SYSTEM_DVBC;
4586ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        break;
4596ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    case FE_OFDM:
4606ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        mDeliverySystemType = DELIVERY_SYSTEM_DVBT;
4616ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        break;
4626ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    case FE_ATSC:
4636ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        mDeliverySystemType = DELIVERY_SYSTEM_ATSC;
4646ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        break;
4656ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    default:
4666ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        mDeliverySystemType = DELIVERY_SYSTEM_UNDEFINED;
4676ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        break;
4686ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                }
4696ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            }
4706ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
4716ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    } else {
4726ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        mDvbApiVersion = DVB_API_VERSION5;
4736ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        switch (feProp.props[0].u.data) {
4746ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            case SYS_DVBT:
4756ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                mDeliverySystemType = DELIVERY_SYSTEM_DVBT;
4766ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                break;
4776ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            case SYS_DVBT2:
4786ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                mDeliverySystemType = DELIVERY_SYSTEM_DVBT2;
4796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                break;
4806ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            case SYS_DVBS:
4816ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                mDeliverySystemType = DELIVERY_SYSTEM_DVBS;
4826ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                break;
4836ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            case SYS_DVBS2:
4846ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                mDeliverySystemType = DELIVERY_SYSTEM_DVBS2;
4856ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                break;
4866ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            case SYS_DVBC_ANNEX_A:
4876ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            case SYS_DVBC_ANNEX_B:
4886ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            case SYS_DVBC_ANNEX_C:
4896ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                mDeliverySystemType = DELIVERY_SYSTEM_DVBC;
4906ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                break;
4916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            case SYS_ATSC:
4926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                mDeliverySystemType = DELIVERY_SYSTEM_ATSC;
4936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                break;
4946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            default:
4956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                mDeliverySystemType = DELIVERY_SYSTEM_UNDEFINED;
4966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                break;
4976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
4986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    }
4996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    return mDeliverySystemType;
5006ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko}