1/* //device/system/rild/rild.c
2**
3** Copyright 2006 The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <dlfcn.h>
21#include <string.h>
22#include <stdint.h>
23#include <unistd.h>
24#include <fcntl.h>
25#include <errno.h>
26
27#include <telephony/ril.h>
28#define LOG_TAG "RILD"
29#include <log/log.h>
30#include <cutils/properties.h>
31#include <cutils/sockets.h>
32#include <sys/capability.h>
33#include <sys/prctl.h>
34#include <sys/stat.h>
35#include <sys/types.h>
36#include <libril/ril_ex.h>
37
38#if defined(PRODUCT_COMPATIBLE_PROPERTY)
39#define LIB_PATH_PROPERTY   "vendor.rild.libpath"
40#define LIB_ARGS_PROPERTY   "vendor.rild.libargs"
41#else
42#define LIB_PATH_PROPERTY   "rild.libpath"
43#define LIB_ARGS_PROPERTY   "rild.libargs"
44#endif
45#define MAX_LIB_ARGS        16
46
47static void usage(const char *argv0) {
48    fprintf(stderr, "Usage: %s -l <ril impl library> [-- <args for impl library>]\n", argv0);
49    exit(EXIT_FAILURE);
50}
51
52extern char ril_service_name_base[MAX_SERVICE_NAME_LENGTH];
53extern char ril_service_name[MAX_SERVICE_NAME_LENGTH];
54
55extern void RIL_register (const RIL_RadioFunctions *callbacks);
56extern void rilc_thread_pool ();
57
58extern void RIL_register_socket (const RIL_RadioFunctions *(*rilUimInit)
59        (const struct RIL_Env *, int, char **), RIL_SOCKET_TYPE socketType, int argc, char **argv);
60
61extern void RIL_onRequestComplete(RIL_Token t, RIL_Errno e,
62        void *response, size_t responselen);
63
64extern void RIL_onRequestAck(RIL_Token t);
65
66#if defined(ANDROID_MULTI_SIM)
67extern void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
68        size_t datalen, RIL_SOCKET_ID socket_id);
69#else
70extern void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
71        size_t datalen);
72#endif
73
74extern void RIL_requestTimedCallback (RIL_TimedCallback callback,
75        void *param, const struct timeval *relativeTime);
76
77
78static struct RIL_Env s_rilEnv = {
79    RIL_onRequestComplete,
80    RIL_onUnsolicitedResponse,
81    RIL_requestTimedCallback,
82    RIL_onRequestAck
83};
84
85extern void RIL_startEventLoop();
86
87static int make_argv(char * args, char ** argv) {
88    // Note: reserve argv[0]
89    int count = 1;
90    char * tok;
91    char * s = args;
92
93    while ((tok = strtok(s, " \0"))) {
94        argv[count] = tok;
95        s = NULL;
96        count++;
97    }
98    return count;
99}
100
101int main(int argc, char **argv) {
102    // vendor ril lib path either passed in as -l parameter, or read from rild.libpath property
103    const char *rilLibPath = NULL;
104    // ril arguments either passed in as -- parameter, or read from rild.libargs property
105    char **rilArgv;
106    // handle for vendor ril lib
107    void *dlHandle;
108    // Pointer to ril init function in vendor ril
109    const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
110    // Pointer to sap init function in vendor ril
111    const RIL_RadioFunctions *(*rilUimInit)(const struct RIL_Env *, int, char **);
112    const char *err_str = NULL;
113
114    // functions returned by ril init function in vendor ril
115    const RIL_RadioFunctions *funcs;
116    // lib path from rild.libpath property (if it's read)
117    char libPath[PROPERTY_VALUE_MAX];
118    // flat to indicate if -- parameters are present
119    unsigned char hasLibArgs = 0;
120
121    int i;
122    // ril/socket id received as -c parameter, otherwise set to 0
123    const char *clientId = NULL;
124
125    RLOGD("**RIL Daemon Started**");
126    RLOGD("**RILd param count=%d**", argc);
127
128    umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
129    for (i = 1; i < argc ;) {
130        if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {
131            rilLibPath = argv[i + 1];
132            i += 2;
133        } else if (0 == strcmp(argv[i], "--")) {
134            i++;
135            hasLibArgs = 1;
136            break;
137        } else if (0 == strcmp(argv[i], "-c") &&  (argc - i > 1)) {
138            clientId = argv[i+1];
139            i += 2;
140        } else {
141            usage(argv[0]);
142        }
143    }
144
145    if (clientId == NULL) {
146        clientId = "0";
147    } else if (atoi(clientId) >= MAX_RILDS) {
148        RLOGE("Max Number of rild's supported is: %d", MAX_RILDS);
149        exit(0);
150    }
151    if (strncmp(clientId, "0", MAX_CLIENT_ID_LENGTH)) {
152        snprintf(ril_service_name, sizeof(ril_service_name), "%s%s", ril_service_name_base,
153                 clientId);
154    }
155
156    if (rilLibPath == NULL) {
157        if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
158            // No lib sepcified on the command line, and nothing set in props.
159            // Assume "no-ril" case.
160            goto done;
161        } else {
162            rilLibPath = libPath;
163        }
164    }
165
166    dlHandle = dlopen(rilLibPath, RTLD_NOW);
167
168    if (dlHandle == NULL) {
169        RLOGE("dlopen failed: %s", dlerror());
170        exit(EXIT_FAILURE);
171    }
172
173    RIL_startEventLoop();
174
175    rilInit =
176        (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))
177        dlsym(dlHandle, "RIL_Init");
178
179    if (rilInit == NULL) {
180        RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath);
181        exit(EXIT_FAILURE);
182    }
183
184    dlerror(); // Clear any previous dlerror
185    rilUimInit =
186        (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))
187        dlsym(dlHandle, "RIL_SAP_Init");
188    err_str = dlerror();
189    if (err_str) {
190        RLOGW("RIL_SAP_Init not defined or exported in %s: %s\n", rilLibPath, err_str);
191    } else if (!rilUimInit) {
192        RLOGW("RIL_SAP_Init defined as null in %s. SAP Not usable\n", rilLibPath);
193    }
194
195    if (hasLibArgs) {
196        rilArgv = argv + i - 1;
197        argc = argc -i + 1;
198    } else {
199        static char * newArgv[MAX_LIB_ARGS];
200        static char args[PROPERTY_VALUE_MAX];
201        rilArgv = newArgv;
202        property_get(LIB_ARGS_PROPERTY, args, "");
203        argc = make_argv(args, rilArgv);
204    }
205
206    rilArgv[argc++] = "-c";
207    rilArgv[argc++] = (char*)clientId;
208    RLOGD("RIL_Init argc = %d clientId = %s", argc, rilArgv[argc-1]);
209
210    // Make sure there's a reasonable argv[0]
211    rilArgv[0] = argv[0];
212
213    funcs = rilInit(&s_rilEnv, argc, rilArgv);
214    RLOGD("RIL_Init rilInit completed");
215
216    RIL_register(funcs);
217
218    RLOGD("RIL_Init RIL_register completed");
219
220    if (rilUimInit) {
221        RLOGD("RIL_register_socket started");
222        RIL_register_socket(rilUimInit, RIL_SAP_SOCKET, argc, rilArgv);
223    }
224
225    RLOGD("RIL_register_socket completed");
226
227done:
228
229    rilc_thread_pool();
230
231    RLOGD("RIL_Init starting sleep loop");
232    while (true) {
233        sleep(UINT32_MAX);
234    }
235}
236