mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
109 lines
2.9 KiB
C
109 lines
2.9 KiB
C
/*
|
|
* dvbci.h: Common Interface for DVB devices
|
|
*
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
* how to reach the author.
|
|
*
|
|
* $Id: dvbci.c 3.1 2015/01/14 11:13:49 kls Exp $
|
|
*/
|
|
|
|
#include "dvbci.h"
|
|
#include <linux/dvb/ca.h>
|
|
#include <sys/ioctl.h>
|
|
#include "device.h"
|
|
|
|
// --- cDvbCiAdapter ---------------------------------------------------------
|
|
|
|
cDvbCiAdapter::cDvbCiAdapter(cDevice *Device, int Fd)
|
|
{
|
|
device = Device;
|
|
SetDescription("device %d CI adapter", device->DeviceNumber());
|
|
fd = Fd;
|
|
ca_caps_t Caps;
|
|
if (ioctl(fd, CA_GET_CAP, &Caps) == 0) {
|
|
if ((Caps.slot_type & CA_CI_LINK) != 0) {
|
|
int NumSlots = Caps.slot_num;
|
|
if (NumSlots > 0) {
|
|
for (int i = 0; i < NumSlots; i++)
|
|
new cCamSlot(this);
|
|
Start();
|
|
}
|
|
else
|
|
esyslog("ERROR: no CAM slots found on device %d", device->DeviceNumber());
|
|
}
|
|
else
|
|
isyslog("device %d doesn't support CI link layer interface", device->DeviceNumber());
|
|
}
|
|
else
|
|
esyslog("ERROR: can't get CA capabilities on device %d", device->DeviceNumber());
|
|
}
|
|
|
|
cDvbCiAdapter::~cDvbCiAdapter()
|
|
{
|
|
Cancel(3);
|
|
}
|
|
|
|
int cDvbCiAdapter::Read(uint8_t *Buffer, int MaxLength)
|
|
{
|
|
if (Buffer && MaxLength > 0) {
|
|
struct pollfd pfd[1];
|
|
pfd[0].fd = fd;
|
|
pfd[0].events = POLLIN;
|
|
if (poll(pfd, 1, CAM_READ_TIMEOUT) > 0 && (pfd[0].revents & POLLIN)) {
|
|
int n = safe_read(fd, Buffer, MaxLength);
|
|
if (n >= 0)
|
|
return n;
|
|
esyslog("ERROR: can't read from CI adapter on device %d: %m", device->DeviceNumber());
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void cDvbCiAdapter::Write(const uint8_t *Buffer, int Length)
|
|
{
|
|
if (Buffer && Length > 0) {
|
|
if (safe_write(fd, Buffer, Length) != Length)
|
|
esyslog("ERROR: can't write to CI adapter on device %d: %m", device->DeviceNumber());
|
|
}
|
|
}
|
|
|
|
bool cDvbCiAdapter::Reset(int Slot)
|
|
{
|
|
if (ioctl(fd, CA_RESET, 1 << Slot) != -1)
|
|
return true;
|
|
else
|
|
esyslog("ERROR: can't reset CAM slot %d on device %d: %m", Slot, device->DeviceNumber());
|
|
return false;
|
|
}
|
|
|
|
eModuleStatus cDvbCiAdapter::ModuleStatus(int Slot)
|
|
{
|
|
ca_slot_info_t sinfo;
|
|
sinfo.num = Slot;
|
|
if (ioctl(fd, CA_GET_SLOT_INFO, &sinfo) != -1) {
|
|
if ((sinfo.flags & CA_CI_MODULE_READY) != 0)
|
|
return msReady;
|
|
else if ((sinfo.flags & CA_CI_MODULE_PRESENT) != 0)
|
|
return msPresent;
|
|
}
|
|
else
|
|
esyslog("ERROR: can't get info of CAM slot %d on device %d: %m", Slot, device->DeviceNumber());
|
|
return msNone;
|
|
}
|
|
|
|
bool cDvbCiAdapter::Assign(cDevice *Device, bool Query)
|
|
{
|
|
// The CI is hardwired to its device, so there's not really much to do here
|
|
if (Device)
|
|
return Device == device;
|
|
return true;
|
|
}
|
|
|
|
cDvbCiAdapter *cDvbCiAdapter::CreateCiAdapter(cDevice *Device, int Fd)
|
|
{
|
|
// TODO check whether a CI is actually present?
|
|
if (Device)
|
|
return new cDvbCiAdapter(Device, Fd);
|
|
return NULL;
|
|
}
|