samsung: add libril for xmm626x modems

Change-Id: I3064271ac8d563f63b13278944639ab5a29ae87f
diff --git a/ril/xmm6260/libril/ril_event.cpp b/ril/xmm6260/libril/ril_event.cpp
new file mode 100644
index 0000000..b916919
--- /dev/null
+++ b/ril/xmm6260/libril/ril_event.cpp
@@ -0,0 +1,384 @@
+/* //device/libs/telephony/ril_event.cpp
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "RILC"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <utils/Log.h>
+#include <ril_event.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include <pthread.h>
+static pthread_mutex_t listMutex;
+#define MUTEX_ACQUIRE() pthread_mutex_lock(&listMutex)
+#define MUTEX_RELEASE() pthread_mutex_unlock(&listMutex)
+#define MUTEX_INIT() pthread_mutex_init(&listMutex, NULL)
+#define MUTEX_DESTROY() pthread_mutex_destroy(&listMutex)
+
+#ifndef timeradd
+#define timeradd(tvp, uvp, vvp)						\
+	do {								\
+		(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec;		\
+		(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec;       \
+		if ((vvp)->tv_usec >= 1000000) {			\
+			(vvp)->tv_sec++;				\
+			(vvp)->tv_usec -= 1000000;			\
+		}							\
+	} while (0)
+#endif
+
+#ifndef timercmp
+#define timercmp(a, b, op)               \
+        ((a)->tv_sec == (b)->tv_sec      \
+        ? (a)->tv_usec op (b)->tv_usec   \
+        : (a)->tv_sec op (b)->tv_sec)
+#endif
+
+#ifndef timersub
+#define timersub(a, b, res)                           \
+    do {                                              \
+        (res)->tv_sec = (a)->tv_sec - (b)->tv_sec;    \
+        (res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+        if ((res)->tv_usec < 0) {                     \
+            (res)->tv_usec += 1000000;                \
+            (res)->tv_sec -= 1;                       \
+        }                                             \
+    } while(0);
+#endif
+
+static fd_set readFds;
+static int nfds = 0;
+
+static struct ril_event * watch_table[MAX_FD_EVENTS];
+static struct ril_event timer_list;
+static struct ril_event pending_list;
+
+#define DEBUG 0
+
+#if DEBUG
+#define dlog(x...) ALOGD( x )
+static void dump_event(struct ril_event * ev)
+{
+    dlog("~~~~ Event %x ~~~~", (unsigned int)ev);
+    dlog("     next    = %x", (unsigned int)ev->next);
+    dlog("     prev    = %x", (unsigned int)ev->prev);
+    dlog("     fd      = %d", ev->fd);
+    dlog("     pers    = %d", ev->persist);
+    dlog("     timeout = %ds + %dus", (int)ev->timeout.tv_sec, (int)ev->timeout.tv_usec);
+    dlog("     func    = %x", (unsigned int)ev->func);
+    dlog("     param   = %x", (unsigned int)ev->param);
+    dlog("~~~~~~~~~~~~~~~~~~");
+}
+#else
+#define dlog(x...) do {} while(0)
+#define dump_event(x) do {} while(0)
+#endif
+
+static void getNow(struct timeval * tv)
+{
+#ifdef HAVE_POSIX_CLOCKS
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    tv->tv_sec = ts.tv_sec;
+    tv->tv_usec = ts.tv_nsec/1000;
+#else
+    gettimeofday(tv, NULL);
+#endif
+}
+
+static void init_list(struct ril_event * list)
+{
+    memset(list, 0, sizeof(struct ril_event));
+    list->next = list;
+    list->prev = list;
+    list->fd = -1;
+}
+
+static void addToList(struct ril_event * ev, struct ril_event * list)
+{
+    ev->next = list;
+    ev->prev = list->prev;
+    ev->prev->next = ev;
+    list->prev = ev;
+    dump_event(ev);
+}
+
+static void removeFromList(struct ril_event * ev)
+{
+    dlog("~~~~ Removing event ~~~~");
+    dump_event(ev);
+
+    ev->next->prev = ev->prev;
+    ev->prev->next = ev->next;
+    ev->next = NULL;
+    ev->prev = NULL;
+}
+
+
+static void removeWatch(struct ril_event * ev, int index)
+{
+    watch_table[index] = NULL;
+    ev->index = -1;
+
+    FD_CLR(ev->fd, &readFds);
+
+    if (ev->fd+1 == nfds) {
+        int n = 0;
+
+        for (int i = 0; i < MAX_FD_EVENTS; i++) {
+            struct ril_event * rev = watch_table[i];
+
+            if ((rev != NULL) && (rev->fd > n)) {
+                n = rev->fd;
+            }
+        }
+        nfds = n + 1;
+        dlog("~~~~ nfds = %d ~~~~", nfds);
+    }
+}
+
+static void processTimeouts()
+{
+    dlog("~~~~ +processTimeouts ~~~~");
+    MUTEX_ACQUIRE();
+    struct timeval now;
+    struct ril_event * tev = timer_list.next;
+    struct ril_event * next;
+
+    getNow(&now);
+    // walk list, see if now >= ev->timeout for any events
+
+    dlog("~~~~ Looking for timers <= %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec);
+    while ((tev != &timer_list) && (timercmp(&now, &tev->timeout, >))) {
+        // Timer expired
+        dlog("~~~~ firing timer ~~~~");
+        next = tev->next;
+        removeFromList(tev);
+        addToList(tev, &pending_list);
+        tev = next;
+    }
+    MUTEX_RELEASE();
+    dlog("~~~~ -processTimeouts ~~~~");
+}
+
+static void processReadReadies(fd_set * rfds, int n)
+{
+    dlog("~~~~ +processReadReadies (%d) ~~~~", n);
+    MUTEX_ACQUIRE();
+
+    for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) {
+        struct ril_event * rev = watch_table[i];
+        if (rev != NULL && FD_ISSET(rev->fd, rfds)) {
+            addToList(rev, &pending_list);
+            if (rev->persist == false) {
+                removeWatch(rev, i);
+            }
+            n--;
+        }
+    }
+
+    MUTEX_RELEASE();
+    dlog("~~~~ -processReadReadies (%d) ~~~~", n);
+}
+
+static void firePending()
+{
+    dlog("~~~~ +firePending ~~~~");
+    struct ril_event * ev = pending_list.next;
+    while (ev != &pending_list) {
+        struct ril_event * next = ev->next;
+        removeFromList(ev);
+        ev->func(ev->fd, 0, ev->param);
+        ev = next;
+    }
+    dlog("~~~~ -firePending ~~~~");
+}
+
+static int calcNextTimeout(struct timeval * tv)
+{
+    struct ril_event * tev = timer_list.next;
+    struct timeval now;
+
+    getNow(&now);
+
+    // Sorted list, so calc based on first node
+    if (tev == &timer_list) {
+        // no pending timers
+        return -1;
+    }
+
+    dlog("~~~~ now = %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec);
+    dlog("~~~~ next = %ds + %dus ~~~~",
+            (int)tev->timeout.tv_sec, (int)tev->timeout.tv_usec);
+    if (timercmp(&tev->timeout, &now, >)) {
+        timersub(&tev->timeout, &now, tv);
+    } else {
+        // timer already expired.
+        tv->tv_sec = tv->tv_usec = 0;
+    }
+    return 0;
+}
+
+// Initialize internal data structs
+void ril_event_init()
+{
+    MUTEX_INIT();
+
+    FD_ZERO(&readFds);
+    init_list(&timer_list);
+    init_list(&pending_list);
+    memset(watch_table, 0, sizeof(watch_table));
+}
+
+// Initialize an event
+void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)
+{
+    dlog("~~~~ ril_event_set %x ~~~~", (unsigned int)ev);
+    memset(ev, 0, sizeof(struct ril_event));
+    ev->fd = fd;
+    ev->index = -1;
+    ev->persist = persist;
+    ev->func = func;
+    ev->param = param;
+    fcntl(fd, F_SETFL, O_NONBLOCK);
+}
+
+// Add event to watch list
+void ril_event_add(struct ril_event * ev)
+{
+    dlog("~~~~ +ril_event_add ~~~~");
+    MUTEX_ACQUIRE();
+    for (int i = 0; i < MAX_FD_EVENTS; i++) {
+        if (watch_table[i] == NULL) {
+            watch_table[i] = ev;
+            ev->index = i;
+            dlog("~~~~ added at %d ~~~~", i);
+            dump_event(ev);
+            FD_SET(ev->fd, &readFds);
+            if (ev->fd >= nfds) nfds = ev->fd+1;
+            dlog("~~~~ nfds = %d ~~~~", nfds);
+            break;
+        }
+    }
+    MUTEX_RELEASE();
+    dlog("~~~~ -ril_event_add ~~~~");
+}
+
+// Add timer event
+void ril_timer_add(struct ril_event * ev, struct timeval * tv)
+{
+    dlog("~~~~ +ril_timer_add ~~~~");
+    MUTEX_ACQUIRE();
+
+    struct ril_event * list;
+    if (tv != NULL) {
+        // add to timer list
+        list = timer_list.next;
+        ev->fd = -1; // make sure fd is invalid
+
+        struct timeval now;
+        getNow(&now);
+        timeradd(&now, tv, &ev->timeout);
+
+        // keep list sorted
+        while (timercmp(&list->timeout, &ev->timeout, < )
+                && (list != &timer_list)) {
+            list = list->next;
+        }
+        // list now points to the first event older than ev
+        addToList(ev, list);
+    }
+
+    MUTEX_RELEASE();
+    dlog("~~~~ -ril_timer_add ~~~~");
+}
+
+// Remove event from watch or timer list
+void ril_event_del(struct ril_event * ev)
+{
+    dlog("~~~~ +ril_event_del ~~~~");
+    MUTEX_ACQUIRE();
+
+    if (ev->index < 0 || ev->index >= MAX_FD_EVENTS) {
+        MUTEX_RELEASE();
+        return;
+    }
+
+    removeWatch(ev, ev->index);
+
+    MUTEX_RELEASE();
+    dlog("~~~~ -ril_event_del ~~~~");
+}
+
+#if DEBUG
+static void printReadies(fd_set * rfds)
+{
+    for (int i = 0; (i < MAX_FD_EVENTS); i++) {
+        struct ril_event * rev = watch_table[i];
+        if (rev != NULL && FD_ISSET(rev->fd, rfds)) {
+          dlog("DON: fd=%d is ready", rev->fd);
+        }
+    }
+}
+#else
+#define printReadies(rfds) do {} while(0)
+#endif
+
+void ril_event_loop()
+{
+    int n;
+    fd_set rfds;
+    struct timeval tv;
+    struct timeval * ptv;
+
+    for (;;) {
+
+        // make local copy of read fd_set
+        memcpy(&rfds, &readFds, sizeof(fd_set));
+        if (-1 == calcNextTimeout(&tv)) {
+            // no pending timers; block indefinitely
+            dlog("~~~~ no timers; blocking indefinitely ~~~~");
+            ptv = NULL;
+        } else {
+            dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec);
+            ptv = &tv;
+        }
+        printReadies(&rfds);
+        n = select(nfds, &rfds, NULL, NULL, ptv);
+        printReadies(&rfds);
+        dlog("~~~~ %d events fired ~~~~", n);
+        if (n < 0) {
+            if (errno == EINTR) continue;
+
+            ALOGE("ril_event: select error (%d)", errno);
+            // bail?
+            return;
+        }
+
+        // Check for timeouts
+        processTimeouts();
+        // Check for read-ready
+        processReadReadies(&rfds, n);
+        // Fire away
+        firePending();
+    }
+}