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),
4565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko          mFeHasLock(false),
4665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko          mHasPendingTune(false) {
471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    jclass clazz = env->FindClass(
4865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        "com/android/tv/tuner/TunerHal");
491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mOpenDvbFrontEndMethodID = env->GetMethodID(
501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        clazz, "openDvbFrontEndFd", "()I");
511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mOpenDvbDemuxMethodID = env->GetMethodID(
521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        clazz, "openDvbDemuxFd", "()I");
531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mOpenDvbDvrMethodID = env->GetMethodID(
541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        clazz, "openDvbDvrFd", "()I");
551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
571abddd9f6225298066094e20a6c29061b6af4590Nick ChalkoDvbManager::~DvbManager() {
581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    reset();
591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
611abddd9f6225298066094e20a6c29061b6af4590Nick Chalkobool DvbManager::isFeLocked() {
6265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    struct pollfd pollFd;
6365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    pollFd.fd = mFeFd;
6465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    pollFd.events = POLLIN;
6565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    pollFd.revents = 0;
6665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    int poll_result = poll(&pollFd, NUM_POLLFDS, FE_POLL_TIMEOUT_MS);
6765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    if (poll_result > 0 && (pollFd.revents & POLLIN)) {
6865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        struct dvb_frontend_event kevent;
6965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        memset(&kevent, 0, sizeof(kevent));
7065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (ioctl(mFeFd, FE_GET_EVENT, &kevent) == 0) {
7165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            return (kevent.status & FE_HAS_LOCK);
7265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return false;
751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
77ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoint DvbManager::tune(JNIEnv *env, jobject thiz,
781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        const int frequency, const char *modulationStr, int timeout_ms) {
791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    resetExceptFe();
801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    struct dvb_frontend_parameters feParams;
821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    memset(&feParams, 0, sizeof(struct dvb_frontend_parameters));
831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    feParams.frequency = frequency;
841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (strcmp(modulationStr, "8VSB") == 0) {
851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        feParams.u.vsb.modulation = VSB_8;
861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    } else if (strcmp(modulationStr, "QAM256") == 0) {
871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        feParams.u.vsb.modulation = QAM_256;
881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    } else {
891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGE("Unrecognized modulation mode : %s", modulationStr);
901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
911abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
9365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    if (mHasPendingTune) {
9465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return -1;
9565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (openDvbFe(env, thiz) != 0) {
971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    feParams.inversion = INVERSION_AUTO;
1011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /* Check frontend capability */
1021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    struct dvb_frontend_info feInfo;
1031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (ioctl(mFeFd, FE_GET_INFO, &feInfo) != -1) {
1041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (!(feInfo.caps & FE_CAN_INVERSION_AUTO)) {
1051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            // FE can't do INVERSION_AUTO, trying INVERSION_OFF instead
1061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            feParams.inversion = INVERSION_OFF;
1071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (ioctl(mFeFd, FE_SET_FRONTEND, &feParams) != 0) {
1111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGD("Can't set Frontend : %s", strerror(errno));
1121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
1131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int lockSuccessCount = 0;
1161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    double tuneClock = currentTimeMillis();
1171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    while (currentTimeMillis() - tuneClock < timeout_ms) {
11865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mHasPendingTune) {
11965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            // Return 0 here since we already call FE_SET_FRONTEND, and return due to having pending
12065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            // tune request. And the frontend setting could be successful.
12165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mFeHasLock = true;
12265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            return 0;
12365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
1241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        bool lockStatus = isFeLocked();
1251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (lockStatus) {
1261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            lockSuccessCount++;
1271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        } else {
1281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            lockSuccessCount = 0;
1291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGI("Lock status : %s", lockStatus ? "true" : "false");
1311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (lockSuccessCount >= FE_CONSECUTIVE_LOCK_SUCCESS_COUNT) {
1321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mFeHasLock = true;
1331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            openDvbDvr(env, thiz);
1341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            return 0;
1351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return -1;
1391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
1401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1411abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::stopTune() {
1421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    reset();
1431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    usleep(DVB_TUNE_STOP_DELAY_MS);
1441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return 0;
1451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
1461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1471abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::openDvbFeFromSystemApi(JNIEnv *env, jobject thiz) {
1481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int fd = (int) env->CallIntMethod(thiz, mOpenDvbFrontEndMethodID);
1491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
1501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return fd;
1511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
1521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1531abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::openDvbDemuxFromSystemApi(JNIEnv *env, jobject thiz) {
1541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int fd = (int) env->CallIntMethod(thiz, mOpenDvbDemuxMethodID);
1551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
1561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return fd;
1571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
1581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1591abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::openDvbDvrFromSystemApi(JNIEnv *env, jobject thiz) {
1601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int fd = (int) env->CallIntMethod(thiz, mOpenDvbDvrMethodID);
1611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
1621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return fd;
1631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
1641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1651abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::openDvbFe(JNIEnv *env, jobject thiz) {
1661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mFeFd == -1) {
1671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if ((mFeFd = openDvbFeFromSystemApi(env, thiz)) < 0) {
1681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            ALOGD("Can't open FE file : %s", strerror(errno));
1691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            return -1;
1701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    struct dvb_frontend_info info;
1741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (ioctl(mFeFd, FE_GET_INFO, &info) == 0) {
1751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        const char *types;
1761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        switch (info.type) {
1771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            case FE_QPSK:
1781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                types = "DVB-S";
1791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                break;
1801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            case FE_QAM:
1811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                types = "DVB-C";
1821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                break;
1831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            case FE_OFDM:
1841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                types = "DVB-T";
1851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                break;
1861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            case FE_ATSC:
1871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                types = "ATSC";
1881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                break;
1891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            default:
1901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                types = "Unknown";
1911abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGI("Using frontend \"%s\", type %s", info.name, types);
1931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return 0;
1951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
1961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1971abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::startTsPidFilter(JNIEnv *env, jobject thiz, int pid, int filterType) {
1981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    Mutex::Autolock autoLock(mFilterLock);
1991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mPidFilters.find(pid) != mPidFilters.end() || (mPatFilterFd != -1 && pid == PAT_PID)) {
2011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return 0;
2021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
20465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    if (mHasPendingTune) {
20565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return -1;
20665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
20765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
2081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int demuxFd;
2091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if ((demuxFd = openDvbDemuxFromSystemApi(env, thiz)) < 0) {
2101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGD("Can't open DEMUX file : %s", strerror(errno));
2111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
2121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    struct dmx_pes_filter_params filter;
2151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    memset(&filter, 0, sizeof(filter));
2161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    filter.pid = pid;
2171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    filter.input = DMX_IN_FRONTEND;
2181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    switch (filterType) {
2191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        case FILTER_TYPE_AUDIO:
2201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            filter.pes_type = DMX_PES_AUDIO;
2211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            break;
2221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        case FILTER_TYPE_VIDEO:
2231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            filter.pes_type = DMX_PES_VIDEO;
2241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            break;
2251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        case FILTER_TYPE_PCR:
2261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            filter.pes_type = DMX_PES_PCR;
2271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            break;
2281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        default:
2291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            filter.pes_type = DMX_PES_OTHER;
2301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            break;
2311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    filter.output = DMX_OUT_TS_TAP;
2331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    filter.flags |= (DMX_CHECK_CRC | DMX_IMMEDIATE_START);
2341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    // create a pes filter
2361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (ioctl(demuxFd, DMX_SET_PES_FILTER, &filter)) {
2371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        close(demuxFd);
2381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
2391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (pid != PAT_PID) {
2421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPidFilters.insert(std::pair<int, int>(pid, demuxFd));
2431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    } else {
2441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPatFilterFd = demuxFd;
2451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return 0;
2481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2501abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::closeAllDvbPidFilter() {
2511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    // Close all dvb pid filters except PAT filter to maintain the opening status of the device.
2521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    Mutex::Autolock autoLock(mFilterLock);
2531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    for (std::map<int, int>::iterator it(mPidFilters.begin());
2551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                it != mPidFilters.end(); it++) {
2561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        close(it->second);
2571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mPidFilters.clear();
25965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    // Close mDvrFd to make sure there is not buffer from previous channel left.
26065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    closeDvbDvr();
2611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2631abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::closePatFilter() {
2641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    Mutex::Autolock autoLock(mFilterLock);
2651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mPatFilterFd != -1) {
2671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        close(mPatFilterFd);
2681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPatFilterFd = -1;
2691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2721abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::openDvbDvr(JNIEnv *env, jobject thiz) {
2731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if ((mDvrFd = openDvbDvrFromSystemApi(env, thiz)) < 0) {
2741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGD("Can't open DVR file : %s", strerror(errno));
2751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
2761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return 0;
2781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2801abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::closeDvbFe() {
2811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mFeFd != -1) {
2821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        close(mFeFd);
2831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mFeFd = -1;
2841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2871abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::closeDvbDvr() {
2881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mDvrFd != -1) {
2891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        close(mDvrFd);
2901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mDvrFd = -1;
2911abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
2931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2941abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::reset() {
2951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mFeHasLock = false;
2961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closeDvbDvr();
2971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closeAllDvbPidFilter();
2981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closePatFilter();
2991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closeDvbFe();
3001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
3011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3021abddd9f6225298066094e20a6c29061b6af4590Nick Chalkovoid DvbManager::resetExceptFe() {
3031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    mFeHasLock = false;
3041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closeDvbDvr();
3051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closeAllDvbPidFilter();
3061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    closePatFilter();
3071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
3081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3091abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoint DvbManager::readTsStream(JNIEnv *env, jobject thiz,
3101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        uint8_t *tsBuffer, int tsBufferSize, int timeout_ms) {
3111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (!mFeHasLock) {
3121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        usleep(DVB_ERROR_RETRY_INTERVAL_MS);
3131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
3141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (mDvrFd == -1) {
3171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        openDvbDvr(env, thiz);
3181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    struct pollfd pollFd;
3211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    pollFd.fd = mDvrFd;
3221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    pollFd.events = POLLIN|POLLPRI|POLLERR;
3231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    pollFd.revents = 0;
3241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    int poll_result = poll(&pollFd, NUM_POLLFDS, timeout_ms);
3251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    if (poll_result == 0) {
3261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return 0;
3271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    } else if (poll_result == -1 || pollFd.revents & POLLERR) {
3281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ALOGD("Can't read DVR : %s", strerror(errno));
3291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        // TODO: Find how to recover this situation correctly.
3301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        closeDvbDvr();
3311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        usleep(DVB_ERROR_RETRY_INTERVAL_MS);
3321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return -1;
3331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    return read(mDvrFd, tsBuffer, tsBufferSize);
3351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
33665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
33765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkovoid DvbManager::setHasPendingTune(bool hasPendingTune) {
33865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    mHasPendingTune = hasPendingTune;
33965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko}
340