1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
/*
* 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 2.0 2007/01/04 12:49:10 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("CI adapter on device %d", 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;
}
|