OSDN Git Service

modify reference-ril to support 3G modem card on x86
[android-x86/hardware-ril.git] / rild / rild.c
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 <utils/Log.h>
30 #include <cutils/properties.h>
31 #include <cutils/sockets.h>
32 #include <linux/capability.h>
33 #include <linux/prctl.h>
34
35 #include <private/android_filesystem_config.h>
36
37 #define LIB_PATH_PROPERTY   "rild.libpath"
38 #define LIB_ARGS_PROPERTY   "rild.libargs"
39 #define MAX_LIB_ARGS        16
40
41 static void usage(const char *argv0)
42 {
43     fprintf(stderr, "Usage: %s -l <ril impl library> [-- <args for impl library>]\n", argv0);
44     exit(-1);
45 }
46
47 extern void RIL_register (const RIL_RadioFunctions *callbacks);
48
49 extern void RIL_onRequestComplete(RIL_Token t, RIL_Errno e,
50                            void *response, size_t responselen);
51
52 extern void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
53                                 size_t datalen);
54
55 extern void RIL_requestTimedCallback (RIL_TimedCallback callback,
56                                void *param, const struct timeval *relativeTime);
57
58
59 static struct RIL_Env s_rilEnv = {
60     RIL_onRequestComplete,
61     RIL_onUnsolicitedResponse,
62     RIL_requestTimedCallback
63 };
64
65 extern void RIL_startEventLoop();
66
67 static int make_argv(char * args, char ** argv)
68 {
69     // Note: reserve argv[0]
70     int count = 1;
71     char * tok;
72     char * s = args;
73
74     while ((tok = strtok(s, " \0"))) {
75         argv[count] = tok;
76         s = NULL;
77         count++;
78     }
79     return count;
80 }
81
82 /*
83  * switchUser - Switches UID to radio, preserving CAP_NET_ADMIN capabilities.
84  * Our group, cache, was set by init.
85  */
86 void switchUser() {
87     prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
88     setuid(AID_RADIO);
89
90     struct __user_cap_header_struct header;
91     struct __user_cap_data_struct cap;
92     header.version = _LINUX_CAPABILITY_VERSION;
93     header.pid = 0;
94     cap.effective = cap.permitted = 1 << CAP_NET_ADMIN;
95     cap.inheritable = 0;
96     capset(&header, &cap);
97 }
98
99 int main(int argc, char **argv)
100 {
101     const char * rilLibPath = NULL;
102     char **rilArgv;
103     void *dlHandle;
104     const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
105     const RIL_RadioFunctions *funcs;
106     char libPath[PROPERTY_VALUE_MAX];
107     unsigned char hasLibArgs = 0;
108
109     int i;
110
111     for (i = 1; i < argc ;) {
112         if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {
113             rilLibPath = argv[i + 1];
114             i += 2;
115         } else if (0 == strcmp(argv[i], "--")) {
116             i++;
117             hasLibArgs = 1;
118             break;
119         } else {
120             usage(argv[0]);
121         }
122     }
123
124     if (rilLibPath == NULL) {
125         if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
126             // No lib sepcified on the command line, and nothing set in props.
127             // Assume "no-ril" case.
128             goto done;
129         } else {
130             rilLibPath = libPath;
131         }
132     }
133
134 #if 0
135     /* special override when in the emulator */
136     {
137         static char*  arg_overrides[3];
138         static char   arg_device[32];
139         int           done = 0;
140
141 #define  REFERENCE_RIL_PATH  "/system/lib/libreference-ril.so"
142
143         /* first, read /proc/cmdline into memory */
144         char          buffer[1024], *p, *q;
145         int           len;
146         int           fd = open("/proc/cmdline",O_RDONLY);
147
148         if (fd < 0) {
149             LOGD("could not open /proc/cmdline:%s", strerror(errno));
150             goto OpenLib;
151         }
152
153         do {
154             len = read(fd,buffer,sizeof(buffer)); }
155         while (len == -1 && errno == EINTR);
156
157         if (len < 0) {
158             LOGD("could not read /proc/cmdline:%s", strerror(errno));
159             close(fd);
160             goto OpenLib;
161         }
162         close(fd);
163
164         if (strstr(buffer, "android.qemud=") != NULL)
165         {
166             /* the qemud daemon is launched after rild, so
167             * give it some time to create its GSM socket
168             */
169             int  tries = 5;
170 #define  QEMUD_SOCKET_NAME    "qemud"
171
172             while (1) {
173                 int  fd;
174
175                 sleep(1);
176
177                 fd = socket_local_client(
178                             QEMUD_SOCKET_NAME,
179                             ANDROID_SOCKET_NAMESPACE_RESERVED,
180                             SOCK_STREAM );
181
182                 if (fd >= 0) {
183                     close(fd);
184                     snprintf( arg_device, sizeof(arg_device), "%s/%s",
185                                 ANDROID_SOCKET_DIR, QEMUD_SOCKET_NAME );
186
187                     arg_overrides[1] = "-s";
188                     arg_overrides[2] = arg_device;
189                     done = 1;
190                     break;
191                 }
192                 LOGD("could not connect to %s socket: %s",
193                     QEMUD_SOCKET_NAME, strerror(errno));
194                 if (--tries == 0)
195                     break;
196             }
197             if (!done) {
198                 LOGE("could not connect to %s socket (giving up): %s",
199                     QEMUD_SOCKET_NAME, strerror(errno));
200                 while(1)
201                     sleep(0x00ffffff);
202             }
203         }
204
205         /* otherwise, try to see if we passed a device name from the kernel */
206         if (!done) do {
207 #define  KERNEL_OPTION  "android.ril="
208 #define  DEV_PREFIX     "/dev/"
209
210             p = strstr( buffer, KERNEL_OPTION );
211             if (p == NULL)
212                 break;
213
214             p += sizeof(KERNEL_OPTION)-1;
215             q  = strpbrk( p, " \t\n\r" );
216             if (q != NULL)
217                 *q = 0;
218
219             snprintf( arg_device, sizeof(arg_device), DEV_PREFIX "%s", p );
220             arg_device[sizeof(arg_device)-1] = 0;
221             arg_overrides[1] = "-d";
222             arg_overrides[2] = arg_device;
223             done = 1;
224
225         } while (0);
226
227         if (done) {
228             argv = arg_overrides;
229             argc = 3;
230             i    = 1;
231             hasLibArgs = 1;
232             rilLibPath = REFERENCE_RIL_PATH;
233
234             LOGD("overriding with %s %s", arg_overrides[1], arg_overrides[2]);
235         }
236     }
237 OpenLib:
238 #endif
239     switchUser();
240
241     dlHandle = dlopen(rilLibPath, RTLD_NOW);
242
243     if (dlHandle == NULL) {
244         fprintf(stderr, "dlopen failed: %s\n", dlerror());
245         exit(-1);
246     }
247
248     RIL_startEventLoop();
249
250     rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
251
252     if (rilInit == NULL) {
253         fprintf(stderr, "RIL_Init not defined or exported in %s\n", rilLibPath);
254         exit(-1);
255     }
256
257     if (hasLibArgs) {
258         rilArgv = argv + i - 1;
259         argc = argc -i + 1;
260     } else {
261         static char * newArgv[MAX_LIB_ARGS];
262         static char args[PROPERTY_VALUE_MAX];
263         rilArgv = newArgv;
264         property_get(LIB_ARGS_PROPERTY, args, "");
265         argc = make_argv(args, rilArgv);
266     }
267
268     // Make sure there's a reasonable argv[0]
269     rilArgv[0] = argv[0];
270
271     funcs = rilInit(&s_rilEnv, argc, rilArgv);
272
273     RIL_register(funcs);
274
275 done:
276
277     while(1) {
278         // sleep(UINT32_MAX) seems to return immediately on bionic
279         sleep(0x00ffffff);
280     }
281 }
282