Klaus Schmidinger wrote:
At this point...
Apr 7 09:06:41 vdr vdr: [4862] ms: 3 Apr 7 09:06:41 vdr vdr: [4862] resetTime1: 0 Apr 7 09:06:41 vdr vdr: [4862] ms: 2
...the module status changed from 3 ("ready") to 2 ("present"). The module status is retrieved from the driver in cDvbCiAdapter::ModuleStatus():
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; }
So for some reason the sinfo.flags doesn't seem to have the CA_CI_MODULE_READY flag set any longer.
Please take a look to the test code in attachment, provided by Christoph Pfister. With it I got the following output:
root@vdr:/video/vdr/cam# ./test 0.000008: 3 0.000161: 0 0.014133: 1 1.694142: 3
And explanation: After a reset CAM is "absent" for a very short time (<14ms == less than a scheduler tick) and then it takes ~1.7s to become ready again. (The intervall between reset and status query seems to be a bit bigger in vdr - so we only see the 3-->1 change == 3-->2 in vdr numbers).
It's an endless loop: cam detection --> cam reset --> cam not present/ready for a short while --> vdr thinks cam has been physically removed --> cam detection --> cam reset etc.
Big thanks to Christoph for assistance.
Is it realistic to hope for a workaround/solution for this kind of CAMs (Technotrend CX at my case)?
Regards, AK
#include <fcntl.h> #include <linux/dvb/ca.h> #include <stdio.h> #include <string.h> #include <sys/ioctl.h> #include <sys/time.h> #include <unistd.h>
int cam_status(int fd) { ca_slot_info_t info; memset(&info, 0, sizeof(info)); info.num = 0;
if (ioctl(fd, CA_GET_SLOT_INFO, &info) != 0) { printf("error: couldn't get slot info\n"); return -1; }
return info.flags; }
struct timeval start_time;
void print_status(int status) { struct timeval time; gettimeofday(&time, NULL);
int dsec = time.tv_sec - start_time.tv_sec; int dusec = time.tv_usec - start_time.tv_usec;
if (dusec < 0) { dusec += 1000000; dsec -= 1; }
printf("%i.%06i: %i\n", dsec, dusec, status); }
int main() { int fd = open("/dev/dvb/adapter0/ca0", O_RDWR);
if (fd < 0) { printf("error: couldn't open ca handle\n"); return 1; }
gettimeofday(&start_time, NULL);
int status = cam_status(fd); print_status(status);
if (ioctl(fd, CA_RESET, (1 << 0)) != 0) { printf("error: couldn't reset cam\n"); return 1; }
int i; for (i = 0; i < 200; ++i) { int new_status = cam_status(fd);
if (status != new_status) { status = new_status; print_status(status); }
usleep(10000); }
return 0; }