Files
vision-anti-pinch/tests/orin_capture_faults.c

40 lines
2.6 KiB
C

#define _GNU_SOURCE
#include <dlfcn.h>
#include <poll.h>
#include <sys/select.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <stdarg.h>
#include <errno.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
static int calls=0;
static int camera_fd(int fd){char name[64],target[256];snprintf(name,sizeof(name),"/proc/self/fd/%d",fd);ssize_t n=readlink(name,target,sizeof(target)-1);if(n<0)return 0;target[n]=0;return strcmp(target,"/dev/video5")==0;}
static long long now_ms(void){struct timespec t;clock_gettime(CLOCK_MONOTONIC,&t);return (long long)t.tv_sec*1000+t.tv_nsec/1000000;}
static void marker(const char *s){ssize_t ignored=write(2,s,strlen(s));(void)ignored;}
static int should_stall(void){
static long long since=0;static int phase=0,resumed=0;
if(!getenv("VAP_TEST_STALL"))return 0;
if(phase==0){if(++calls<60)return 0;phase=1;since=now_ms();marker("TEST_STALL_ACTIVE\n");}
if(phase==1&&getenv("VAP_TEST_RECOVER")&&now_ms()-since>=4200){phase=2;marker("TEST_CAMERA_RECOVERED\n");return 0;}
if(phase==2){if(++resumed<30)return 0;phase=3;marker("TEST_STALL_SECOND\n");}
return phase==1||phase==3;
}
int poll(struct pollfd *fds,nfds_t count,int timeout){static int(*real_poll)(struct pollfd*,nfds_t,int);if(!real_poll)real_poll=dlsym(RTLD_NEXT,"poll");for(nfds_t i=0;i<count;++i)if(!getenv("VAP_TEST_KIND")&&camera_fd(fds[i].fd)&&should_stall()){int saved=fds[i].fd;fds[i].fd=-1;int rc=real_poll(fds,count,timeout);fds[i].fd=saved;return rc;}return real_poll(fds,count,timeout);}
int __poll_chk(struct pollfd *fds,nfds_t count,int timeout,size_t size){(void)size;return poll(fds,count,timeout);}
int select(int count,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout){static int(*real_select)(int,fd_set*,fd_set*,fd_set*,struct timeval*);if(!real_select)real_select=dlsym(RTLD_NEXT,"select");if(readfds)for(int fd=0;fd<count;++fd)if(!getenv("VAP_TEST_KIND")&&FD_ISSET(fd,readfds)&&camera_fd(fd)&&should_stall()){FD_CLR(fd,readfds);break;}return real_select(count,readfds,writefds,exceptfds,timeout);}
int ioctl(int fd,unsigned long request,...){
static int(*real_ioctl)(int,unsigned long,...);if(!real_ioctl)real_ioctl=dlsym(RTLD_NEXT,"ioctl");
va_list args;va_start(args,request);void *arg=va_arg(args,void*);va_end(args);
const char *kind=getenv("VAP_TEST_KIND");
if(kind&&request==VIDIOC_DQBUF&&camera_fd(fd)&&should_stall()){
if(strcmp(kind,"bad_frames")==0){int rc=real_ioctl(fd,request,arg);if(rc==0)((struct v4l2_buffer*)arg)->flags|=V4L2_BUF_FLAG_ERROR;return rc;}
errno=strcmp(kind,"device_error")==0?ENODEV:EIO;return -1;
}
return real_ioctl(fd,request,arg);
}