394 lines
10 KiB
C++
394 lines
10 KiB
C++
/*
|
|||
|
|
* Copyright (c) 2020 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_NDEBUG 0
|
||
|
|
#define LOG_TAG "AmlMpCAS"
|
||
|
|
#include <Aml_MP/Cas.h>
|
||
|
|
#include "AmlDvbCasHal.h"
|
||
|
|
#include <utils/AmlMpHandle.h>
|
||
|
|
#include <utils/AmlMpUtils.h>
|
||
|
|
#include "cas/AmlCasBase.h"
|
||
|
|
#ifdef HAVE_VMX_IPTV_MEDIA_CAS
|
||
|
|
#include "cas/vmx_iptvcas/AmlVMXIptvMediaCas.h"
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static const char* mName = LOG_TAG;
|
||
|
|
|
||
|
|
using namespace aml_mp;
|
||
|
|
//using namespace android;
|
||
|
|
|
||
|
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
//global CAS functions
|
||
|
|
pthread_once_t g_dvbCasInitFlag = PTHREAD_ONCE_INIT;
|
||
|
|
#ifdef HAVE_CAS_HAL
|
||
|
|
CasHandle g_casHandle = 0;
|
||
|
|
|
||
|
|
static AM_CA_SECTION convertToCASection(Aml_MP_CASSectionType casSection)
|
||
|
|
{
|
||
|
|
switch (casSection) {
|
||
|
|
case AML_MP_CAS_SECTION_PMT:
|
||
|
|
return AM_CA_SECTION_PMT;
|
||
|
|
|
||
|
|
case AML_MP_CAS_SECTION_CAT:
|
||
|
|
return AM_CA_SECTION_CAT;
|
||
|
|
|
||
|
|
case AML_MP_CAS_SECTION_NIT:
|
||
|
|
return AM_CA_SECTION_NIT;
|
||
|
|
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return AM_CA_SECTION_PMT;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int convertToAmlMPErrorCode(AM_RESULT CasResult) {
|
||
|
|
switch (CasResult) {
|
||
|
|
case AM_ERROR_SUCCESS:
|
||
|
|
return AML_MP_OK;
|
||
|
|
case AM_ERROR_NOT_LOAD:
|
||
|
|
return AML_MP_ERROR_BAD_INDEX;
|
||
|
|
case AM_ERROR_NOT_SUPPORTED:
|
||
|
|
return AML_MP_ERROR_BAD_TYPE;
|
||
|
|
case AM_ERROR_OVERFLOW:
|
||
|
|
return AML_MP_ERROR_NO_MEMORY;
|
||
|
|
default:
|
||
|
|
return AML_MP_ERROR;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef __cplusplus
|
||
|
|
extern "C" {
|
||
|
|
#endif
|
||
|
|
|
||
|
|
int Aml_MP_CAS_Initialize()
|
||
|
|
{
|
||
|
|
MLOG();
|
||
|
|
|
||
|
|
#ifdef HAVE_CAS_HAL
|
||
|
|
pthread_once(&g_dvbCasInitFlag, [] {
|
||
|
|
AM_CA_Init(&g_casHandle);
|
||
|
|
});
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef HAVE_VMX_IPTV_MEDIA_CAS
|
||
|
|
PreInitVmxMediaCas();
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return AML_MP_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_Terminate()
|
||
|
|
{
|
||
|
|
MLOG();
|
||
|
|
|
||
|
|
int ret = AML_MP_ERROR;
|
||
|
|
|
||
|
|
#ifdef HAVE_CAS_HAL
|
||
|
|
//coverity[value_overwrite]
|
||
|
|
ret = convertToAmlMPErrorCode(AM_CA_Term(g_casHandle));
|
||
|
|
|
||
|
|
g_casHandle = 0;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef HAVE_VMX_IPTV_MEDIA_CAS
|
||
|
|
DeinitVmxMediaCas();
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_IsNeedWholeSection()
|
||
|
|
{
|
||
|
|
int ret = AML_MP_ERROR;
|
||
|
|
|
||
|
|
#ifdef HAVE_CAS_HAL
|
||
|
|
//coverity[value_overwrite]
|
||
|
|
ret = AM_CA_IsNeedWholeSection();
|
||
|
|
#endif
|
||
|
|
|
||
|
|
MLOG("isNeedWholeSection = %d", ret);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_IsSystemIdSupported(int caSystemId)
|
||
|
|
{
|
||
|
|
bool ret = false;
|
||
|
|
|
||
|
|
#ifdef HAVE_CAS_HAL
|
||
|
|
//coverity[value_overwrite]
|
||
|
|
ret = AM_CA_IsSystemIdSupported(caSystemId);
|
||
|
|
#else
|
||
|
|
AML_MP_UNUSED(caSystemId);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_ReportSection(Aml_MP_CASSectionReportAttr* pAttr, uint8_t* data, size_t len)
|
||
|
|
{
|
||
|
|
MLOG("dmx_dev:%d, service_id:%d", pAttr->dmxDev, pAttr->serviceId);
|
||
|
|
|
||
|
|
int ret = AML_MP_ERROR;
|
||
|
|
#ifdef HAVE_CAS_HAL
|
||
|
|
AM_CA_SecAttr_t attr;
|
||
|
|
|
||
|
|
attr.dmx_dev = pAttr->dmxDev;
|
||
|
|
attr.service_id = pAttr->serviceId;
|
||
|
|
attr.section_type = convertToCASection(pAttr->sectionType);
|
||
|
|
|
||
|
|
//coverity[value_overwrite]
|
||
|
|
ret = convertToAmlMPErrorCode(AM_CA_ReportSection(&attr, data, len));
|
||
|
|
#else
|
||
|
|
AML_MP_UNUSED(data);
|
||
|
|
AML_MP_UNUSED(len);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_SetEmmPid(int dmxDev, uint16_t emmPid)
|
||
|
|
{
|
||
|
|
MLOG("dmxDev:%d, emmPid:%d", dmxDev, emmPid);
|
||
|
|
|
||
|
|
int ret = AML_MP_ERROR;
|
||
|
|
#ifdef HAVE_CAS_HAL
|
||
|
|
RETURN_IF(-1, g_casHandle == 0);
|
||
|
|
|
||
|
|
//coverity[value_overwrite]
|
||
|
|
ret = convertToAmlMPErrorCode(AM_CA_SetEmmPid(g_casHandle, dmxDev, emmPid));
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_OpenSession(AML_MP_CASSESSION* casSession, Aml_MP_CASServiceType serviceType)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = AmlCasBase::create(serviceType);
|
||
|
|
if (!casBase) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
casBase->incStrong(casBase.get());
|
||
|
|
|
||
|
|
*casSession = aml_handle_cast(casBase);
|
||
|
|
return AML_MP_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_CloseSession(AML_MP_CASSESSION casSession)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
casBase->decStrong(casSession);
|
||
|
|
|
||
|
|
return AML_MP_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_RegisterEventCallback(AML_MP_CASSESSION casSession, Aml_MP_CAS_EventCallback cb, void* userData)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
int ret = AML_MP_OK;
|
||
|
|
|
||
|
|
if (casBase) {
|
||
|
|
ret = casBase->registerEventCallback(cb, userData);
|
||
|
|
} else {
|
||
|
|
#ifdef HAVE_CAS_HAL
|
||
|
|
CAS_EventFunction_t eventFn = reinterpret_cast<CAS_EventFunction_t>(cb);
|
||
|
|
ret = AM_CA_RegisterEventCallback((CasSession)nullptr, eventFn);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_Ioctl(AML_MP_CASSESSION casSession, const char* inJson, char* outJson, uint32_t outLen)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
int ret = AML_MP_OK;
|
||
|
|
|
||
|
|
if (casBase) {
|
||
|
|
ret = casBase->ioctl(inJson, outJson, outLen);
|
||
|
|
} else {
|
||
|
|
#ifdef HAVE_CAS_HAL
|
||
|
|
ret = AM_CA_Ioctl((CasSession)nullptr, inJson, outJson, outLen);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_StartDescrambling(AML_MP_CASSESSION casSession, Aml_MP_CASServiceInfo* serviceInfo)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->startDescrambling(serviceInfo);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_StartDescramblingIPTV(AML_MP_CASSESSION casSession, const Aml_MP_IptvCASParams* params)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casIptv = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casIptv == nullptr);
|
||
|
|
|
||
|
|
return casIptv->startDescrambling(params);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_StopDescrambling(AML_MP_CASSESSION casSession)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->stopDescrambling();
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_UpdateDescramblingPid(AML_MP_CASSESSION casSession, int oldStreamPid, int newStreamPid)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->updateDescramblingPid(oldStreamPid, newStreamPid);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_SwitchAudioTrack(AML_MP_CASSESSION casSession, Aml_MP_AudioParams* params)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->switchAudioTrack(params);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_StartDVRRecord(AML_MP_CASSESSION casSession, Aml_MP_CASServiceInfo *serviceInfo)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->startDVRRecord(serviceInfo);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_StopDVRRecord(AML_MP_CASSESSION casSession)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->stopDVRRecord();
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_StartDVRReplay(AML_MP_CASSESSION casSession, Aml_MP_CASDVRReplayParams *dvrReplayParams)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->startDVRReplay(dvrReplayParams);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_StopDVRReplay(AML_MP_CASSESSION casSession)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->stopDVRReplay();
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_DVRReplay(AML_MP_CASSESSION casSession, Aml_MP_CASCryptoParams* cryptoParams)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->dvrReplay(cryptoParams);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_DVREncrypt(AML_MP_CASSESSION casSession, Aml_MP_CASCryptoParams *cryptoParams)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->DVREncrypt(cryptoParams);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_DVRDecrypt(AML_MP_CASSESSION casSession, Aml_MP_CASCryptoParams *cryptoParams)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->DVRDecrypt(cryptoParams);
|
||
|
|
}
|
||
|
|
|
||
|
|
AML_MP_SECMEM Aml_MP_CAS_CreateSecmem(AML_MP_CASSESSION casSession, Aml_MP_CASServiceType type, void **pSecbuf, uint32_t *size)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(AML_MP_INVALID_HANDLE, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->createSecmem(type, pSecbuf, size);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_DestroySecmem(AML_MP_CASSESSION casSession, AML_MP_SECMEM secMem)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->destroySecmem(secMem);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_GetStoreRegion(AML_MP_CASSESSION casSession, Aml_MP_CASStoreRegion* region, uint8_t* regionCount)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->getStoreRegion(region, regionCount);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_ProcessEcmIPTV(AML_MP_CASSESSION casSession, bool isSection, int ecmPid, const uint8_t* data, size_t size)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
return casBase->processEcm(isSection, ecmPid, data, size);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_ProcessEmmIPTV(AML_MP_CASSESSION casSession, bool isSection, int emmPid, const uint8_t* data, size_t size)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
return casBase->processEmm(isSection, emmPid, data, size);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_DecryptIPTV(AML_MP_CASSESSION casSession, uint8_t* data, size_t size, void* ext_data, Aml_MP_Buffer* outbuffer)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
return casBase->decrypt(data, size, ext_data, outbuffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_GetChipId(AML_MP_CASSESSION casSession, char* chipid, size_t size)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->getChipID(chipid, size);
|
||
|
|
}
|
||
|
|
|
||
|
|
const char* Aml_MP_CAS_GetCAVersion(AML_MP_CASSESSION casSession)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(NULL, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->getCAVersion();
|
||
|
|
}
|
||
|
|
|
||
|
|
int Aml_MP_CAS_ProvisionIPTV(AML_MP_CASSESSION casSession, const Aml_MP_IptvCASParams* params)
|
||
|
|
{
|
||
|
|
sptr<AmlCasBase> casBase = aml_handle_cast<AmlCasBase>(casSession);
|
||
|
|
RETURN_IF(-1, casBase == nullptr);
|
||
|
|
|
||
|
|
return casBase->provision(params);
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef __cplusplus
|
||
|
|
}
|
||
|
|
#endif
|