100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/* //device/system/rild/rild.c
200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project**
3d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen** Copyright 2006 The Android Open Source Project
400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project**
500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** you may not use this file except in compliance with the License.
700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** You may obtain a copy of the License at
800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project**
900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
1000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project**
1100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
1200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
1300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** 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#include <stdio.h>
1900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <stdlib.h>
2000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <dlfcn.h>
2100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <string.h>
2200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <stdint.h>
2300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <unistd.h>
2400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <fcntl.h>
2500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <errno.h>
2600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
2700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <telephony/ril.h>
2800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define LOG_TAG "RILD"
2900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <utils/Log.h>
3000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <cutils/properties.h>
3100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <cutils/sockets.h>
32fe4e1ec0233967f537e21d1b2ae30e7d33a97051Nick Kralevich#include <sys/capability.h>
335d0cb9ee42b4f192b039dd6b6c58dcb40c830a14Elliott Hughes#include <sys/prctl.h>
3400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
3500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <private/android_filesystem_config.h>
36385a73934b05fd28915e0ae17020dbfe3b20afd4Vladimir Chtchetkine#include "hardware/qemu_pipe.h"
3700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
3800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define LIB_PATH_PROPERTY   "rild.libpath"
3900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define LIB_ARGS_PROPERTY   "rild.libargs"
4000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define MAX_LIB_ARGS        16
4100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
4200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void usage(const char *argv0)
4300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
4400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    fprintf(stderr, "Usage: %s -l <ril impl library> [-- <args for impl library>]\n", argv0);
45e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes    exit(EXIT_FAILURE);
4600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
4700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
48d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohenextern char rild[MAX_SOCKET_NAME_LENGTH];
49d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen
5000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectextern void RIL_register (const RIL_RadioFunctions *callbacks);
5100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
5200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectextern void RIL_onRequestComplete(RIL_Token t, RIL_Errno e,
5300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                           void *response, size_t responselen);
5400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
55d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen
56d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen#if defined(ANDROID_MULTI_SIM)
57d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohenextern void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
58d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen                                size_t datalen, RIL_SOCKET_ID socket_id);
59d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen#else
6000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectextern void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
6100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                                size_t datalen);
62d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen#endif
6300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
642932f31296822b86ed945e09cadaabf2a453843cWink Savilleextern void RIL_requestTimedCallback (RIL_TimedCallback callback,
6500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                               void *param, const struct timeval *relativeTime);
6600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
6700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
6800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic struct RIL_Env s_rilEnv = {
6900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    RIL_onRequestComplete,
7000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    RIL_onUnsolicitedResponse,
712932f31296822b86ed945e09cadaabf2a453843cWink Saville    RIL_requestTimedCallback
7200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project};
7300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
7400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectextern void RIL_startEventLoop();
7500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
7600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int make_argv(char * args, char ** argv)
7700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
7800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    // Note: reserve argv[0]
7900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    int count = 1;
8000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    char * tok;
8100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    char * s = args;
8200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
8300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    while ((tok = strtok(s, " \0"))) {
8400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        argv[count] = tok;
8500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        s = NULL;
8600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        count++;
8700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
8800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    return count;
8900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
9000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
9100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/*
9200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * switchUser - Switches UID to radio, preserving CAP_NET_ADMIN capabilities.
9300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Our group, cache, was set by init.
9400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */
9500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid switchUser() {
9600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
9700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    setuid(AID_RADIO);
9800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
9900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    struct __user_cap_header_struct header;
100e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes    memset(&header, 0, sizeof(header));
101e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes    header.version = _LINUX_CAPABILITY_VERSION_3;
10200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    header.pid = 0;
103e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes
104e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes    struct __user_cap_data_struct data[2];
105e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes    memset(&data, 0, sizeof(data));
106e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes
107e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes    data[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN);
108e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes    data[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN);
109e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes
110e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes    data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
111e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes    data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
112e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes
113e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes    if (capset(&header, &data[0]) == -1) {
114e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes        RLOGE("capset failed: %s", strerror(errno));
115e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes        exit(EXIT_FAILURE);
116e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes    }
11700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
11800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
11900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectint main(int argc, char **argv)
12000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{
12100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    const char * rilLibPath = NULL;
12200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    char **rilArgv;
12300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    void *dlHandle;
12400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
12500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    const RIL_RadioFunctions *funcs;
12600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    char libPath[PROPERTY_VALUE_MAX];
12700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    unsigned char hasLibArgs = 0;
12800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
12900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    int i;
130d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    const char *clientId = NULL;
131d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    RLOGD("**RIL Daemon Started**");
132d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    RLOGD("**RILd param count=%d**", argc);
13300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
134aea7d5beb2d2cc4d49954f9d5158b8a53c3d7d31Nick Kralevich    umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
13500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    for (i = 1; i < argc ;) {
13600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {
13700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            rilLibPath = argv[i + 1];
13800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            i += 2;
13900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        } else if (0 == strcmp(argv[i], "--")) {
14000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            i++;
14100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            hasLibArgs = 1;
14200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            break;
143d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen        } else if (0 == strcmp(argv[i], "-c") &&  (argc - i > 1)) {
144d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen            clientId = argv[i+1];
145d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen            i += 2;
14600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        } else {
14700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            usage(argv[0]);
14800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }
14900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
15000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
151d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    if (clientId == NULL) {
152d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen        clientId = "0";
153d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    } else if (atoi(clientId) >= MAX_RILDS) {
154d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen        RLOGE("Max Number of rild's supported is: %d", MAX_RILDS);
155d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen        exit(0);
156d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    }
157d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    if (strncmp(clientId, "0", MAX_CLIENT_ID_LENGTH)) {
158d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen        RIL_setRilSocketName(strncat(rild, clientId, MAX_SOCKET_NAME_LENGTH));
159d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    }
160d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen
16100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    if (rilLibPath == NULL) {
16200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
16300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            // No lib sepcified on the command line, and nothing set in props.
16400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            // Assume "no-ril" case.
16500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            goto done;
16600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        } else {
16700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            rilLibPath = libPath;
16800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }
16900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
17000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
17100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    /* special override when in the emulator */
17200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#if 1
17300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    {
174d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen        static char*  arg_overrides[5];
17500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        static char   arg_device[32];
17600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        int           done = 0;
17700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
17860c1f5bd6932365413f27e3083b54c3a98f3299dVince Harron#define  REFERENCE_RIL_PATH  "libreference-ril.so"
17900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
18000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        /* first, read /proc/cmdline into memory */
18100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        char          buffer[1024], *p, *q;
18200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        int           len;
18300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        int           fd = open("/proc/cmdline",O_RDONLY);
18400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
18500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if (fd < 0) {
1868eb2a12cb7b525e74736300962a5f3848427275aWink Saville            RLOGD("could not open /proc/cmdline:%s", strerror(errno));
18700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            goto OpenLib;
18800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }
18900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
19000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        do {
19100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            len = read(fd,buffer,sizeof(buffer)); }
19200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        while (len == -1 && errno == EINTR);
19300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
19400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if (len < 0) {
1958eb2a12cb7b525e74736300962a5f3848427275aWink Saville            RLOGD("could not read /proc/cmdline:%s", strerror(errno));
19600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            close(fd);
19700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            goto OpenLib;
19800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }
19900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        close(fd);
20000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
20100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if (strstr(buffer, "android.qemud=") != NULL)
20200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        {
20300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            /* the qemud daemon is launched after rild, so
20400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            * give it some time to create its GSM socket
20500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            */
20600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            int  tries = 5;
207e6e6fb2ebbaae681ab45b866bb9bba57aff1c33cThe Android Open Source Project#define  QEMUD_SOCKET_NAME    "qemud"
20800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
20900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            while (1) {
21000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                int  fd;
21100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
21200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                sleep(1);
21300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
214385a73934b05fd28915e0ae17020dbfe3b20afd4Vladimir Chtchetkine                fd = qemu_pipe_open("qemud:gsm");
215385a73934b05fd28915e0ae17020dbfe3b20afd4Vladimir Chtchetkine                if (fd < 0) {
216385a73934b05fd28915e0ae17020dbfe3b20afd4Vladimir Chtchetkine                    fd = socket_local_client(
217385a73934b05fd28915e0ae17020dbfe3b20afd4Vladimir Chtchetkine                                QEMUD_SOCKET_NAME,
218385a73934b05fd28915e0ae17020dbfe3b20afd4Vladimir Chtchetkine                                ANDROID_SOCKET_NAMESPACE_RESERVED,
219385a73934b05fd28915e0ae17020dbfe3b20afd4Vladimir Chtchetkine                                SOCK_STREAM );
220385a73934b05fd28915e0ae17020dbfe3b20afd4Vladimir Chtchetkine                }
22100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                if (fd >= 0) {
22200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                    close(fd);
22300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                    snprintf( arg_device, sizeof(arg_device), "%s/%s",
22400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                                ANDROID_SOCKET_DIR, QEMUD_SOCKET_NAME );
22500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
22600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                    arg_overrides[1] = "-s";
22700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                    arg_overrides[2] = arg_device;
22800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                    done = 1;
22900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                    break;
23000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                }
2318eb2a12cb7b525e74736300962a5f3848427275aWink Saville                RLOGD("could not connect to %s socket: %s",
23200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                    QEMUD_SOCKET_NAME, strerror(errno));
23300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                if (--tries == 0)
23400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                    break;
23500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            }
23600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            if (!done) {
2378eb2a12cb7b525e74736300962a5f3848427275aWink Saville                RLOGE("could not connect to %s socket (giving up): %s",
23800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                    QEMUD_SOCKET_NAME, strerror(errno));
23900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                while(1)
24000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                    sleep(0x00ffffff);
24100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            }
24200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }
24300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
24400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        /* otherwise, try to see if we passed a device name from the kernel */
24500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if (!done) do {
24600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define  KERNEL_OPTION  "android.ril="
24700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define  DEV_PREFIX     "/dev/"
24800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
24900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            p = strstr( buffer, KERNEL_OPTION );
25000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            if (p == NULL)
25100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                break;
25200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
25300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            p += sizeof(KERNEL_OPTION)-1;
25400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            q  = strpbrk( p, " \t\n\r" );
25500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            if (q != NULL)
25600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project                *q = 0;
25700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
25800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            snprintf( arg_device, sizeof(arg_device), DEV_PREFIX "%s", p );
25900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            arg_device[sizeof(arg_device)-1] = 0;
26000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            arg_overrides[1] = "-d";
26100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            arg_overrides[2] = arg_device;
26200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            done = 1;
26300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
26400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        } while (0);
26500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
26600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        if (done) {
26700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            argv = arg_overrides;
26800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            argc = 3;
26900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            i    = 1;
27000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            hasLibArgs = 1;
27100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project            rilLibPath = REFERENCE_RIL_PATH;
27200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
2738eb2a12cb7b525e74736300962a5f3848427275aWink Saville            RLOGD("overriding with %s %s", arg_overrides[1], arg_overrides[2]);
27400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        }
27500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
27600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source ProjectOpenLib:
27700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#endif
27800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    switchUser();
27900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
28000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    dlHandle = dlopen(rilLibPath, RTLD_NOW);
28100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
28200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    if (dlHandle == NULL) {
2838eb2a12cb7b525e74736300962a5f3848427275aWink Saville        RLOGE("dlopen failed: %s", dlerror());
284e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes        exit(EXIT_FAILURE);
28500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
28600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
28700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    RIL_startEventLoop();
28800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
28900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
29000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
29100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    if (rilInit == NULL) {
2928eb2a12cb7b525e74736300962a5f3848427275aWink Saville        RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath);
293e2a70cfbf3b3db7ab87c5799fc264f52a8326ae2Elliott Hughes        exit(EXIT_FAILURE);
29400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
29500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
29600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    if (hasLibArgs) {
29700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        rilArgv = argv + i - 1;
29800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        argc = argc -i + 1;
29900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    } else {
30000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        static char * newArgv[MAX_LIB_ARGS];
30100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        static char args[PROPERTY_VALUE_MAX];
30200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        rilArgv = newArgv;
30300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        property_get(LIB_ARGS_PROPERTY, args, "");
30400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project        argc = make_argv(args, rilArgv);
30500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
30600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
307d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    rilArgv[argc++] = "-c";
308d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    rilArgv[argc++] = clientId;
309d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    RLOGD("RIL_Init argc = %d clientId = %s", argc, rilArgv[argc-1]);
310d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen
31100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    // Make sure there's a reasonable argv[0]
31200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    rilArgv[0] = argv[0];
31300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
31400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    funcs = rilInit(&s_rilEnv, argc, rilArgv);
315d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    RLOGD("RIL_Init rilInit completed");
31600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
31700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    RIL_register(funcs);
31800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
319d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    RLOGD("RIL_Init RIL_register completed");
320d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen
32100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectdone:
32200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project
323d365219a1873e42d2ff669e13a9fe6ce6973bd51Etan Cohen    RLOGD("RIL_Init starting sleep loop");
324164d2052f1bd1a9fe98fe90ca18f87438cba2a81Elliott Hughes    while (true) {
325164d2052f1bd1a9fe98fe90ca18f87438cba2a81Elliott Hughes        sleep(UINT32_MAX);
32600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project    }
32700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}
328