aboutsummaryrefslogtreecommitdiff
path: root/jni/DvbManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'jni/DvbManager.cpp')
-rw-r--r--jni/DvbManager.cpp233
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