adcapp

This is a tool to read all the available ADC channels.
A raw value is read from each of the channels.

Updated LICENSE file to cover all source files and
removed file specific licenses at the top of some
of the files.

Signed-off-by: Hongwei Zhang <hongweiz@ami.com>
Change-Id: I3c1b389c0d91bccfc3ee93bccfe04137d7ea9960
Signed-off-by: Kiran Kumar <kirank@ami.com>
diff --git a/hongweiz/adcapp/src/EINTR_wrappers.c b/hongweiz/adcapp/src/EINTR_wrappers.c
new file mode 100644
index 0000000..b60622e
--- /dev/null
+++ b/hongweiz/adcapp/src/EINTR_wrappers.c
@@ -0,0 +1,826 @@
+
+/*
+* File: EINTR_wrappers.c
+*
+* This file implements the wrapper functions for some of the System APIs
+*
+* Copyright (C) <2019>  <American Megatrends International LLC>
+*
+*/
+
+#include "EINTR_wrappers.h"
+#if defined(__linux__)
+#include <sys/msg.h>
+#include <sys/file.h>
+#endif
+#include <errno.h>
+#include <unistd.h>
+
+static const int OneSecondasNS = 1000000000;
+
+#ifndef bool
+typedef int bool;
+#endif
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+typedef struct
+{
+    bool OnePoll;
+    struct timespec EndTime, Timeout;
+} SIGWRAP_TIMEOUT;
+
+static void sigwrap_InitTimeout(SIGWRAP_TIMEOUT *pDst, const struct timespec *timeout)
+{
+    pDst->Timeout = *timeout;
+
+    if ((timeout->tv_sec == 0) && (timeout->tv_nsec == 0))                  // If both value are zero than only a single poll is requested!
+    {
+        pDst->OnePoll = 1;
+        return;
+    }
+
+    pDst->OnePoll = 0;
+
+    struct timespec Now;
+
+    (void)clock_gettime(CLOCK_MONOTONIC_RAW, &Now);                         // CLOCK_MONOTONIC_RAW is not affected by NTP etc.
+
+    pDst->EndTime.tv_sec = Now.tv_sec + pDst->Timeout.tv_sec;               // Check necessary in 2038 due to signed integer variables
+    pDst->EndTime.tv_nsec = Now.tv_nsec + pDst->Timeout.tv_nsec;
+
+    if (pDst->EndTime.tv_nsec >= OneSecondasNS)
+    {
+        pDst->EndTime.tv_sec += (pDst->EndTime.tv_nsec / OneSecondasNS);
+        pDst->EndTime.tv_nsec = (pDst->EndTime.tv_nsec % OneSecondasNS);
+    }
+}
+
+
+static bool sigwrap_CheckTimeout(SIGWRAP_TIMEOUT *pTo)
+{
+    if (pTo->OnePoll == TRUE) // Make sure, that in the case that a single poll is requested at least one call is not terminated with EINTR
+        return FALSE;
+
+    struct timespec Now;
+
+    (void)clock_gettime(CLOCK_MONOTONIC_RAW, &Now);
+
+    if (Now.tv_sec > pTo->EndTime.tv_sec) // Can become a problem already in 2038 due to signed integer variables
+        return TRUE;
+
+    pTo->Timeout.tv_nsec = pTo->EndTime.tv_nsec - Now.tv_nsec;
+    pTo->Timeout.tv_sec = pTo->EndTime.tv_sec - Now.tv_sec;
+
+    if (pTo->Timeout.tv_sec == 0)
+    {
+        if (pTo->Timeout.tv_nsec <= 0)
+            return TRUE;
+    }
+    else if (pTo->Timeout.tv_nsec < 0)
+    {
+        pTo->Timeout.tv_nsec += OneSecondasNS;
+        pTo->Timeout.tv_sec--;
+    }
+
+    return FALSE;
+}
+
+
+
+int sigwrap_semop(int semid, struct sembuf *sops, size_t nsops)
+{
+    while (1)
+    {
+        if (semop(semid, sops, nsops) == 0)
+            return 0;
+
+        if (errno != EINTR)
+            return -1;
+    }
+}
+
+#if 0
+int sigwrap_semtimedop(int semid, struct sembuf *sops, size_t nsops, const struct timespec *timeout)
+{
+    SIGWRAP_TIMEOUT To;
+
+    if (timeout == NULL)
+        return (sigwrap_semop(semid, sops, nsops));
+
+    sigwrap_InitTimeout(&To, timeout);
+
+    while (1)
+    {
+        if (semtimedop(semid, sops, nsops, &To.Timeout) == 0)
+            return 0;
+
+        if (errno != EINTR)
+            return -1;
+
+        if (sigwrap_CheckTimeout(&To))
+        {
+            errno = EAGAIN;
+            return -1;
+        }
+    }
+}
+#endif
+
+int sigwrap_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
+{
+    SIGWRAP_TIMEOUT To;
+
+    if (timeout != -1)
+    {
+        struct timespec Timeout;
+
+        Timeout.tv_sec = timeout / 1000;
+        Timeout.tv_nsec = (timeout % 1000) * 1000000; // Convert msec to nsec
+
+        sigwrap_InitTimeout(&To, &Timeout);
+    }
+
+    while (1)
+    {
+        int Result = epoll_wait(epfd, events, maxevents, timeout);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+
+        if (timeout == -1)
+            continue;
+
+        if (sigwrap_CheckTimeout(&To))
+            return 0;
+
+        timeout = To.Timeout.tv_sec * 1000 + To.Timeout.tv_nsec / 1000000;
+    }
+}
+
+
+int sigwrap_epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask)
+{
+    SIGWRAP_TIMEOUT To;
+
+    if (timeout != -1)
+    {
+        struct timespec Timeout;
+
+        Timeout.tv_sec = timeout / 1000;
+        Timeout.tv_nsec = (timeout % 1000) * 1000000; // Convert msec to nsec
+
+        sigwrap_InitTimeout(&To, &Timeout);
+    }
+
+    while (1)
+    {
+        int Result = epoll_pwait(epfd, events, maxevents, timeout, sigmask);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+
+        if (timeout == -1)
+            continue;
+
+        if (sigwrap_CheckTimeout(&To))
+            return 0;
+
+        timeout = To.Timeout.tv_sec * 1000 + To.Timeout.tv_nsec / 1000000;
+    }
+}
+
+
+int sigwrap_sigwaitinfo(const sigset_t *set, siginfo_t *info)
+{
+    while (1)
+    {
+        int Result = sigwaitinfo(set, info);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+    }
+}
+
+
+int sigwrap_sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout)
+{
+    SIGWRAP_TIMEOUT To;
+
+    sigwrap_InitTimeout(&To, timeout);
+
+    while (1)
+    {
+        int Result = sigtimedwait(set, info, &To.Timeout);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+
+        if (sigwrap_CheckTimeout(&To))
+            return 0;
+    }
+}
+
+
+int sigwrap_nanosleep(const struct timespec *req, struct timespec *rem)
+{
+    struct timespec Wait, Remain;
+
+    if (!rem)
+        rem = &Remain;
+
+    Wait = *req;
+
+    while (1)
+    {
+        if (nanosleep(&Wait, rem) == 0)
+            return 0;
+
+        if (errno != EINTR)
+            return -1;
+
+        Wait = *rem;
+    }
+}
+
+
+int sigwrap_clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, struct timespec *remain)
+{
+    struct timespec Wait, Remain;
+
+    if (!remain)
+        remain = &Remain;
+
+    Wait = *request;
+
+    while (1)
+    {
+        int Result = clock_nanosleep(clock_id, flags, &Wait, remain);
+        
+        if (Result == 0)
+            return Result;
+
+        if (Result != EINTR)
+            return Result;
+
+        if (flags != TIMER_ABSTIME)
+            Wait = *remain;
+    }
+}
+
+
+int sigwrap_usleep(useconds_t usec)
+{
+    SIGWRAP_TIMEOUT To;
+
+    struct timespec Timeout;
+
+    Timeout.tv_sec = usec / 1000000;
+    Timeout.tv_nsec = (usec % 1000000) * 1000;
+
+    sigwrap_InitTimeout(&To, &Timeout);
+
+    while (1)
+    {
+        if (usleep(usec) == 0)
+            return 0;
+
+        if (errno != EINTR)
+            return -1;
+
+        if (sigwrap_CheckTimeout(&To))
+            return 0;
+
+        usec = To.Timeout.tv_sec * 1000000 + To.Timeout.tv_nsec / 1000;
+    }
+}
+
+
+int sigwrap_poll(struct pollfd *fds, nfds_t nfds, int timeout)
+{
+    SIGWRAP_TIMEOUT To;
+
+    if (timeout > 0)
+    {
+        struct timespec Timeout;
+
+        Timeout.tv_sec = timeout / 1000;
+        Timeout.tv_nsec = (timeout % 1000) * 1000000;
+
+        sigwrap_InitTimeout(&To, &Timeout);
+    }
+
+    while (1)
+    {
+        int Result = poll(fds, nfds, timeout);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+
+        if (timeout < 0) // Specifying a negative value in timeout means an infinite/no timeout. 
+            continue;
+        else if (timeout == 0)
+            continue; // We want to make sure that at least one check was not aborted with EINTR
+
+        if (sigwrap_CheckTimeout(&To))
+            return 0;
+
+        timeout = To.Timeout.tv_sec * 1000 + To.Timeout.tv_nsec / 1000000;
+    }
+}
+
+#if 0
+int sigwrap_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask)
+{
+    SIGWRAP_TIMEOUT To;
+
+    if (tmo_p != NULL)
+    {
+        sigwrap_InitTimeout(&To, tmo_p);
+        tmo_p = &To.Timeout;
+    }
+
+    while (1)
+    {
+        int Result = ppoll(fds, nfds, tmo_p, sigmask);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+
+        if (tmo_p == NULL)
+            continue;
+
+        if (sigwrap_CheckTimeout(&To))
+            return 0;
+    }
+}
+#endif
+
+int sigwrap_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
+{
+    while (1)
+    {
+        int Result = select(nfds, readfds, writefds, exceptfds, timeout);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+    }
+}
+
+
+int sigwrap_pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout,
+                    const sigset_t *sigmask)
+{
+    SIGWRAP_TIMEOUT To;
+
+    if (timeout != NULL)
+    {
+        sigwrap_InitTimeout(&To, timeout);
+        timeout = &To.Timeout;
+    }
+
+    while (1)
+    {
+        int Result = pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+
+        if (timeout == NULL)
+            continue;
+
+        if (sigwrap_CheckTimeout(&To))
+            return 0;
+    }
+}
+
+
+int sigwrap_msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)
+{
+    while (1)
+    {
+        int Result = msgsnd(msqid, msgp, msgsz, msgflg);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+    }
+}
+
+
+ssize_t sigwrap_msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
+{
+    while (1)
+    {
+        ssize_t Result = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+    }
+}
+
+
+int sigwrap_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+    while (1)
+    {
+        int Result = connect(sockfd, addr, addrlen);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+    }
+}
+
+
+ssize_t sigwrap_send(int sockfd, const void *buf, size_t len, int flags)
+{
+    while (1)
+    {
+        ssize_t Result = send(sockfd, buf, len, flags);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+    }
+}
+
+
+ssize_t sigwrap_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr,
+                       socklen_t addrlen)
+{
+    while (1)
+    {
+        ssize_t Result = sendto(sockfd, buf, len, flags, dest_addr, addrlen);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+    }
+}
+
+
+ssize_t sigwrap_sendsendmsg(int sockfd, const struct msghdr *msg, int flags)
+{
+    while (1)
+    {
+        ssize_t Result = sendmsg(sockfd, msg, flags);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+    }
+}
+
+
+int sigwrap_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+    while (1)
+    {
+        int Result = accept(sockfd, addr, addrlen);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+    }
+}
+
+#if 0
+int sigwrap_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
+{
+    while (1)
+    {
+        int Result = accept4(sockfd, addr, addrlen, flags);
+
+        if (Result != -1)
+            return Result;
+
+        if (errno != EINTR)
+            return Result;
+    }
+}
+#endif
+
+// EINTR wrapper for the standard read() function. Can be used for sockets that are the to non-blocking mode.
+// The length of the returned data can be shorter than the requested one!
+
+ssize_t sigwrap_read(int fd, void *buf, size_t count)
+{
+    while (1)
+    {
+        ssize_t Result = read(fd, buf, count);
+
+        if (Result != -1)
+            return (Result);
+
+        if (errno != EINTR)
+            return (Result);
+    }
+}
+
+
+// EINTR wrapper for the standard read() function. Waits until ALL requested data is available. Use the non-blocking version (sigwrap_read)
+// for sockets that are set to non-blocking mode or when partial data is okay
+// Although the description for the read() function describes it differently, it seems possible that the original function may already return
+// even though partial data has already been read. This implementation makes sure that all requested data have been read.
+// See the comment in the signal description https://linux.die.net/man/7/signal
+//* read(2), readv(2), write(2), writev(2), and ioctl(2) calls on "slow" devices. 
+//* A "slow" device is one where the I/O call may block for an indefinite time, for example, a terminal, pipe, or socket. 
+//* (A disk is not a slow device according to this definition.) If an I/O call on a slow device has already transferred
+//* some data by the time it is interrupted by a signal handler, then the call will return a success status (normally, the number of bytes transferred). 
+
+ssize_t sigwrap_blocking_read(int hFile, void *pData, size_t RdLen)
+{
+    ssize_t Transfered;
+    ssize_t Len = RdLen;
+
+    while ((Transfered = read(hFile, pData, Len)) != Len)
+    {
+        if (Transfered == 0) // EOF reached?
+            return 0;
+
+        if (Transfered != -1)
+        {
+            pData += Transfered;
+            Len -= Transfered;
+            continue;
+        }
+
+        if (errno != EINTR)
+            return -1;
+    }
+
+    return RdLen;
+}
+
+
+ssize_t sigwrap_readv(int fd, const struct iovec *iov, int iovcnt)
+{
+    while (1)
+    {
+        ssize_t Result = readv(fd, iov, iovcnt);
+
+        if (Result != -1)
+            return (Result);
+
+        if (errno != EINTR)
+            return (Result);
+    }
+}
+
+
+ssize_t sigwrap_recv(int sockfd, void *buf, size_t len, int flags)
+{
+    while (1)
+    {
+        ssize_t Result = recv(sockfd, buf, len, flags);
+
+        if (Result != -1)
+            return (Result);
+
+        if (errno != EINTR)
+            return (Result);
+    }
+}
+
+
+ssize_t sigwrap_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
+{
+    while (1)
+    {
+        ssize_t Result = recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
+
+        if (Result != -1)
+            return (Result);
+
+        if (errno != EINTR)
+            return (Result);
+    }
+}
+
+
+ssize_t sigwrap_recvmsg(int sockfd, struct msghdr *msg, int flags)
+{
+    while (1)
+    {
+        ssize_t Result = recvmsg(sockfd, msg, flags);
+
+        if (Result != -1)
+            return (Result);
+
+        if (errno != EINTR)
+            return (Result);
+    }
+}
+
+
+// EINTR wrapper for the standard write() function. Can be used for sockets that are the to non-blocking mode.
+// The length of the effectively written data can be shorter than the length specified at the function call!
+
+ssize_t sigwrap_write(int fd, const void *buf, size_t count)
+{
+    while (1)
+    {
+        ssize_t Result = write(fd, buf, count);
+
+        if (Result != -1)
+            return (Result);
+
+        if (errno != EINTR)
+            return (Result);
+    }
+}
+
+// EINTR wrapper for the standard write() function. Waits until ALL data is written! Use the non-blocking version (sigwrap_write)
+// for sockets that are set to non-blocking mode, or when it is OK to write only partial data.
+// Although the description for the write() function describes it differently, it seems possible that the original function may already return
+// even though partial data has already been written. This implementation makes sure that all requested data have been written.
+// See the comment in the signal description https://linux.die.net/man/7/signal
+//* read(2), readv(2), write(2), writev(2), and ioctl(2) calls on "slow" devices. 
+//* A "slow" device is one where the I/O call may block for an indefinite time, for example, a terminal, pipe, or socket. 
+//* (A disk is not a slow device according to this definition.) If an I/O call on a slow device has already transferred
+//* some data by the time it is interrupted by a signal handler, then the call will return a success status (normally, the number of bytes transferred). 
+        
+ssize_t sigwrap_blocking_write(int hFile, const void *pData, ssize_t WrtLen)
+{
+    ssize_t Written;
+    ssize_t Len = WrtLen;
+
+    while ((Written = write(hFile, pData, Len)) != Len)
+    {
+        if (Written != -1)
+        {
+            pData += Written;
+            Len -= Written;
+            continue;
+        }
+
+        if (errno != EINTR)
+            return -1;
+    }
+
+    return WrtLen;
+}
+
+
+ssize_t sigwrap_writev(int fd, const struct iovec *iov, int iovcnt)
+{
+    while (1)
+    {
+        ssize_t Result = writev(fd, iov, iovcnt);
+
+        if (Result != -1)
+            return (Result);
+
+        if (errno != EINTR)
+            return (Result);
+    }
+}
+
+
+int sigwrap_close(int hFile)
+{
+    while (close(hFile) == -1)
+    {
+        if (errno != EINTR)
+            return -1;
+    }
+
+    return 0;
+}
+
+
+int sigwrap_open_mode(const char *pathname, int flags, mode_t mode)
+{
+    while (1)
+    {
+        int hFile = open(pathname, flags, mode);
+        
+        if(hFile != -1)
+            return hFile;
+        
+        if (errno != EINTR)
+            return hFile;
+    }
+}
+
+int sigwrap_open(const char *pathname, int flags)
+{
+    while (1)
+    {
+        int hFile = open(pathname, flags);
+        
+        if(hFile != -1)
+            return hFile;
+        
+        if (errno != EINTR)
+            return hFile;
+    }
+}
+
+
+pid_t sigwrap_wait(int *status)
+{
+    while(1)
+    {
+        pid_t Result = wait(status);
+        
+        if(Result != -1)
+            return Result;
+        
+        if(errno != EINTR)
+            return Result;
+    }
+}
+
+
+pid_t sigwrap_waitpid(pid_t pid, int *status, int options)
+{
+    while(1)
+    {
+        pid_t Result = waitpid(pid, status, options);
+        
+        if(Result != -1)
+            return Result;
+        
+        if(errno != EINTR)
+            return Result;
+    }
+}
+
+
+int sigwrap_waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
+{
+    while(1)
+    {
+        int Result = waitid(idtype, id, infop, options);
+        
+        if(Result != -1)
+            return Result;
+        
+        if(errno != EINTR)
+            return Result;
+    }
+}
+
+
+int sigwrap_flock(int fd, int operation) 
+{
+    while(1)
+    {
+        int Result = flock(fd, operation);
+        
+        if(Result != -1)
+            return Result;
+        
+        if(errno != EINTR)
+            return Result;
+    }
+}
+
+