100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/* //device/libs/telephony/ril_event.cpp
200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project**
300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** Copyright 2008, The Android Open Source Project
400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project**
5510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville** Licensed under the Apache License, Version 2.0 (the "License");
6510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville** you may not use this file except in compliance with the License.
7510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville** You may obtain a copy of the License at
800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project**
9510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville**     http://www.apache.org/licenses/LICENSE-2.0
1000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project**
11510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville** Unless required by applicable law or agreed to in writing, software
12510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville** distributed under the License is distributed on an "AS IS" BASIS,
13510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville** See the License for the specific language governing permissions and
1500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** limitations under the License.
1600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project*/
1700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
1800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define LOG_TAG "RILC"
1900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
2000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <stdlib.h>
2100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <unistd.h>
2200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <errno.h>
2300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <fcntl.h>
2400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <utils/Log.h>
2500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <ril_event.h>
2600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <string.h>
2700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <sys/time.h>
2800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <time.h>
2900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
3000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <pthread.h>
3100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic pthread_mutex_t listMutex;
3200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define MUTEX_ACQUIRE() pthread_mutex_lock(&listMutex)
3300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define MUTEX_RELEASE() pthread_mutex_unlock(&listMutex)
3400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define MUTEX_INIT() pthread_mutex_init(&listMutex, NULL)
3500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define MUTEX_DESTROY() pthread_mutex_destroy(&listMutex)
3600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
3700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#ifndef timeradd
3800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define timeradd(tvp, uvp, vvp)						\
3900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project	do {								\
4000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project		(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec;		\
4100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project		(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec;       \
4200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project		if ((vvp)->tv_usec >= 1000000) {			\
4300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project			(vvp)->tv_sec++;				\
4400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project			(vvp)->tv_usec -= 1000000;			\
4500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project		}							\
4600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project	} while (0)
4700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#endif
4800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
4900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#ifndef timercmp
5000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define timercmp(a, b, op)               \
5100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        ((a)->tv_sec == (b)->tv_sec      \
5200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        ? (a)->tv_usec op (b)->tv_usec   \
5300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        : (a)->tv_sec op (b)->tv_sec)
5400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#endif
5500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
5600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#ifndef timersub
5700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define timersub(a, b, res)                           \
5800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    do {                                              \
5900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        (res)->tv_sec = (a)->tv_sec - (b)->tv_sec;    \
6000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        (res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
6100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if ((res)->tv_usec < 0) {                     \
6200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            (res)->tv_usec += 1000000;                \
6300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            (res)->tv_sec -= 1;                       \
6400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }                                             \
6500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    } while(0);
6600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#endif
6700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
6800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic fd_set readFds;
6900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int nfds = 0;
7000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
7100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic struct ril_event * watch_table[MAX_FD_EVENTS];
7200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic struct ril_event timer_list;
7300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic struct ril_event pending_list;
7400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
7500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define DEBUG 0
7600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
7700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#if DEBUG
784dcab4f90d2d49e40100e4888b1411dfbd1c9783Wink Saville#define dlog(x...) RLOGD( x )
7900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void dump_event(struct ril_event * ev)
8000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
8100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ Event %x ~~~~", (unsigned int)ev);
8200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("     next    = %x", (unsigned int)ev->next);
8300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("     prev    = %x", (unsigned int)ev->prev);
8400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("     fd      = %d", ev->fd);
8500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("     pers    = %d", ev->persist);
8600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("     timeout = %ds + %dus", (int)ev->timeout.tv_sec, (int)ev->timeout.tv_usec);
8700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("     func    = %x", (unsigned int)ev->func);
8800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("     param   = %x", (unsigned int)ev->param);
8900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~~~~~~~~~~~~~~~");
9000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
9100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#else
92510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville#define dlog(x...) do {} while(0)
93510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville#define dump_event(x) do {} while(0)
9400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#endif
9500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
9600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void getNow(struct timeval * tv)
9700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
9800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#ifdef HAVE_POSIX_CLOCKS
9900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    struct timespec ts;
10000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    clock_gettime(CLOCK_MONOTONIC, &ts);
10100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    tv->tv_sec = ts.tv_sec;
10200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    tv->tv_usec = ts.tv_nsec/1000;
10300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#else
10400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    gettimeofday(tv, NULL);
10500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#endif
10600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
10700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
10800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void init_list(struct ril_event * list)
10900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
11000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    memset(list, 0, sizeof(struct ril_event));
11100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    list->next = list;
11200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    list->prev = list;
11300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    list->fd = -1;
11400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
11500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
11600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void addToList(struct ril_event * ev, struct ril_event * list)
11700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
11800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->next = list;
11900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->prev = list->prev;
12000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->prev->next = ev;
12100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    list->prev = ev;
12200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dump_event(ev);
12300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
12400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
12500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void removeFromList(struct ril_event * ev)
12600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
12700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ Removing event ~~~~");
12800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dump_event(ev);
12900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
13000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->next->prev = ev->prev;
13100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->prev->next = ev->next;
13200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->next = NULL;
13300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->prev = NULL;
13400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
13500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
13600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
13700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void removeWatch(struct ril_event * ev, int index)
13800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
13900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    watch_table[index] = NULL;
14000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->index = -1;
14100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
14200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    FD_CLR(ev->fd, &readFds);
14300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
14400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    if (ev->fd+1 == nfds) {
14500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        int n = 0;
14600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
14700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        for (int i = 0; i < MAX_FD_EVENTS; i++) {
14800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            struct ril_event * rev = watch_table[i];
14900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
15000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            if ((rev != NULL) && (rev->fd > n)) {
15100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                n = rev->fd;
15200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            }
15300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }
154510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville        nfds = n + 1;
15500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        dlog("~~~~ nfds = %d ~~~~", nfds);
15600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
15700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
15800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
15900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void processTimeouts()
16000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
16100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ +processTimeouts ~~~~");
16200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    MUTEX_ACQUIRE();
16300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    struct timeval now;
16400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    struct ril_event * tev = timer_list.next;
16500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    struct ril_event * next;
16600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
16700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    getNow(&now);
16800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    // walk list, see if now >= ev->timeout for any events
16900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
17000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ Looking for timers <= %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec);
17100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    while ((tev != &timer_list) && (timercmp(&now, &tev->timeout, >))) {
17200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        // Timer expired
17300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        dlog("~~~~ firing timer ~~~~");
17400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        next = tev->next;
17500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        removeFromList(tev);
17600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        addToList(tev, &pending_list);
17700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        tev = next;
17800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
17900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    MUTEX_RELEASE();
18000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ -processTimeouts ~~~~");
18100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
18200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
18300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void processReadReadies(fd_set * rfds, int n)
18400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
18500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ +processReadReadies (%d) ~~~~", n);
18600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    MUTEX_ACQUIRE();
18700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
18800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) {
18900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        struct ril_event * rev = watch_table[i];
19000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if (rev != NULL && FD_ISSET(rev->fd, rfds)) {
19100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            addToList(rev, &pending_list);
19200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            if (rev->persist == false) {
19300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                removeWatch(rev, i);
19400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            }
19500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            n--;
19600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }
19700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
19800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
19900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    MUTEX_RELEASE();
20000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ -processReadReadies (%d) ~~~~", n);
20100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
20200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
20300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void firePending()
20400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
20500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ +firePending ~~~~");
20600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    struct ril_event * ev = pending_list.next;
20700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    while (ev != &pending_list) {
20800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        struct ril_event * next = ev->next;
20900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        removeFromList(ev);
210510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville        ev->func(ev->fd, 0, ev->param);
21100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        ev = next;
21200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
21300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ -firePending ~~~~");
21400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
21500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
21600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int calcNextTimeout(struct timeval * tv)
21700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
21800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    struct ril_event * tev = timer_list.next;
21900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    struct timeval now;
22000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
22100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    getNow(&now);
22200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
22300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    // Sorted list, so calc based on first node
22400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    if (tev == &timer_list) {
22500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        // no pending timers
22600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        return -1;
22700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
22800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
22900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ now = %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec);
23000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ next = %ds + %dus ~~~~",
23100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            (int)tev->timeout.tv_sec, (int)tev->timeout.tv_usec);
23200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    if (timercmp(&tev->timeout, &now, >)) {
23300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        timersub(&tev->timeout, &now, tv);
23400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    } else {
23500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        // timer already expired.
23600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        tv->tv_sec = tv->tv_usec = 0;
23700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
23800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    return 0;
23900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
24000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
24100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project// Initialize internal data structs
24200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid ril_event_init()
24300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
24400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    MUTEX_INIT();
24500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
24600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    FD_ZERO(&readFds);
24700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    init_list(&timer_list);
24800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    init_list(&pending_list);
24900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    memset(watch_table, 0, sizeof(watch_table));
25000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
25100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
25200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project// Initialize an event
25300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)
25400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
25500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ ril_event_set %x ~~~~", (unsigned int)ev);
25600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    memset(ev, 0, sizeof(struct ril_event));
25700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->fd = fd;
25800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->index = -1;
25900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->persist = persist;
26000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->func = func;
26100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    ev->param = param;
26200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    fcntl(fd, F_SETFL, O_NONBLOCK);
26300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
26400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
26500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project// Add event to watch list
26600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid ril_event_add(struct ril_event * ev)
26700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
26800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ +ril_event_add ~~~~");
26900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    MUTEX_ACQUIRE();
27000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    for (int i = 0; i < MAX_FD_EVENTS; i++) {
27100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if (watch_table[i] == NULL) {
27200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            watch_table[i] = ev;
27300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            ev->index = i;
27400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            dlog("~~~~ added at %d ~~~~", i);
27500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            dump_event(ev);
27600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            FD_SET(ev->fd, &readFds);
27700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            if (ev->fd >= nfds) nfds = ev->fd+1;
27800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            dlog("~~~~ nfds = %d ~~~~", nfds);
27900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            break;
280510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville        }
28100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
28200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    MUTEX_RELEASE();
28300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ -ril_event_add ~~~~");
28400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
28500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
28600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project// Add timer event
28700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid ril_timer_add(struct ril_event * ev, struct timeval * tv)
28800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
28900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ +ril_timer_add ~~~~");
29000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    MUTEX_ACQUIRE();
29100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
29200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    struct ril_event * list;
29300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    if (tv != NULL) {
29400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        // add to timer list
29500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        list = timer_list.next;
29600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        ev->fd = -1; // make sure fd is invalid
29700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
29800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        struct timeval now;
29900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        getNow(&now);
30000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        timeradd(&now, tv, &ev->timeout);
30100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
30200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        // keep list sorted
30300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        while (timercmp(&list->timeout, &ev->timeout, < )
30400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                && (list != &timer_list)) {
30500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            list = list->next;
30600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }
30700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        // list now points to the first event older than ev
30800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        addToList(ev, list);
309510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville    }
31000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
31100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    MUTEX_RELEASE();
31200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ -ril_timer_add ~~~~");
31300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
31400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
31500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project// Remove event from watch or timer list
31600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid ril_event_del(struct ril_event * ev)
31700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
3182932f31296822b86ed945e09cadaabf2a453843cWink Saville    dlog("~~~~ +ril_event_del ~~~~");
31900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    MUTEX_ACQUIRE();
32000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
32100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    if (ev->index < 0 || ev->index >= MAX_FD_EVENTS) {
32211b35e613debbc9bcc162111d104e4c9f90fdbb8Axel Lin        MUTEX_RELEASE();
32300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        return;
32400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
32500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
32600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    removeWatch(ev, ev->index);
32700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
32800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    MUTEX_RELEASE();
32900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlog("~~~~ -ril_event_del ~~~~");
33000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
33100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
332510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville#if DEBUG
333510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Savillestatic void printReadies(fd_set * rfds)
334510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville{
335510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville    for (int i = 0; (i < MAX_FD_EVENTS); i++) {
336510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville        struct ril_event * rev = watch_table[i];
337510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville        if (rev != NULL && FD_ISSET(rev->fd, rfds)) {
338510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville          dlog("DON: fd=%d is ready", rev->fd);
339510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville        }
340510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville    }
341510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville}
342510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville#else
343510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville#define printReadies(rfds) do {} while(0)
344510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville#endif
345510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville
34600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid ril_event_loop()
34700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
34800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    int n;
34900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    fd_set rfds;
35000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    struct timeval tv;
35100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    struct timeval * ptv;
35200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
35300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
35400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    for (;;) {
35500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
35600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        // make local copy of read fd_set
35700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        memcpy(&rfds, &readFds, sizeof(fd_set));
35800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if (-1 == calcNextTimeout(&tv)) {
35900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            // no pending timers; block indefinitely
36000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            dlog("~~~~ no timers; blocking indefinitely ~~~~");
36100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            ptv = NULL;
36200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        } else {
36300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec);
36400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            ptv = &tv;
36500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }
366510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville        printReadies(&rfds);
36700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        n = select(nfds, &rfds, NULL, NULL, ptv);
368510a9bc7e2444cdb2b6a923ca3c4d0b45eebc400Wink Saville        printReadies(&rfds);
36900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        dlog("~~~~ %d events fired ~~~~", n);
37000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if (n < 0) {
37100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            if (errno == EINTR) continue;
37200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
3734dcab4f90d2d49e40100e4888b1411dfbd1c9783Wink Saville            RLOGE("ril_event: select error (%d)", errno);
37400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            // bail?
37500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            return;
37600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }
37700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
37800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        // Check for timeouts
37900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        processTimeouts();
38000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        // Check for read-ready
38100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        processReadReadies(&rfds, n);
38200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        // Fire away
38300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        firePending();
38400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
38500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
386