vdr
1.7.27
|
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 }