vdr  1.7.31
dvbci.c
Go to the documentation of this file.
1 /*
2  * dvbci.h: Common Interface for DVB devices
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: dvbci.c 2.0 2007/01/04 12:49:10 kls Exp $
8  */
9 
10 #include "dvbci.h"
11 #include <linux/dvb/ca.h>
12 #include <sys/ioctl.h>
13 #include "device.h"
14 
15 // --- cDvbCiAdapter ---------------------------------------------------------
16 
18 {
19  device = Device;
20  SetDescription("CI adapter on device %d", device->DeviceNumber());
21  fd = Fd;
22  ca_caps_t Caps;
23  if (ioctl(fd, CA_GET_CAP, &Caps) == 0) {
24  if ((Caps.slot_type & CA_CI_LINK) != 0) {
25  int NumSlots = Caps.slot_num;
26  if (NumSlots > 0) {
27  for (int i = 0; i < NumSlots; i++)
28  new cCamSlot(this);
29  Start();
30  }
31  else
32  esyslog("ERROR: no CAM slots found on device %d", device->DeviceNumber());
33  }
34  else
35  isyslog("device %d doesn't support CI link layer interface", device->DeviceNumber());
36  }
37  else
38  esyslog("ERROR: can't get CA capabilities on device %d", device->DeviceNumber());
39 }
40 
42 {
43  Cancel(3);
44 }
45 
46 int cDvbCiAdapter::Read(uint8_t *Buffer, int MaxLength)
47 {
48  if (Buffer && MaxLength > 0) {
49  struct pollfd pfd[1];
50  pfd[0].fd = fd;
51  pfd[0].events = POLLIN;
52  if (poll(pfd, 1, CAM_READ_TIMEOUT) > 0 && (pfd[0].revents & POLLIN)) {
53  int n = safe_read(fd, Buffer, MaxLength);
54  if (n >= 0)
55  return n;
56  esyslog("ERROR: can't read from CI adapter on device %d: %m", device->DeviceNumber());
57  }
58  }
59  return 0;
60 }
61 
62 void cDvbCiAdapter::Write(const uint8_t *Buffer, int Length)
63 {
64  if (Buffer && Length > 0) {
65  if (safe_write(fd, Buffer, Length) != Length)
66  esyslog("ERROR: can't write to CI adapter on device %d: %m", device->DeviceNumber());
67  }
68 }
69 
70 bool cDvbCiAdapter::Reset(int Slot)
71 {
72  if (ioctl(fd, CA_RESET, 1 << Slot) != -1)
73  return true;
74  else
75  esyslog("ERROR: can't reset CAM slot %d on device %d: %m", Slot, device->DeviceNumber());
76  return false;
77 }
78 
80 {
81  ca_slot_info_t sinfo;
82  sinfo.num = Slot;
83  if (ioctl(fd, CA_GET_SLOT_INFO, &sinfo) != -1) {
84  if ((sinfo.flags & CA_CI_MODULE_READY) != 0)
85  return msReady;
86  else if ((sinfo.flags & CA_CI_MODULE_PRESENT) != 0)
87  return msPresent;
88  }
89  else
90  esyslog("ERROR: can't get info of CAM slot %d on device %d: %m", Slot, device->DeviceNumber());
91  return msNone;
92 }
93 
94 bool cDvbCiAdapter::Assign(cDevice *Device, bool Query)
95 {
96  // The CI is hardwired to its device, so there's not really much to do here
97  if (Device)
98  return Device == device;
99  return true;
100 }
101 
103 {
104  // TODO check whether a CI is actually present?
105  if (Device)
106  return new cDvbCiAdapter(Device, Fd);
107  return NULL;
108 }