521 lines
15 KiB
C++
521 lines
15 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 "AmlMPDscDev"
|
|
|
|
#include <utils/AmlMpLog.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <sys/ioctl.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <pthread.h>
|
|
#include <Aml_MP/Aml_MP.h>
|
|
#include "AmlMPDscDev.h"
|
|
|
|
#define MAX_DSC_DEV 16
|
|
#define DEV_NAME "/dev/dvb0.ca"
|
|
|
|
static const char* mName = LOG_TAG;
|
|
|
|
namespace aml_mp {
|
|
|
|
struct _dsc_dev{
|
|
uint8_t used;
|
|
int fd;
|
|
};
|
|
typedef struct _dsc_dev dsc_dev;
|
|
static dsc_dev dvb_dsc_dev[MAX_DSC_DEV];
|
|
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
|
bool dsc_inited = false;
|
|
|
|
int ca_init(void)
|
|
{
|
|
pthread_mutex_lock(&lock);
|
|
|
|
if (!dsc_inited) {
|
|
MLOGI("ca dsc inited");
|
|
dsc_inited = true;
|
|
}
|
|
|
|
pthread_mutex_unlock(&lock);
|
|
|
|
return CA_DSC_OK;
|
|
}
|
|
|
|
int ca_open(int devno)
|
|
{
|
|
int fd;
|
|
char buf[32];
|
|
int32_t retry_open_times = 0;
|
|
|
|
if (devno >= MAX_DSC_DEV) {
|
|
MLOGE("ca_open failed! devno:%d\n", devno);
|
|
return CA_DSC_ERROR;
|
|
}
|
|
snprintf(buf, sizeof(buf), DEV_NAME"%d", devno);
|
|
|
|
pthread_mutex_lock(&lock);
|
|
if (dvb_dsc_dev[devno].used) {
|
|
MLOGI("ca_open dvb_dsc_dev[%d] has been used!", devno);
|
|
pthread_mutex_unlock(&lock);
|
|
return CA_DSC_OK;
|
|
}
|
|
pthread_mutex_unlock(&lock);
|
|
|
|
retry_open:
|
|
fd = open(buf, O_RDWR);
|
|
MLOGI("ca_open [%d] fd is %d", devno, fd);
|
|
if (fd == -1) {
|
|
retry_open_times++;
|
|
usleep(10000);
|
|
if (retry_open_times < 200) {
|
|
goto retry_open;
|
|
}
|
|
MLOGE("Cannot open %s%d (%d:%s), and will retry_open_times %d", DEV_NAME, devno, errno, strerror(errno), retry_open_times);
|
|
return CA_DSC_ERROR;
|
|
}
|
|
|
|
pthread_mutex_lock(&lock);
|
|
if (dvb_dsc_dev[devno].used) {
|
|
MLOGI("ca_open dvb_dsc_dev[%d] has been used!", devno);
|
|
close(fd);
|
|
} else {
|
|
dvb_dsc_dev[devno].fd = fd;
|
|
dvb_dsc_dev[devno].used = 1;
|
|
}
|
|
pthread_mutex_unlock(&lock);
|
|
|
|
return CA_DSC_OK;
|
|
}
|
|
|
|
int ca_alloc_chan(int devno, unsigned int pid, int algo, int dsc_type)
|
|
{
|
|
int ret, fd;
|
|
struct ca_sc2_descr_ex desc;
|
|
|
|
pthread_mutex_lock(&lock);
|
|
|
|
MLOGI("ca_alloc_chan dev:%d, pid:0x%0x, algo:%d, dsc_type:%d\n", devno, pid, algo, dsc_type);
|
|
memset(&desc, 0, sizeof(desc));
|
|
desc.cmd = CA_ALLOC;
|
|
desc.params.alloc_params.pid = pid;
|
|
desc.params.alloc_params.algo = (ca_sc2_algo_type)algo;
|
|
desc.params.alloc_params.dsc_type = (ca_sc2_dsc_type)dsc_type;
|
|
desc.params.alloc_params.ca_index = -1;
|
|
desc.params.alloc_params.loop = 0;
|
|
|
|
if (devno >= MAX_DSC_DEV) {
|
|
MLOGE("ca_alloc_chan failed! devno:%d\n", devno);
|
|
goto ERROR_EXIT;
|
|
}
|
|
|
|
if (!dvb_dsc_dev[devno].used) {
|
|
MLOGE("ca_alloc_chan failed! devno:%d used:%d\n", devno, dvb_dsc_dev[devno].used);
|
|
goto ERROR_EXIT;
|
|
}
|
|
fd = dvb_dsc_dev[devno].fd;
|
|
ret = ioctl(fd, CA_SC2_SET_DESCR_EX, &desc);
|
|
if (ret != 0) {
|
|
MLOGE(" ca_alloc_chan ioctl fail, ret:0x%0x\n", ret);
|
|
goto ERROR_EXIT;
|
|
}
|
|
|
|
pthread_mutex_unlock(&lock);
|
|
MLOGI("ca_alloc_chan, index:%d\n", desc.params.alloc_params.ca_index);
|
|
|
|
return desc.params.alloc_params.ca_index;
|
|
ERROR_EXIT:
|
|
pthread_mutex_unlock(&lock);
|
|
return CA_DSC_ERROR;
|
|
}
|
|
|
|
|
|
int ca_set_scb(int devno, int ca_index,int ca_scb, int ca_scb_as_is)
|
|
{
|
|
struct ca_sc2_descr_ex desc;
|
|
memset(&desc, 0, sizeof(desc));
|
|
pthread_mutex_lock(&lock);
|
|
|
|
if (devno >= MAX_DSC_DEV) {
|
|
MLOGE("ca_set_scb failed! devno:%d\n", devno);
|
|
pthread_mutex_unlock(&lock);
|
|
return CA_DSC_ERROR;
|
|
}
|
|
|
|
if (!dvb_dsc_dev[devno].used) {
|
|
MLOGE("ca_set_scb failed! devno:%d used:%d\n", devno, dvb_dsc_dev[devno].used);
|
|
pthread_mutex_unlock(&lock);
|
|
return CA_DSC_ERROR;
|
|
}
|
|
|
|
desc.cmd = CA_SET_SCB;
|
|
desc.params.scb_params.ca_index = ca_index;
|
|
desc.params.scb_params.ca_scb = ca_scb;
|
|
desc.params.scb_params.ca_scb_as_is = ca_scb_as_is;
|
|
int fd = dvb_dsc_dev[devno].fd;
|
|
int ret = ioctl(fd, CA_SC2_SET_DESCR_EX, &desc);
|
|
if (ret != 0) {
|
|
MLOGE("ca_set_scb ioctl fail, ret:0x%0x\n", ret);
|
|
pthread_mutex_unlock(&lock);
|
|
return CA_DSC_ERROR;
|
|
}
|
|
MLOGI("ca_set_scb ca_index:%d,ca_scb:%d,ca_scb_as_is:%d, ret:0x%0x\n", desc.params.scb_params.ca_index,desc.params.scb_params.ca_scb,desc.params.scb_params.ca_scb_as_is, ret);
|
|
pthread_mutex_unlock(&lock);
|
|
return CA_DSC_OK;
|
|
}
|
|
|
|
|
|
int ca_free_chan(int devno, int index)
|
|
{
|
|
int ret, fd;
|
|
struct ca_sc2_descr_ex desc;
|
|
|
|
pthread_mutex_lock(&lock);
|
|
|
|
MLOGI("ca_free_chan:%d, index:%d\n", devno, index);
|
|
desc.cmd = CA_FREE;
|
|
desc.params.free_params.ca_index = index;
|
|
|
|
if (devno >= MAX_DSC_DEV) {
|
|
MLOGE("ca_free_chan failed! devno:%d\n", devno);
|
|
goto ERROR_EXIT;
|
|
}
|
|
|
|
if (!dvb_dsc_dev[devno].used) {
|
|
MLOGE("ca_free_chan failed! devno:%d used:%d\n", devno, dvb_dsc_dev[devno].used);
|
|
goto ERROR_EXIT;
|
|
}
|
|
fd = dvb_dsc_dev[devno].fd;
|
|
ret = ioctl(fd, CA_SC2_SET_DESCR_EX, &desc);
|
|
if (ret != 0) {
|
|
MLOGE(" ca_free_chan ioctl fail\n");
|
|
goto ERROR_EXIT;
|
|
}
|
|
|
|
pthread_mutex_unlock(&lock);
|
|
MLOGI("ca_free_chan, index:%d\n", index);
|
|
|
|
return CA_DSC_OK;
|
|
ERROR_EXIT:
|
|
pthread_mutex_unlock(&lock);
|
|
return CA_DSC_ERROR;
|
|
}
|
|
|
|
|
|
int ca_set_key(int devno, int index, int parity, uint32_t key_index)
|
|
{
|
|
int ret, fd;
|
|
struct ca_sc2_descr_ex desc;
|
|
|
|
pthread_mutex_lock(&lock);
|
|
|
|
MLOGI("ca_set_key dev:%d, index:%d, parity:%d, key_index:%#x\n",
|
|
devno, index, parity, key_index);
|
|
desc.cmd = CA_KEY;
|
|
desc.params.key_params.ca_index = index;
|
|
desc.params.key_params.parity = (ca_sc2_key_type)parity;
|
|
desc.params.key_params.key_index = key_index;
|
|
|
|
if (devno >= MAX_DSC_DEV) {
|
|
MLOGE("ca_set_key failed! devno:%d\n", devno);
|
|
goto ERROR_EXIT;
|
|
}
|
|
|
|
if (!dvb_dsc_dev[devno].used) {
|
|
MLOGE("ca_set_key failed! devno:%d used:%d\n", devno, dvb_dsc_dev[devno].used);
|
|
goto ERROR_EXIT;
|
|
}
|
|
fd = dvb_dsc_dev[devno].fd;
|
|
ret = ioctl(fd, CA_SC2_SET_DESCR_EX, &desc);
|
|
if (ret != 0) {
|
|
MLOGE("ca_set_key ioctl fail, ret:0x%0x\n", ret);
|
|
goto ERROR_EXIT;
|
|
}
|
|
|
|
pthread_mutex_unlock(&lock);
|
|
MLOGI("ca_set_key ok, index:%d, parity:%d, key_index:%#x\n",index, parity, key_index);
|
|
|
|
return CA_DSC_OK;
|
|
ERROR_EXIT:
|
|
pthread_mutex_unlock(&lock);
|
|
return CA_DSC_ERROR;
|
|
}
|
|
|
|
int ca_close(int devno)
|
|
{
|
|
int fd;
|
|
int ret = 0;
|
|
pthread_mutex_lock(&lock);
|
|
|
|
MLOGI("ca_close dev:%d\n", devno);
|
|
|
|
if (devno >= MAX_DSC_DEV) {
|
|
MLOGE("ca_close failed! devno:%d\n", devno);
|
|
goto ERROR_EXIT;
|
|
}
|
|
|
|
if (!dvb_dsc_dev[devno].used) {
|
|
MLOGE("ca_close failed! devno:%d used:%d\n", devno, dvb_dsc_dev[devno].used);
|
|
goto ERROR_EXIT;
|
|
}
|
|
fd = dvb_dsc_dev[devno].fd;
|
|
ret = close(fd);
|
|
if (0 == ret) {
|
|
dvb_dsc_dev[devno].fd = 0;
|
|
dvb_dsc_dev[devno].used = 0;
|
|
}
|
|
MLOGI("ca_close ret:%d\n", ret);
|
|
pthread_mutex_unlock(&lock);
|
|
|
|
return CA_DSC_OK;
|
|
ERROR_EXIT:
|
|
pthread_mutex_unlock(&lock);
|
|
return CA_DSC_ERROR;
|
|
}
|
|
|
|
|
|
|
|
int caGetFd(int devno)
|
|
{
|
|
int fd = -1;
|
|
|
|
pthread_mutex_lock(&lock);
|
|
|
|
if (devno >= MAX_DSC_DEV) {
|
|
MLOGE("ca_open failed! devno:%d\n", devno);
|
|
pthread_mutex_unlock(&lock);
|
|
return fd;
|
|
}
|
|
if (dvb_dsc_dev[devno].used) {
|
|
fd = dvb_dsc_dev[devno].fd;
|
|
}
|
|
pthread_mutex_unlock(&lock);
|
|
|
|
return fd;
|
|
}
|
|
|
|
bool caSetDscChannelsKeyslot(Aml_MP_MediaCasDsmParams *mediacasDsmParams)
|
|
{
|
|
MLOG();
|
|
Aml_MP_MediaCasDsmParams *mParams = mediacasDsmParams;
|
|
|
|
int mCount = mParams->mKeyslotList.count;
|
|
MLOGI("mKeyslotList mCount=%d.", mCount);
|
|
for (int i = 0; i < mCount; i++) {
|
|
uint32_t kt_parity = mParams->mKeyslotList.keyslots[i].parity;
|
|
uint32_t kt_is_iv = mParams->mKeyslotList.keyslots[i].is_iv;
|
|
int kt_type = 0;
|
|
uint32_t kt_id = 0;
|
|
if (kt_parity == DSM_PARITY_NONE)
|
|
kt_type = kt_is_iv ? CA_KEY_00_IV_TYPE : CA_KEY_00_TYPE;
|
|
else if (kt_parity == DSM_PARITY_EVEN)
|
|
kt_type = kt_is_iv ? CA_KEY_EVEN_IV_TYPE : CA_KEY_EVEN_TYPE;
|
|
else if (kt_parity == DSM_PARITY_ODD)
|
|
kt_type = kt_is_iv ? CA_KEY_ODD_IV_TYPE : CA_KEY_ODD_TYPE;
|
|
else
|
|
return false;
|
|
kt_id = mParams->mKeyslotList.keyslots[i].id;
|
|
MLOGI("kt_is_iv=%d kt_type=%d kt_id=%d .", kt_is_iv, kt_type, kt_id);
|
|
if (mParams->vdsc_handle != AML_MP_INVALID_DSC_HANDLE) {
|
|
if (ca_set_key(mParams->dev_no, mParams->vdsc_handle, kt_type, kt_id)) {
|
|
MLOGI("ca_set_key vdsc(%d %d %d) failed!", mParams->vdsc_handle, kt_type, kt_id);
|
|
return false;
|
|
}
|
|
}
|
|
for (int i = 0; i < (int)(sizeof(mParams->adsc_handle) / sizeof(mParams->adsc_handle[0])); i++) {
|
|
if (mParams->adsc_handle[i] != AML_MP_INVALID_DSC_HANDLE) {
|
|
if (ca_set_key(mParams->dev_no, mParams->adsc_handle[i], kt_type, kt_id)) {
|
|
MLOGI("ca_set_key adsc[%d](%d %d %d) failed!", i, mParams->adsc_handle[i], kt_type, kt_id);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool caFreeDscChannels(Aml_MP_MediaCasDsmParams *mediacasDsmParams)
|
|
{
|
|
MLOG();
|
|
Aml_MP_MediaCasDsmParams *mParams = mediacasDsmParams;
|
|
|
|
MLOGI("dev_no,vdsc_handle (%d,%d).", mParams->dev_no, mParams->vdsc_handle);
|
|
if (mParams->vdsc_handle != AML_MP_INVALID_DSC_HANDLE) {
|
|
ca_free_chan(mParams->dev_no, mParams->vdsc_handle);
|
|
}
|
|
MLOGI("ca_free_chan vdsc(0x%x 0x%x) ok.", mParams->vid, mParams->vdsc_handle);
|
|
|
|
for (int i = 0; i < (int)(sizeof(mParams->adsc_handle) / sizeof(mParams->adsc_handle[0])); i++) {
|
|
MLOGI("dev_no,adsc_handle[%d] (%d,%d).", i, mParams->dev_no, mParams->adsc_handle[i]);
|
|
if (mParams->adsc_handle[i] != AML_MP_INVALID_DSC_HANDLE) {
|
|
ca_free_chan(mParams->dev_no, mParams->adsc_handle[i]);
|
|
}
|
|
MLOGI("ca_free_chan adsc[%d](0x%x 0x%x) ok.", i, mParams->aid[i], mParams->adsc_handle[i]);
|
|
}
|
|
|
|
ca_close(mParams->dev_no);
|
|
mParams->hasAllocDscChannels = false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool caAllocDscChannels(Aml_MP_MediaCasDsmParams *mediacasDsmParams)
|
|
{
|
|
MLOG();
|
|
Aml_MP_MediaCasDsmParams *mParams = mediacasDsmParams;
|
|
|
|
if (mParams->hasAllocDscChannels == true) {
|
|
MLOGI("caAllocDscChannels hasAllocDscChannels %d", mParams->hasAllocDscChannels);
|
|
return true;
|
|
}
|
|
|
|
if (mParams->vid != AML_MP_INVALID_PID) {
|
|
mParams->vdsc_handle = ca_alloc_chan(mParams->dev_no, mParams->vid, mParams->mDscAlgo, mParams->mDscType);
|
|
if (mParams->vdsc_handle == AML_MP_INVALID_DSC_HANDLE) {
|
|
MLOGI("ca_alloc_chan failed! vid:0x%x", mParams->vid);
|
|
ca_close(mParams->dev_no);
|
|
return false;
|
|
}
|
|
MLOGI("ca_alloc_chan vdsc(0x%x 0x%x) ok.", mParams->vid, mParams->vdsc_handle);
|
|
|
|
//if(mParams->isDvrRecord) {
|
|
ca_set_scb(mParams->dev_no, mParams->vdsc_handle, 0, 1);
|
|
//}
|
|
|
|
}
|
|
for (int i = 0; i < (int)(sizeof(mParams->aid) / sizeof(mParams->aid[0])); i++) {
|
|
if (mParams->aid[i] != AML_MP_INVALID_PID) {
|
|
mParams->adsc_handle[i] = ca_alloc_chan(mParams->dev_no, mParams->aid[i], mParams->mDscAlgo, mParams->mDscType);
|
|
if (mParams->adsc_handle[i] == AML_MP_INVALID_DSC_HANDLE) {
|
|
MLOGI("ca_alloc_chan failed! aid:0x%x", mParams->aid[i]);
|
|
ca_close(mParams->dev_no);
|
|
return false;
|
|
}
|
|
MLOGI("ca_alloc_chan adsc[%d](0x%x 0x%x) ok.hasAllocDscChannels=true", i, mParams->aid[i], mParams->adsc_handle[i]);
|
|
mParams->hasAllocDscChannels = true;
|
|
|
|
//if(mParams->isDvrRecord) {
|
|
ca_set_scb(mParams->dev_no, mParams->adsc_handle[i], 0, 1);
|
|
//}
|
|
}
|
|
}
|
|
mParams->hasAllocDscChannels = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool isDsmDecSlotReady(int dsmFd)
|
|
{
|
|
int dsmRet = 0;
|
|
uint32_t mIsKtReady = DSM_PROP_SLOT_NOT_READY;
|
|
uint32_t dsmUsage = DSM_PROP_SESSION_USAGE_LIVE;
|
|
|
|
if (dsmFd >= 0) {
|
|
dsmRet = DSM_GetProperty(dsmFd, DSM_PROP_CAS_SESSION_USAGE, &dsmUsage);
|
|
if (dsmRet != 0 || dsmUsage != DSM_PROP_SESSION_USAGE_LIVE)
|
|
return false;
|
|
|
|
dsmRet = DSM_GetProperty(dsmFd, DSM_PROP_DEC_SLOT_READY, &mIsKtReady);
|
|
if (dsmRet == 0 && mIsKtReady == DSM_PROP_SLOT_IS_READY) {
|
|
MLOGI("DSM_PROP_SLOT_IS_READY");
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool getKeySlots(int dsmFd, Aml_MP_MediaCasDsmParams *mediacasDsmParams)
|
|
{
|
|
int dsmRet = 0;
|
|
|
|
if (dsmFd < 0 || mediacasDsmParams == NULL) {
|
|
MLOGI("invalid parameter");
|
|
return false;
|
|
}
|
|
dsmRet = DSM_GetKeySlots(dsmFd, &(mediacasDsmParams->mKeyslotList));
|
|
if (dsmRet)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
bool caDsmOpenSession(int dev_no, int sessionId, int &dsmFd)
|
|
{
|
|
if (sessionId == -1) {
|
|
MLOGE("invalid parameter");
|
|
return false;
|
|
}
|
|
|
|
int dsmFd_tmp = DSM_OpenSession(0);//a non-negative integer on success
|
|
MLOGI("DSM_OpenSession mDsmFd: %d", dsmFd_tmp);
|
|
if (dsmFd_tmp < 0) {
|
|
MLOGE("dsm_open failed! %s", strerror(errno));
|
|
return false;
|
|
}
|
|
|
|
MLOGI("sessionId = 0x%x", sessionId);
|
|
if (DSM_BindToken(dsmFd_tmp, sessionId)) {
|
|
MLOGE("DSM_BindToken failed! %s", strerror(errno));
|
|
DSM_CloseSession(dsmFd_tmp);
|
|
return false;
|
|
}
|
|
|
|
uint32_t casSessionUsage = 0;
|
|
if (DSM_GetProperty(dsmFd_tmp, DSM_PROP_CAS_SESSION_USAGE, &casSessionUsage) == 0) {
|
|
MLOGI("casSessionUsage:%d", casSessionUsage);
|
|
}
|
|
|
|
if (ca_open(dev_no) != 0) {
|
|
MLOGE("ca_open failed! %s", strerror(errno));
|
|
DSM_CloseSession(dsmFd_tmp);
|
|
return false;
|
|
}
|
|
dsmFd = dsmFd_tmp;
|
|
return true;
|
|
}
|
|
|
|
int caDsmCloseSession(Aml_MP_MediaCasDsmParams *mediacasDsmParams)
|
|
{
|
|
Aml_MP_MediaCasDsmParams *mParams = mediacasDsmParams;
|
|
int ret = 0;
|
|
|
|
if (mParams->mDsmFd >= 0) {
|
|
DSM_CloseSession(mParams->mDsmFd);
|
|
mParams->mDsmFd = -1;
|
|
}
|
|
|
|
MLOGI("caDsmCloseSession ret:%d", ret);
|
|
return ret;
|
|
}
|
|
|
|
int CaClearMediacasDsmParamsState(Aml_MP_MediaCasDsmParams *mediacasDsmParams)
|
|
{
|
|
Aml_MP_MediaCasDsmParams *mParams = mediacasDsmParams;
|
|
memset(mParams, 0, sizeof(Aml_MP_MediaCasDsmParams));
|
|
mParams->mDsmFd = -1;
|
|
mParams->vdsc_handle = AML_MP_INVALID_DSC_HANDLE;
|
|
mParams->vid = AML_MP_INVALID_PID;
|
|
for (int i = 0; i < (int)(sizeof(mParams->adsc_handle) / sizeof(mParams->adsc_handle[0])); i++) {
|
|
mParams->adsc_handle[i] = AML_MP_INVALID_DSC_HANDLE;
|
|
}
|
|
for (int j = 0; j < (int)(sizeof(mParams->aid) / sizeof(mParams->aid[0])); j++) {
|
|
mParams->aid[j] = AML_MP_INVALID_PID;
|
|
}
|
|
mParams->hasAllocDscChannels = false;
|
|
return 0;
|
|
}
|
|
|
|
}
|