/* * Copyright (c) 2021 Amlogic, Inc. All rights reserved. * * This source code is subject to the terms and conditions defined in the * file 'LICENSE' which is part of this source code package. * * Description: */ #define LOG_TAG "AmCasLibWrapper" #include "cas/AmCasLibWrapper.h" #include #include #include namespace aml_mp { template typename AmCasLibWrapper::CasSymbols AmCasLibWrapper::sCasSymbols; template void* AmCasLibWrapper::sCasHandle; template std::once_flag AmCasLibWrapper::sLoadCasLibFlag; template AmCasLibWrapper::AmCasLibWrapper(const char *libName) { snprintf(mName, sizeof(mName), "%s", LOG_TAG); std::call_once(sLoadCasLibFlag, [libName] { loadLib(libName); }); if (!sCasSymbols.createAmCas) { return; } AmCasStatus_t ret = sCasSymbols.createAmCas(&mCasObj); if (ret != CAS_STATUS_OK) { MLOGE("createAmCas failed"); } } template AmCasLibWrapper::~AmCasLibWrapper() { MLOG(); if (mCasObj) { if (!sCasSymbols.releaseAmCas) { MLOGW("releaseAmCas is nullptr, CHECK!"); free(mCasObj); } else if (sCasSymbols.releaseAmCas(mCasObj) != CAS_STATUS_OK) { MLOGE("releaseAmCas failed"); } } } template AmCasCode_t AmCasLibWrapper::setCasInstanceId(int casInstanceId) { if (!sCasSymbols.setCasInstanceId) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.setCasInstanceId(mCasObj, casInstanceId); if (ret != CAS_STATUS_OK) { MLOGE("setCasInstanceId failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template int AmCasLibWrapper::getCasInstanceId() { if (!sCasSymbols.getCasInstanceId) { return -1; } return sCasSymbols.getCasInstanceId(mCasObj); } template AmCasCode_t AmCasLibWrapper::setPrivateData(void *iDate, int iSize) { if (!sCasSymbols.setPrivateData) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.setPrivateData(mCasObj, iDate, iSize); if (ret != CAS_STATUS_OK) { MLOGE("setPrivateData failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template AmCasCode_t AmCasLibWrapper::provision() { if (!sCasSymbols.provision) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.provision(mCasObj); if (ret != CAS_STATUS_OK) { MLOGE("provision failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template AmCasCode_t AmCasLibWrapper::openSession(uint8_t *sessionId) { if (!sCasSymbols.openSession) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.openSession(mCasObj, sessionId); if (ret != CAS_STATUS_OK) { MLOGE("openSession failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template AmCasCode_t AmCasLibWrapper::closeSession(uint8_t *sessionId) { if (!sCasSymbols.closeSession) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.closeSession(mCasObj, sessionId); if (ret != CAS_STATUS_OK) { MLOGE("closeSession failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template AmCasCode_t AmCasLibWrapper::setPids(int vPid, int aPid) { if (!sCasSymbols.setPids) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.setPids(mCasObj, vPid, aPid); if (ret != CAS_STATUS_OK) { MLOGE("setPids failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template AmCasCode_t AmCasLibWrapper::selectTrack(int trackType, int trackPid, int trackFormat) { if (!sCasSymbols.selectTrack) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.selectTrack(mCasObj, trackType, trackPid, trackFormat); if (ret != CAS_STATUS_OK) { MLOGE("selectTrack failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template AmCasCode_t AmCasLibWrapper::processEcm(int isSection, int isVideoEcm, int vEcmPid, int aEcmPid, uint8_t *pBuffer, int iBufferLength) { if (!sCasSymbols.processEcm) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.processEcm(mCasObj, isSection, isVideoEcm, vEcmPid, aEcmPid, pBuffer, iBufferLength); if (ret != CAS_STATUS_OK) { MLOGE("processEcm failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template AmCasCode_t AmCasLibWrapper::processEmm(int isSection, int iPid, uint8_t *pBuffer, int iBufferLength) { if (!sCasSymbols.processEmm) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.processEmm(mCasObj, isSection, iPid, pBuffer, iBufferLength); if (ret != CAS_STATUS_OK) { MLOGE("processEmm failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template AmCasCode_t AmCasLibWrapper::decrypt(uint8_t *in, uint8_t *out, int size, void *ext_data) { if (!sCasSymbols.decrypt) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.decrypt(mCasObj, in, out, size, ext_data); if (ret != CAS_STATUS_OK) { MLOGE("decrypt failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template uint8_t* AmCasLibWrapper::getOutbuffer() { if (!sCasSymbols.getOutbuffer) { return nullptr; } return sCasSymbols.getOutbuffer(mCasObj); } template void AmCasLibWrapper::loadLib(const char *libName) { sCasHandle = dlopen(libName, RTLD_NOW); if (!sCasHandle) { ALOGE("%s dlopen failed because of: %s", libName, dlerror()); } else { ALOGI("%s dlopen success, sCasHandle:%p", libName, sCasHandle); } sCasSymbols.createAmCas = lookupSymbol("createAmCas"); sCasSymbols.setCasInstanceId = lookupSymbol("setCasInstanceId"); sCasSymbols.getCasInstanceId = lookupSymbol("getCasInstanceId"); sCasSymbols.setPrivateData = lookupSymbol("setPrivateData"); sCasSymbols.provision = lookupSymbol("provision"); sCasSymbols.setPids = lookupSymbol("setPids"); sCasSymbols.processEcm = lookupSymbol("processEcm"); sCasSymbols.processEmm = lookupSymbol("processEmm"); sCasSymbols.decrypt = lookupSymbol("decrypt"); sCasSymbols.getOutbuffer = lookupSymbol("getOutbuffer"); sCasSymbols.openSession = lookupSymbol("openSession"); sCasSymbols.closeSession = lookupSymbol("closeSession"); sCasSymbols.releaseAll = lookupSymbol("releaseAll"); sCasSymbols.selectTrack = lookupSymbol("selectTrack"); sCasSymbols.releaseAmCas = lookupSymbol("releaseAmCas"); sCasSymbols.getChipID = lookupSymbol("getChipID"); sCasSymbols.getCAVersion = lookupSymbol("getCAVersion"); sCasSymbols.setCasEventCallback = lookupSymbol("setCasEventCallback"); } template AmCasCode_t AmCasLibWrapper::releaseAll() { if (!sCasSymbols.releaseAll) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.releaseAll(mCasObj); if (ret != CAS_STATUS_OK) { ALOGE("releaseAll failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template AmCasCode_t AmCasLibWrapper::releaseAmCas() { if (!sCasSymbols.releaseAmCas) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.releaseAmCas(mCasObj); if (ret != CAS_STATUS_OK) { ALOGE("releaseAmCas failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template void AmCasLibWrapper::releaseLib() { dlclose(sCasHandle); sCasHandle = nullptr; } template template F AmCasLibWrapper::lookupSymbol(const char *symbolName) { F func = (F)dlsym(sCasHandle, symbolName); if (func == nullptr) { ALOGW("dlsym for %s failed, %s", symbolName, dlerror()); } return func; } template AmCasCode_t AmCasLibWrapper::getChipID(char* chipid) { if (!sCasSymbols.getChipID) { return AM_CAS_ERROR; } AmCasStatus_t ret = sCasSymbols.getChipID(chipid); if (ret != CAS_STATUS_OK) { MLOGE("getChipID failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template const char* AmCasLibWrapper::getCAVersion() { if (!sCasSymbols.getCAVersion) { return nullptr; } return sCasSymbols.getCAVersion(mCasObj); } template AmCasCode_t AmCasLibWrapper::setCasEventCallback(Aml_MP_CAS_EventCallback callback, void* pUserData) { if (!sCasSymbols.setCasEventCallback) { return AM_CAS_ERROR; } FCAS_EventFunction_t eventFn = reinterpret_cast(callback); AmCasStatus_t ret = sCasSymbols.setCasEventCallback(eventFn, pUserData); if (ret != CAS_STATUS_OK) { MLOGE("setCasEventCallback failed"); return AM_CAS_ERROR; } return AM_CAS_SUCCESS; } template class AmCasLibWrapper; template class AmCasLibWrapper; template class AmCasLibWrapper; template class AmCasLibWrapper; }