338 lines
10 KiB
C++
338 lines
10 KiB
C++
/*
|
|||
|
|
* 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 <dlfcn.h>
|
||
|
|
#include <utils/AmlMpUtils.h>
|
||
|
|
#include <utils/AmlMpLog.h>
|
||
|
|
|
||
|
|
namespace aml_mp
|
||
|
|
{
|
||
|
|
|
||
|
|
template <Aml_MP_CASServiceType ServiceType>
|
||
|
|
typename AmCasLibWrapper<ServiceType>::CasSymbols AmCasLibWrapper<ServiceType>::sCasSymbols;
|
||
|
|
|
||
|
|
template <Aml_MP_CASServiceType ServiceType>
|
||
|
|
void* AmCasLibWrapper<ServiceType>::sCasHandle;
|
||
|
|
|
||
|
|
template <Aml_MP_CASServiceType ServiceType>
|
||
|
|
std::once_flag AmCasLibWrapper<ServiceType>::sLoadCasLibFlag;
|
||
|
|
|
||
|
|
template <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasLibWrapper<ServiceType>::~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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
int AmCasLibWrapper<ServiceType>::getCasInstanceId()
|
||
|
|
{
|
||
|
|
if (!sCasSymbols.getCasInstanceId) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
return sCasSymbols.getCasInstanceId(mCasObj);
|
||
|
|
}
|
||
|
|
|
||
|
|
template <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
uint8_t* AmCasLibWrapper<ServiceType>::getOutbuffer()
|
||
|
|
{
|
||
|
|
if (!sCasSymbols.getOutbuffer) {
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
return sCasSymbols.getOutbuffer(mCasObj);
|
||
|
|
}
|
||
|
|
|
||
|
|
template <Aml_MP_CASServiceType ServiceType>
|
||
|
|
void AmCasLibWrapper<ServiceType>::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<createAmCasFunc>("createAmCas");
|
||
|
|
sCasSymbols.setCasInstanceId = lookupSymbol<setCasInstanceIdFunc>("setCasInstanceId");
|
||
|
|
sCasSymbols.getCasInstanceId = lookupSymbol<getCasInstanceIdFunc>("getCasInstanceId");
|
||
|
|
sCasSymbols.setPrivateData = lookupSymbol<setPrivateDataFunc>("setPrivateData");
|
||
|
|
sCasSymbols.provision = lookupSymbol<provisionFunc>("provision");
|
||
|
|
sCasSymbols.setPids = lookupSymbol<setPidsFunc>("setPids");
|
||
|
|
sCasSymbols.processEcm = lookupSymbol<processEcmFunc>("processEcm");
|
||
|
|
sCasSymbols.processEmm = lookupSymbol<processEmmFunc>("processEmm");
|
||
|
|
sCasSymbols.decrypt = lookupSymbol<decryptFunc>("decrypt");
|
||
|
|
sCasSymbols.getOutbuffer = lookupSymbol<getOutbufferFunc>("getOutbuffer");
|
||
|
|
sCasSymbols.openSession = lookupSymbol<openSessionFunc>("openSession");
|
||
|
|
sCasSymbols.closeSession = lookupSymbol<closeSessionFunc>("closeSession");
|
||
|
|
sCasSymbols.releaseAll = lookupSymbol<releaseAllFunc>("releaseAll");
|
||
|
|
sCasSymbols.selectTrack = lookupSymbol<selectTrackFunc>("selectTrack");
|
||
|
|
sCasSymbols.releaseAmCas = lookupSymbol<releaseAmCasFunc>("releaseAmCas");
|
||
|
|
sCasSymbols.getChipID = lookupSymbol<getChipIDFunc>("getChipID");
|
||
|
|
sCasSymbols.getCAVersion = lookupSymbol<getCAVersionFunc>("getCAVersion");
|
||
|
|
sCasSymbols.setCasEventCallback = lookupSymbol<setCasEventCallbackFunc>("setCasEventCallback");
|
||
|
|
}
|
||
|
|
|
||
|
|
template <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
void AmCasLibWrapper<ServiceType>::releaseLib()
|
||
|
|
{
|
||
|
|
dlclose(sCasHandle);
|
||
|
|
sCasHandle = nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
template <Aml_MP_CASServiceType ServiceType>
|
||
|
|
template <typename F>
|
||
|
|
F AmCasLibWrapper<ServiceType>::lookupSymbol(const char *symbolName)
|
||
|
|
{
|
||
|
|
F func = (F)dlsym(sCasHandle, symbolName);
|
||
|
|
if (func == nullptr) {
|
||
|
|
ALOGW("dlsym for %s failed, %s", symbolName, dlerror());
|
||
|
|
}
|
||
|
|
|
||
|
|
return func;
|
||
|
|
}
|
||
|
|
|
||
|
|
template <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::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 <Aml_MP_CASServiceType ServiceType>
|
||
|
|
const char* AmCasLibWrapper<ServiceType>::getCAVersion()
|
||
|
|
{
|
||
|
|
if (!sCasSymbols.getCAVersion) {
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
return sCasSymbols.getCAVersion(mCasObj);
|
||
|
|
}
|
||
|
|
|
||
|
|
template <Aml_MP_CASServiceType ServiceType>
|
||
|
|
AmCasCode_t AmCasLibWrapper<ServiceType>::setCasEventCallback(Aml_MP_CAS_EventCallback callback, void* pUserData)
|
||
|
|
{
|
||
|
|
if (!sCasSymbols.setCasEventCallback) {
|
||
|
|
return AM_CAS_ERROR;
|
||
|
|
}
|
||
|
|
FCAS_EventFunction_t eventFn = reinterpret_cast<FCAS_EventFunction_t>(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<AML_MP_CAS_SERVICE_VERIMATRIX_IPTV>;
|
||
|
|
template class AmCasLibWrapper<AML_MP_CAS_SERVICE_VERIMATRIX_WEB>;
|
||
|
|
template class AmCasLibWrapper<AML_MP_CAS_SERVICE_NAGRA_WEB>;
|
||
|
|
template class AmCasLibWrapper<AML_MP_CAS_SERVICE_WIDEVINE>;
|
||
|
|
|
||
|
|
}
|