summaryrefslogtreecommitdiffstats
path: root/ril/libril/ril_event.cpp
diff options
context:
space:
mode:
authorHoward Su <howard0su@gmail.com>2015-01-07 15:55:57 +0800
committersbrissen <sbrissen@hotmail.com>2015-04-03 08:23:16 -0400
commit56b8dcfa3094f93698dda9f6731fa845f00ef287 (patch)
treea5572f414faf8c83b02cc82788785367aa0d5c9c /ril/libril/ril_event.cpp
parent6b9cd5f8b49db8d5dab0e7042a1bc7ab333bbe4b (diff)
downloadandroid_hardware_samsung-56b8dcfa3094f93698dda9f6731fa845f00ef287.tar.gz
android_hardware_samsung-56b8dcfa3094f93698dda9f6731fa845f00ef287.tar.bz2
android_hardware_samsung-56b8dcfa3094f93698dda9f6731fa845f00ef287.zip
libril: Merge xmm6262 and xmm6260 to single lib.
The difference between two libs are very minor, includes one hack around ucsInfo and the logic to adjust signal strength. Besides that other diffs are some logs. The new version of code is minaly based on xmm6262, especially the logic to adjust singal strength. Merge them to easy maintain the code. Change-Id: I76390541d017576591860c8701bb9763c460b8be
Diffstat (limited to 'ril/libril/ril_event.cpp')
-rw-r--r--ril/libril/ril_event.cpp385
1 files changed, 385 insertions, 0 deletions
diff --git a/ril/libril/ril_event.cpp b/ril/libril/ril_event.cpp
new file mode 100644
index 0000000..9d2954e
--- /dev/null
+++ b/ril/libril/ril_event.cpp
@@ -0,0 +1,385 @@
+/* //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...) RLOGD( 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;
+
+ RLOGE("ril_event: select error (%d)", errno);
+ // bail?
+ return;
+ }
+
+ // Check for timeouts
+ processTimeouts();
+ // Check for read-ready
+ processReadReadies(&rfds, n);
+ // Fire away
+ firePending();
+ }
+}