diff options
Diffstat (limited to 'jni/DvbManager.cpp')
-rw-r--r-- | jni/DvbManager.cpp | 233 |
1 files changed, 197 insertions, 36 deletions
diff --git a/jni/DvbManager.cpp b/jni/DvbManager.cpp index aa4ed530..941a1fa7 100644 --- a/jni/DvbManager.cpp +++ b/jni/DvbManager.cpp @@ -42,6 +42,8 @@ DvbManager::DvbManager(JNIEnv *env, jobject) mDemuxFd(-1), mDvrFd(-1), mPatFilterFd(-1), + mDvbApiVersion(DVB_API_VERSION_UNDEFINED), + mDeliverySystemType(-1), mFeHasLock(false), mHasPendingTune(false) { jclass clazz = env->FindClass( @@ -59,16 +61,26 @@ DvbManager::~DvbManager() { } bool DvbManager::isFeLocked() { - struct pollfd pollFd; - pollFd.fd = mFeFd; - pollFd.events = POLLIN; - pollFd.revents = 0; - int poll_result = poll(&pollFd, NUM_POLLFDS, FE_POLL_TIMEOUT_MS); - if (poll_result > 0 && (pollFd.revents & POLLIN)) { - struct dvb_frontend_event kevent; - memset(&kevent, 0, sizeof(kevent)); - if (ioctl(mFeFd, FE_GET_EVENT, &kevent) == 0) { - return (kevent.status & FE_HAS_LOCK); + if (mDvbApiVersion == DVB_API_VERSION5) { + fe_status_t status; + if (ioctl(mFeFd, FE_READ_STATUS, &status) < 0) { + return false; + } + if (status & FE_HAS_LOCK) { + return true; + } + } else { + struct pollfd pollFd; + pollFd.fd = mFeFd; + pollFd.events = POLLIN; + pollFd.revents = 0; + int poll_result = poll(&pollFd, NUM_POLLFDS, FE_POLL_TIMEOUT_MS); + if (poll_result > 0 && (pollFd.revents & POLLIN)) { + struct dvb_frontend_event kevent; + memset(&kevent, 0, sizeof(kevent)); + if (ioctl(mFeFd, FE_GET_EVENT, &kevent) == 0) { + return (kevent.status & FE_HAS_LOCK); + } } } return false; @@ -78,38 +90,111 @@ int DvbManager::tune(JNIEnv *env, jobject thiz, const int frequency, const char *modulationStr, int timeout_ms) { resetExceptFe(); - struct dvb_frontend_parameters feParams; - memset(&feParams, 0, sizeof(struct dvb_frontend_parameters)); - feParams.frequency = frequency; - if (strcmp(modulationStr, "8VSB") == 0) { - feParams.u.vsb.modulation = VSB_8; - } else if (strcmp(modulationStr, "QAM256") == 0) { - feParams.u.vsb.modulation = QAM_256; - } else { - ALOGE("Unrecognized modulation mode : %s", modulationStr); - return -1; - } - - if (mHasPendingTune) { - return -1; - } if (openDvbFe(env, thiz) != 0) { return -1; } - - feParams.inversion = INVERSION_AUTO; - /* Check frontend capability */ - struct dvb_frontend_info feInfo; - if (ioctl(mFeFd, FE_GET_INFO, &feInfo) != -1) { - if (!(feInfo.caps & FE_CAN_INVERSION_AUTO)) { - // FE can't do INVERSION_AUTO, trying INVERSION_OFF instead - feParams.inversion = INVERSION_OFF; + if (mDvbApiVersion == DVB_API_VERSION_UNDEFINED) { + struct dtv_property testProps[1] = { + { .cmd = DTV_DELIVERY_SYSTEM } + }; + struct dtv_properties feProp = { + .num = 1, .props = testProps + }; + // On fugu, DVB_API_VERSION is 5 but it doesn't support FE_SET_PROPERTY. Checking the device + // support FE_GET_PROPERTY or not to determine the DVB API version is greater than 5 or not. + if (ioctl(mFeFd, FE_GET_PROPERTY, &feProp) == -1) { + ALOGD("FE_GET_PROPERTY failed, %s", strerror(errno)); + mDvbApiVersion = DVB_API_VERSION3; + } else { + mDvbApiVersion = DVB_API_VERSION5; } } - if (ioctl(mFeFd, FE_SET_FRONTEND, &feParams) != 0) { - ALOGD("Can't set Frontend : %s", strerror(errno)); - return -1; + if (mDvbApiVersion == DVB_API_VERSION5) { + struct dtv_property deliverySystemProperty = { + .cmd = DTV_DELIVERY_SYSTEM, .u.data = SYS_ATSC + }; + struct dtv_property frequencyProperty = { + .cmd = DTV_FREQUENCY, .u.data = frequency + }; + struct dtv_property modulationProperty = { .cmd = DTV_MODULATION }; + if (strncmp(modulationStr, "QAM", 3) == 0) { + modulationProperty.u.data = QAM_AUTO; + } else if (strcmp(modulationStr, "8VSB") == 0) { + modulationProperty.u.data = VSB_8; + } else { + ALOGE("Unrecognized modulation mode : %s", modulationStr); + return -1; + } + struct dtv_property tuneProperty = { .cmd = DTV_TUNE }; + + struct dtv_property props[] = { + deliverySystemProperty, frequencyProperty, modulationProperty, tuneProperty + }; + struct dtv_properties dtvProperty = { + .num = 4, .props = props + }; + + if (mHasPendingTune) { + return -1; + } + if (ioctl(mFeFd, FE_SET_PROPERTY, &dtvProperty) != 0) { + ALOGD("Can't set Frontend : %s", strerror(errno)); + return -1; + } + } else { + struct dvb_frontend_parameters feParams; + memset(&feParams, 0, sizeof(struct dvb_frontend_parameters)); + feParams.frequency = frequency; + feParams.inversion = INVERSION_AUTO; + /* Check frontend capability */ + struct dvb_frontend_info feInfo; + if (ioctl(mFeFd, FE_GET_INFO, &feInfo) != -1) { + if (!(feInfo.caps & FE_CAN_INVERSION_AUTO)) { + // FE can't do INVERSION_AUTO, trying INVERSION_OFF instead + feParams.inversion = INVERSION_OFF; + } + } + switch (feInfo.type) { + case FE_ATSC: + if (strcmp(modulationStr, "8VSB") == 0) { + feParams.u.vsb.modulation = VSB_8; + } else if (strncmp(modulationStr, "QAM", 3) == 0) { + feParams.u.vsb.modulation = QAM_AUTO; + } else { + ALOGE("Unrecognized modulation mode : %s", modulationStr); + return -1; + } + break; + case FE_OFDM: + if (strcmp(modulationStr, "8VSB") == 0) { + feParams.u.ofdm.constellation = VSB_8; + } else if (strcmp(modulationStr, "QAM16") == 0) { + feParams.u.ofdm.constellation = QAM_16; + } else if (strcmp(modulationStr, "QAM64") == 0) { + feParams.u.ofdm.constellation = QAM_64; + } else if (strcmp(modulationStr, "QAM256") == 0) { + feParams.u.ofdm.constellation = QAM_256; + } else if (strcmp(modulationStr, "QPSK") == 0) { + feParams.u.ofdm.constellation = QPSK; + } else { + ALOGE("Unrecognized modulation mode : %s", modulationStr); + return -1; + } + break; + default: + ALOGE("Unsupported delivery system."); + return -1; + } + + if (mHasPendingTune) { + return -1; + } + + if (ioctl(mFeFd, FE_SET_FRONTEND, &feParams) != 0) { + ALOGD("Can't set Frontend : %s", strerror(errno)); + return -1; + } } int lockSuccessCount = 0; @@ -238,6 +323,10 @@ int DvbManager::startTsPidFilter(JNIEnv *env, jobject thiz, int pid, int filterT return -1; } + if (mDvbApiVersion == DVB_API_VERSION5) { + ioctl(demuxFd, DMX_START, 0); + } + if (pid != PAT_PID) { mPidFilters.insert(std::pair<int, int>(pid, demuxFd)); } else { @@ -337,3 +426,75 @@ int DvbManager::readTsStream(JNIEnv *env, jobject thiz, void DvbManager::setHasPendingTune(bool hasPendingTune) { mHasPendingTune = hasPendingTune; } + +int DvbManager::getDeliverySystemType(JNIEnv *env, jobject thiz) { + if (mDeliverySystemType != -1) { + return mDeliverySystemType; + } + if (mFeFd == -1) { + if ((mFeFd = openDvbFeFromSystemApi(env, thiz)) < 0) { + ALOGD("Can't open FE file : %s", strerror(errno)); + return DELIVERY_SYSTEM_UNDEFINED; + } + } + struct dtv_property testProps[1] = { + { .cmd = DTV_DELIVERY_SYSTEM } + }; + struct dtv_properties feProp = { + .num = 1, .props = testProps + }; + mDeliverySystemType = DELIVERY_SYSTEM_UNDEFINED; + if (ioctl(mFeFd, FE_GET_PROPERTY, &feProp) == -1) { + mDvbApiVersion = DVB_API_VERSION3; + if (openDvbFe(env, thiz) == 0) { + struct dvb_frontend_info info; + if (ioctl(mFeFd, FE_GET_INFO, &info) == 0) { + switch (info.type) { + case FE_QPSK: + mDeliverySystemType = DELIVERY_SYSTEM_DVBS; + break; + case FE_QAM: + mDeliverySystemType = DELIVERY_SYSTEM_DVBC; + break; + case FE_OFDM: + mDeliverySystemType = DELIVERY_SYSTEM_DVBT; + break; + case FE_ATSC: + mDeliverySystemType = DELIVERY_SYSTEM_ATSC; + break; + default: + mDeliverySystemType = DELIVERY_SYSTEM_UNDEFINED; + break; + } + } + } + } else { + mDvbApiVersion = DVB_API_VERSION5; + switch (feProp.props[0].u.data) { + case SYS_DVBT: + mDeliverySystemType = DELIVERY_SYSTEM_DVBT; + break; + case SYS_DVBT2: + mDeliverySystemType = DELIVERY_SYSTEM_DVBT2; + break; + case SYS_DVBS: + mDeliverySystemType = DELIVERY_SYSTEM_DVBS; + break; + case SYS_DVBS2: + mDeliverySystemType = DELIVERY_SYSTEM_DVBS2; + break; + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_B: + case SYS_DVBC_ANNEX_C: + mDeliverySystemType = DELIVERY_SYSTEM_DVBC; + break; + case SYS_ATSC: + mDeliverySystemType = DELIVERY_SYSTEM_ATSC; + break; + default: + mDeliverySystemType = DELIVERY_SYSTEM_UNDEFINED; + break; + } + } + return mDeliverySystemType; +}
\ No newline at end of file |