vdr  1.7.27
dvbci.c
Go to the documentation of this file.
00001 /*
00002  * dvbci.h: Common Interface for DVB devices
00003  *
00004  * See the main source file 'vdr.c' for copyright information and
00005  * how to reach the author.
00006  *
00007  * $Id: dvbci.c 2.0 2007/01/04 12:49:10 kls Exp $
00008  */
00009 
00010 #include "dvbci.h"
00011 #include <linux/dvb/ca.h>
00012 #include <sys/ioctl.h>
00013 #include "device.h"
00014 
00015 // --- cDvbCiAdapter ---------------------------------------------------------
00016 
00017 cDvbCiAdapter::cDvbCiAdapter(cDevice *Device, int Fd)
00018 {
00019   device = Device;
00020   SetDescription("CI adapter on device %d", device->DeviceNumber());
00021   fd = Fd;
00022   ca_caps_t Caps;
00023   if (ioctl(fd, CA_GET_CAP, &Caps) == 0) {
00024      if ((Caps.slot_type & CA_CI_LINK) != 0) {
00025         int NumSlots = Caps.slot_num;
00026         if (NumSlots > 0) {
00027            for (int i = 0; i < NumSlots; i++)
00028                new cCamSlot(this);
00029            Start();
00030            }
00031         else
00032            esyslog("ERROR: no CAM slots found on device %d", device->DeviceNumber());
00033         }
00034      else
00035         isyslog("device %d doesn't support CI link layer interface", device->DeviceNumber());
00036      }
00037   else
00038      esyslog("ERROR: can't get CA capabilities on device %d", device->DeviceNumber());
00039 }
00040 
00041 cDvbCiAdapter::~cDvbCiAdapter()
00042 {
00043   Cancel(3);
00044 }
00045 
00046 int cDvbCiAdapter::Read(uint8_t *Buffer, int MaxLength)
00047 {
00048   if (Buffer && MaxLength > 0) {
00049      struct pollfd pfd[1];
00050      pfd[0].fd = fd;
00051      pfd[0].events = POLLIN;
00052      if (poll(pfd, 1, CAM_READ_TIMEOUT) > 0 && (pfd[0].revents & POLLIN)) {
00053         int n = safe_read(fd, Buffer, MaxLength);
00054         if (n >= 0)
00055            return n;
00056         esyslog("ERROR: can't read from CI adapter on device %d: %m", device->DeviceNumber());
00057         }
00058      }
00059   return 0;
00060 }
00061 
00062 void cDvbCiAdapter::Write(const uint8_t *Buffer, int Length)
00063 {
00064   if (Buffer && Length > 0) {
00065      if (safe_write(fd, Buffer, Length) != Length)
00066         esyslog("ERROR: can't write to CI adapter on device %d: %m", device->DeviceNumber());
00067      }
00068 }
00069 
00070 bool cDvbCiAdapter::Reset(int Slot)
00071 {
00072   if (ioctl(fd, CA_RESET, 1 << Slot) != -1)
00073      return true;
00074   else
00075      esyslog("ERROR: can't reset CAM slot %d on device %d: %m", Slot, device->DeviceNumber());
00076   return false;
00077 }
00078 
00079 eModuleStatus cDvbCiAdapter::ModuleStatus(int Slot)
00080 {
00081   ca_slot_info_t sinfo;
00082   sinfo.num = Slot;
00083   if (ioctl(fd, CA_GET_SLOT_INFO, &sinfo) != -1) {
00084      if ((sinfo.flags & CA_CI_MODULE_READY) != 0)
00085         return msReady;
00086      else if ((sinfo.flags & CA_CI_MODULE_PRESENT) != 0)
00087         return msPresent;
00088      }
00089   else
00090      esyslog("ERROR: can't get info of CAM slot %d on device %d: %m", Slot, device->DeviceNumber());
00091   return msNone;
00092 }
00093 
00094 bool cDvbCiAdapter::Assign(cDevice *Device, bool Query)
00095 {
00096   // The CI is hardwired to its device, so there's not really much to do here
00097   if (Device)
00098      return Device == device;
00099   return true;
00100 }
00101 
00102 cDvbCiAdapter *cDvbCiAdapter::CreateCiAdapter(cDevice *Device, int Fd)
00103 {
00104   // TODO check whether a CI is actually present?
00105   if (Device)
00106      return new cDvbCiAdapter(Device, Fd);
00107   return NULL;
00108 }