int main(int argc, char **argv) { const char * rilLibPath = NULL; char **rilArgv; void *dlHandle; const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **); const RIL_RadioFunctions *(*rilInitSocket)(const struct RIL_EnvSocket *, int, char **); const RIL_RadioFunctions *funcs; const RIL_RadioFunctionsSocket *funcsSocket; char libPath[PROPERTY_VALUE_MAX]; char socPath[PROPERTY_VALUE_MAX]; unsigned char hasLibArgs = 0; int i; const char *clientId = NULL; RLOGD("**RIL Daemon Started**"); RLOGD("**RILd param count=%d**", argc); #ifdef MTK_RIL_MD2 RLOGD("RILD started (MD2)"); #else RLOGD("RILD started"); #endif if (mtkInit() == -1) goto done; umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH); for (i = 1; i < argc ;) { if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) { rilLibPath = argv[i + 1]; i += 2; } else if (0 == strcmp(argv[i], "--")) { i++; hasLibArgs = 1; break; } else if (0 == strcmp(argv[i], "-c") && (argc - i > 1)) { clientId = argv[i+1]; i += 2; } else { usage(argv[0]); } } if (clientId == NULL) { clientId = "0"; } else if (atoi(clientId) >= MAX_RILDS) { RLOGE("Max Number of rild's supported is: %d", MAX_RILDS); exit(0); } if (strncmp(clientId, "0", MAX_CLIENT_ID_LENGTH)) { RIL_setRilSocketName(strncat(rild, clientId, MAX_SOCKET_NAME_LENGTH)); } if (rilLibPath == NULL) { #ifdef MTK_RIL_MD2 if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, "/system/lib/mtk-rilmd2.so")) { #else if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, "/system/lib/mtk-ril.so")) { #endif // No lib sepcified on the command line, and nothing set in props. // Assume "no-ril" case. goto done; } else { rilLibPath = libPath; } } /* special override when in the emulator */ #if 1 { static char* arg_overrides[5]; static char arg_device[32]; int done = 0; #ifdef MTK_RIL_MD2 #define REFERENCE_RIL_PATH "/system/lib/mtk-rilmd2.so" #else #define REFERENCE_RIL_PATH "/system/lib/mtk-ril.so" #endif /* first, read /proc/cmdline into memory */ char buffer[1024], *p, *q; int len; int fd = open("/proc/cmdline",O_RDONLY); if (fd < 0) { RLOGD("could not open /proc/cmdline:%s", strerror(errno)); goto OpenLib; } do { len = read(fd,buffer,sizeof(buffer)); } while (len == -1 && errno == EINTR); if (len < 0) { RLOGD("could not read /proc/cmdline:%s", strerror(errno)); close(fd); goto OpenLib; } close(fd); if (strstr(buffer, "android.qemud=") != NULL) { /* the qemud daemon is launched after rild, so * give it some time to create its GSM socket */ int tries = 5; #define QEMUD_SOCKET_NAME "qemud" while (1) { int fd; sleep(1); fd = qemu_pipe_open("qemud:gsm"); if (fd < 0) { fd = socket_local_client( QEMUD_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM ); } if (fd >= 0) { close(fd); snprintf( arg_device, sizeof(arg_device), "%s/%s", ANDROID_SOCKET_DIR, QEMUD_SOCKET_NAME ); arg_overrides[1] = "-s"; arg_overrides[2] = arg_device; done = 1; break; } RLOGD("could not connect to %s socket: %s", QEMUD_SOCKET_NAME, strerror(errno)); if (--tries == 0) break; } if (!done) { RLOGE("could not connect to %s socket (giving up): %s", QEMUD_SOCKET_NAME, strerror(errno)); while(1) sleep(0x00ffffff); } } /* otherwise, try to see if we passed a device name from the kernel */ if (!done) do { #define KERNEL_OPTION "android.ril=" #define DEV_PREFIX "/dev/" p = strstr( buffer, KERNEL_OPTION ); if (p == NULL) break; p += sizeof(KERNEL_OPTION)-1; q = strpbrk( p, " \t\n\r" ); if (q != NULL) *q = 0; snprintf( arg_device, sizeof(arg_device), DEV_PREFIX "%s", p ); arg_device[sizeof(arg_device)-1] = 0; arg_overrides[1] = "-d"; arg_overrides[2] = arg_device; done = 1; } while (0); if (done) { argv = arg_overrides; argc = 3; i = 1; hasLibArgs = 1; rilLibPath = REFERENCE_RIL_PATH; RLOGD("overriding with %s %s", arg_overrides[1], arg_overrides[2]); } } OpenLib: #endif switchUser(); #ifdef MTK_RIL_MD2 rilLibPath = "/system/lib/mtk-rilmd2.so"; #endif RLOGD("Open ril lib path: %s", rilLibPath); dlHandle = dlopen(rilLibPath, RTLD_NOW); if (dlHandle == NULL) { RLOGE("dlopen failed: %s", dlerror()); exit(EXIT_FAILURE); } RIL_startEventLoop(); rilInitSocket = (const int(*)(void))dlsym(dlHandle, "RIL_InitSocket"); if (rilInitSocket == NULL) { RLOGD("Vendor RIL do not need socket id!"); rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init"); if (rilInit == NULL) { RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath); exit(EXIT_FAILURE); } } else { RLOGD("vendor RIL need socket id"); } if (hasLibArgs) { rilArgv = argv + i - 1; argc = argc -i + 1; } else { static char * newArgv[MAX_LIB_ARGS]; static char args[PROPERTY_VALUE_MAX]; rilArgv = newArgv; #ifdef MTK_RIL_MD2 property_get(LIB_ARGS_PROPERTY, args, "-d /dev/ccci2_tty0"); #else property_get(LIB_ARGS_PROPERTY, args, "-d /dev/ttyC0"); #endif argc = make_argv(args, rilArgv); } rilArgv[argc++] = "-c"; rilArgv[argc++] = clientId; RLOGD("RIL_Init argc = %d clientId = %s", argc, rilArgv[argc-1]); // Make sure there's a reasonable argv[0] rilArgv[0] = argv[0]; if (rilInitSocket == NULL) { RLOGD("Old vendor ril! so RIL_register is called"); funcs = rilInit(&s_rilEnv, argc, rilArgv); RIL_register(funcs); } else { RLOGD("New vendor ril! so RIL_registerSocket is called"); funcsSocket = rilInitSocket(&s_rilEnvSocket, argc, rilArgv); RIL_registerSocket(funcsSocket); } done: RLOGD("RIL_Init starting sleep loop"); while (true) { sleep(UINT32_MAX); } }
void asyncOperation(void* ptr, asyncHandler handler, asyncDestructor dtor, const char* operationID) //operationID for debug { //Run it right away to see if it finished instantly. auto res = handler(ptr); switch(res) { case ASYNC_OPERATION_COMPLETE: RLOGI("Async operation %s completed", operationID); break; case ASYNC_OPERATION_RUNNING: while(length == BUFFER_SIZE) { RLOGW("To many async operations in flight! %d", length); asyncOperationsProcess(); } asyncBuffer[length++] = (AsyncItem){ptr, handler, dtor, operationID}; break; case ASYNC_OPERATION_FAILURE: RLOGE("Async operation %s failed", operationID); break; default: RLOGE("Async operation %s returned invalid result %d", operationID, res); break; } }
void asyncOperationsProcess() { for(int i = 0; i < length; i++) { auto item = asyncBuffer[i]; auto res = item.handler(item.payload); switch(res) { case ASYNC_OPERATION_COMPLETE: asyncBuffer[i--] = asyncBuffer[--length]; item.dtor(item.payload); RLOGI("Async operation %s completed", item.operationID); break; case ASYNC_OPERATION_RUNNING: //Do nothing break; case ASYNC_OPERATION_FAILURE: RLOGE("Async operation %s failed", item.operationID); asyncBuffer[i--] = asyncBuffer[--length]; item.dtor(item.payload); break; default: RLOGE("Async operation %s returned invalid result %d", item.operationID, res); asyncBuffer[i--] = asyncBuffer[--length]; item.dtor(item.payload); break; } } }
RILChannelCtx *openPPPDataChannel(int isBlocking) { RLOGI("openDataChannel"); RILChannelCtx* p_channel = &g_pppDataChannel; if (p_channel->fd > 0) closePPPDataChannel(); memset(p_channel, 0, sizeof(RILChannelCtx)); p_channel->fd = -1; /* fd of the AT channel */ int retryCounter = 0; int err = 0; while (p_channel->fd < 0 && retryCounter < 5) { do { RLOGI("set property for usb permission"); /* set this property than the permission of /dev/ttyACM0 will be set to 777 */ property_set("gsm.usb.ttyusb", "1"); if (isBlocking) p_channel->fd = open("/dev/ttyUSB0", O_RDWR); else p_channel->fd = open("/dev/ttyUSB0", O_RDWR | O_NONBLOCK); } while (p_channel->fd < 0 && errno == EINTR); if (p_channel->fd < 0) { perror ("opening AT interface. retrying..."); RLOGE("could not connect to %s: %s", "/dev/ttyUSB0", strerror(errno)); /* reduce polling time for usb connected */ sleep(1); /* never returns */ } else { struct termios ios; tcgetattr(p_channel->fd, &ios ); ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */ ios.c_iflag = 0; tcsetattr(p_channel->fd, TCSANOW, &ios ); } ++retryCounter; } if (p_channel->fd < 0) { RLOGE("/dev/ttyUSB0 open failed"); return NULL; } else { RLOGI("/dev/ttyUSB0 open success"); p_channel->ATBufferCur = p_channel->ATBuffer; p_channel->myName = "PPP_CHANNEL"; p_channel->id = ++g_channelIndex; p_channel->unsolHandler = 0; p_channel->readerClosed = 0; p_channel->responsePrefix = NULL; p_channel->smsPDU = NULL; p_channel->p_response = NULL; } return &g_pppDataChannel; }
static void *readerLoop(void *arg) { RILChannelCtx *p_channel = (RILChannelCtx *)arg; const char *readerName = p_channel->myName; RLOGI("%s is up", readerName); for (;; ) { const char *line; line = readline(p_channel); RLOGD("%s:%s", readerName, line); if (line == NULL) break; if (isSMSUnsolicited(line)) { char *line1; const char *line2; RLOGD("SMS Urc Received!"); // The scope of string returned by 'readline()' is valid only // till next call to 'readline()' hence making a copy of line // before calling readline again. line1 = strdup(line); line2 = readline(p_channel); if (line2 == NULL) { RLOGE("NULL line found in %s", readerName); break; } if (p_channel->unsolHandler != NULL) { RLOGD("%s: line1:%s,line2:%s", readerName, line1, line2); p_channel->unsolHandler(line1, line2, p_channel); } free(line1); } else { pthread_mutex_lock(&p_channel->commandmutex); RLOGD("%s Enter processLine", readerName); processLine(line, p_channel); pthread_mutex_unlock(&p_channel->commandmutex); } } RLOGE("%s Closed", readerName); onReaderClosed(p_channel); return NULL; }
int openDataChannel(char* deviceNote, int isBlocking, RILChannelCtx* p_channel, int channelId) { RLOGI("openDataChannel"); if (p_channel->fd > 0) closeDataChannel(p_channel); memset(p_channel, 0, sizeof(RILChannelCtx)); p_channel->fd = -1; /* fd of the AT channel */ int retryCounter = 0; int err = 0; while (p_channel->fd < 0 && retryCounter < 5) { do { RLOGI("set property for usb permission"); p_channel->fd = open(deviceNote, isBlocking? O_RDWR : (O_RDWR | O_NONBLOCK)); } while (p_channel->fd < 0 && errno == EINTR); if (p_channel->fd < 0) { perror ("opening AT interface. retrying..."); RLOGE("could not connect to %s: %s", "/dev/ttyUSB0", strerror(errno)); /* reduce polling time for usb connected */ sleep(1); /* never returns */ } else { struct termios ios; tcgetattr(p_channel->fd, &ios ); ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */ ios.c_iflag = 0; tcsetattr(p_channel->fd, TCSANOW, &ios ); } ++retryCounter; } if (p_channel->fd < 0) { RLOGE("%s open failed", deviceNote); return -1; } else { RLOGI("%s open success", deviceNote); p_channel->ATBufferCur = p_channel->ATBuffer; p_channel->myName = deviceNote; p_channel->id = ++channelId; p_channel->unsolHandler = 0; p_channel->readerClosed = 0; p_channel->responsePrefix = NULL; p_channel->smsPDU = NULL; p_channel->p_response = NULL; } return 0; }
/* * switchUser - Switches UID to radio, preserving CAP_NET_ADMIN capabilities. * Our group, cache, was set by init. */ void switchUser() { char debuggable[PROP_VALUE_MAX]; prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); setuid(AID_RADIO); struct __user_cap_header_struct header; memset(&header, 0, sizeof(header)); header.version = _LINUX_CAPABILITY_VERSION_3; header.pid = 0; struct __user_cap_data_struct data[2]; memset(&data, 0, sizeof(data)); data[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN); data[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN); data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW); data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW); if (capset(&header, &data[0]) == -1) { RLOGE("capset failed: %s", strerror(errno)); exit(EXIT_FAILURE); } /* * Debuggable build only: * Set DUMPABLE that was cleared by setuid() to have tombstone on RIL crash */ property_get("ro.debuggable", debuggable, "0"); if (strcmp(debuggable, "1") == 0) { prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } }
static void processLine(const char *line) { pthread_mutex_lock(&s_commandmutex); if (sp_response == NULL) { /* no command pending */ handleUnsolicited(line); } else if (isFinalResponseSuccess(line)) { sp_response->success = 1; handleFinalResponse(line); } else if (isFinalResponseError(line)) { sp_response->success = 0; handleFinalResponse(line); } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) { // See eg. TS 27.005 4.3 // Commands like AT+CMGS have a "> " prompt writeCtrlZ(s_smsPDU); s_smsPDU = NULL; } else switch (s_type) { case NO_RESULT: handleUnsolicited(line); break; case NUMERIC: if (sp_response->p_intermediates == NULL && isdigit(line[0]) ) { addIntermediate(line); } else { /* either we already have an intermediate response or the line doesn't begin with a digit */ handleUnsolicited(line); } break; case SINGLELINE: if (sp_response->p_intermediates == NULL && strStartsWith (line, s_responsePrefix) ) { addIntermediate(line); } else { /* we already have an intermediate response */ handleUnsolicited(line); } break; case MULTILINE: if (strStartsWith (line, s_responsePrefix)) { addIntermediate(line); } else { handleUnsolicited(line); } break; default: /* this should never be reached */ RLOGE("Unsupported AT command type %d\n", s_type); handleUnsolicited(line); break; } pthread_mutex_unlock(&s_commandmutex); }
static void checkGlError(const char* op) { for (GLint error = glGetError(); error; error = glGetError()) { switch (error) { case GL_INVALID_VALUE: RLOGE("after %s glError invalid value occured", op); break; case GL_INVALID_ENUM: RLOGE("after %s glError invalid enum occured", op); break; case GL_INVALID_OPERATION: RLOGE("after %s glError invalid operation occured", op); break; case GL_INVALID_FRAMEBUFFER_OPERATION: break; case EGL_CONTEXT_LOST: RLOGE("Context is lost!", ""); break; } } }
void closeDataChannel(RILChannelCtx* p_channel) { if (p_channel == NULL) { RLOGE("closeDataChannel invalid input argument"); return; } RLOGI("closeDataChannel [%d, %d]", p_channel->id, p_channel->fd); if (p_channel->fd >= 0) { close(p_channel->fd); } p_channel->fd = -1; }
/* * switchUser - Switches UID to radio, preserving CAP_NET_ADMIN capabilities. * Our group, cache, was set by init. */ void switchUser() { prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); setuid(AID_RADIO); struct __user_cap_header_struct header; memset(&header, 0, sizeof(header)); header.version = _LINUX_CAPABILITY_VERSION_3; header.pid = 0; struct __user_cap_data_struct data[2]; memset(&data, 0, sizeof(data)); data[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN); data[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN); data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW); data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW); if (capset(&header, &data[0]) == -1) { RLOGE("capset failed: %s", strerror(errno)); exit(EXIT_FAILURE); } }
/** * Called by atchannel when an unsolicited line appears * This is called on atchannel's reader thread. AT commands may * not be issued here */ static void onUnsolicited (const char *s, const char *sms_pdu, void * pChannel) { RLOGI("[Emu]get in onUnsolicited"); RLOGI("[Emu]command %s",s); char *line = NULL; int err; RIL_RadioState radioState = sState; RILChannelCtx * p_channel = (RILChannelCtx *) pChannel; #ifdef MTK_GEMINI if (MTK_RIL_SOCKET_2 == getRILIdByChannelCtx(p_channel)) { radioState = sState2; RLOGI("[Emu]state2"); } #endif /* Ignore unsolicited responses until we're initialized. * This is OK because the RIL library will poll for initial state */ if (radioState == RADIO_STATE_UNAVAILABLE) { return; } if (!(rilNwUnsolicited(s,sms_pdu,p_channel) || rilCcUnsolicited(s,sms_pdu, p_channel) || rilSsUnsolicited(s,sms_pdu, p_channel) || rilSmsUnsolicited(s,sms_pdu, p_channel) || rilStkUnsolicited(s,sms_pdu, p_channel) || rilOemUnsolicited(s,sms_pdu, p_channel) || rilDataUnsolicited(s,sms_pdu, p_channel)|| rilSimUnsolicited(s,sms_pdu, p_channel)) ) { RLOGE("Unhandled unsolicited result code: %s\n", s); } }
void RIL_startRILProxys(void) { int ret; int i; int proxysNum = getRilProxysNum(); for (i=0; i<proxysNum; i++) { pthread_attr_t attr; pthread_attr_init (&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); ret = pthread_create(&s_tid_proxy[i], &attr, proxyLoop,(void*) &s_Proxy[i]); if (ret < 0) { RLOGE("Failed to create proxy thread errno:%d", errno); assert(0); return; } LOGD("proxy %s is up, tid:%d",::proxyIdToString(i),(int) s_tid_proxy[i]); } }
int main(int argc, char **argv) { // vendor ril lib path either passed in as -l parameter, or read from rild.libpath property const char *rilLibPath = NULL; // ril arguments either passed in as -- parameter, or read from rild.libargs property char **rilArgv; // handle for vendor ril lib void *dlHandle; // Pointer to ril init function in vendor ril const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **); // Pointer to sap init function in vendor ril const RIL_RadioFunctions *(*rilUimInit)(const struct RIL_Env *, int, char **); const char *err_str = NULL; // functions returned by ril init function in vendor ril const RIL_RadioFunctions *funcs; // lib path from rild.libpath property (if it's read) char libPath[PROPERTY_VALUE_MAX]; // flat to indicate if -- parameters are present unsigned char hasLibArgs = 0; int i; // ril/socket id received as -c parameter, otherwise set to 0 const char *clientId = NULL; RLOGD("**RIL Daemon Started**"); RLOGD("**RILd param count=%d**", argc); umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH); for (i = 1; i < argc ;) { if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) { rilLibPath = argv[i + 1]; i += 2; } else if (0 == strcmp(argv[i], "--")) { i++; hasLibArgs = 1; break; } else if (0 == strcmp(argv[i], "-c") && (argc - i > 1)) { clientId = argv[i+1]; i += 2; } else { usage(argv[0]); } } if (clientId == NULL) { clientId = "0"; } else if (atoi(clientId) >= MAX_RILDS) { RLOGE("Max Number of rild's supported is: %d", MAX_RILDS); exit(0); } if (strncmp(clientId, "0", MAX_CLIENT_ID_LENGTH)) { snprintf(ril_service_name, sizeof(ril_service_name), "%s%s", ril_service_name_base, clientId); } if (rilLibPath == NULL) { if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) { // No lib sepcified on the command line, and nothing set in props. // Assume "no-ril" case. goto done; } else { rilLibPath = libPath; } } dlHandle = dlopen(rilLibPath, RTLD_NOW); if (dlHandle == NULL) { RLOGE("dlopen failed: %s", dlerror()); exit(EXIT_FAILURE); } RIL_startEventLoop(); rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **)) dlsym(dlHandle, "RIL_Init"); if (rilInit == NULL) { RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath); exit(EXIT_FAILURE); } dlerror(); // Clear any previous dlerror rilUimInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **)) dlsym(dlHandle, "RIL_SAP_Init"); err_str = dlerror(); if (err_str) { RLOGW("RIL_SAP_Init not defined or exported in %s: %s\n", rilLibPath, err_str); } else if (!rilUimInit) { RLOGW("RIL_SAP_Init defined as null in %s. SAP Not usable\n", rilLibPath); } if (hasLibArgs) { rilArgv = argv + i - 1; argc = argc -i + 1; } else { static char * newArgv[MAX_LIB_ARGS]; static char args[PROPERTY_VALUE_MAX]; rilArgv = newArgv; property_get(LIB_ARGS_PROPERTY, args, ""); argc = make_argv(args, rilArgv); } rilArgv[argc++] = "-c"; rilArgv[argc++] = (char*)clientId; RLOGD("RIL_Init argc = %d clientId = %s", argc, rilArgv[argc-1]); // Make sure there's a reasonable argv[0] rilArgv[0] = argv[0]; funcs = rilInit(&s_rilEnv, argc, rilArgv); RLOGD("RIL_Init rilInit completed"); RIL_register(funcs); RLOGD("RIL_Init RIL_register completed"); if (rilUimInit) { RLOGD("RIL_register_socket started"); RIL_register_socket(rilUimInit, RIL_SAP_SOCKET, argc, rilArgv); } RLOGD("RIL_register_socket completed"); rilc_thread_pool(); done: RLOGD("RIL_Init starting sleep loop"); while (true) { sleep(UINT32_MAX); } }
static void initializeCallback(void *param) { RLOGE ("[Emu]get in initializeCallback"); ATResponse *p_response = NULL; int err; RILId rid = *((RILId *)param); char property_value[5] = { 0 }; int current_share_modem = 0; current_share_modem = MTK_SHARE_MODEM_CURRENT; setRadioState (RADIO_STATE_OFF,rid); err = at_handshake(getDefaultChannelCtx(rid)); RLOGI("AT handshake: %d",err); /* note: we don't check errors here. Everything important will be handled in onATTimeout and onATReaderClosed */ /* atchannel is tolerant of echo but it must */ /* have verbose result codes */ at_send_command("ATE0Q0V1", NULL, getDefaultChannelCtx(rid)); /* No auto-answer */ at_send_command("ATS0=0", NULL,getDefaultChannelCtx(rid)); /* Extended errors */ at_send_command("AT+CMEE=1", NULL, getDefaultChannelCtx(rid)); /* Network registration events */ err = at_send_command("AT+CREG=2", &p_response, getDefaultChannelCtx(rid)); /* some handsets -- in tethered mode -- don't support CREG=2 */ if (err < 0 || p_response->success == 0) { at_send_command("AT+CREG=1", NULL, getDefaultChannelCtx(rid)); } at_response_free(p_response); /* GPRS registration events */ at_send_command("AT+CGREG=1", NULL, getDefaultChannelCtx(rid)); /* Call Waiting notifications */ at_send_command("AT+CCWA=1", NULL, getDefaultChannelCtx(rid)); //[Emu]TODO diff /* mtk00924: enable Call Progress notifications */ at_send_command("AT+ECPI=4294967295", NULL, getDefaultChannelCtx(rid)); /* Alternating voice/data off */ /* at_send_command("AT+CMOD=0", NULL, getDefaultChannelCtx(rid)); */ /* Not muted */ /* at_send_command("AT+CMUT=0", NULL, getDefaultChannelCtx(rid)); */ //[Emu]TODO diff /* +CSSU unsolicited supp service notifications */ at_send_command("AT+CSSN=1,1", NULL, getDefaultChannelCtx(rid)); //[Emu]TODO diff /* connected line identification on */ at_send_command("AT+COLP=1", NULL, getDefaultChannelCtx(rid)); //[Emu]TODO diff /* HEX character set */ at_send_command("AT+CSCS=\"UCS2\"", NULL, getDefaultChannelCtx(rid)); /* USSD unsolicited */ at_send_command("AT+CUSD=1", NULL, getDefaultChannelCtx(rid)); /* Enable +CGEV GPRS event notifications, but don't buffer */ at_send_command("AT+CGEREP=1,0", NULL, getDefaultChannelCtx(rid)); /* SMS PDU mode */ at_send_command("AT+CMGF=0", NULL, getDefaultChannelCtx(rid)); /* Initial CID table */ initialCidTable(); //[Emu]TODO diff /* Enable getting NITZ, include TZ and Operator Name*/ /* To Receive +CIEV: 9 and +CIEV: 10*/ //[Emu]TODO_1_ changed // at_send_command("AT+CTZR=1", NULL, getDefaultChannelCtx(rid)); //[Emu]TODO diff /* Enable getting CFU info +ECFU and speech info +ESPEECH*/ // at_send_command("AT+EINFO=114", NULL, getDefaultChannelCtx(rid)); //[Emu]TODO diff /* Enable get ECSQ URC */ //at_send_command("AT+ECSQ=2", NULL, getDefaultChannelCtx(rid)); //[Emu]TODO diff /* Enable get +CIEV:7 URC to receive SMS SIM Storage Status*/ // at_send_command("AT+CMER=1,0,0,2,0", NULL, getDefaultChannelCtx(rid)); //[Emu]TODO diff #ifdef MTK_VT3G324M_SUPPORT at_send_command("AT+CRC=1", NULL, getDefaultChannelCtx(rid)); #endif #ifdef MTK_GEMINI requestSimReset(rid); RLOGD("start rild bootup flow [%d, %d, %d, %d]", isDualTalkMode(), rid, RIL_is3GSwitched(), current_share_modem); if (isDualTalkMode()) { if (rid == MTK_RIL_SOCKET_1) { flightModeBoot(); bootupGetIccid(rid); //query ICCID after AT+ESIMS bootupGetImei(rid); bootupGetImeisv(rid); bootupGetBasebandVersion(rid); bootupGetCalData(rid); RLOGD("get SIM inserted status (DT) [%d]", sim_inserted_status); RIL_onUnsolicitedResponse(RIL_UNSOL_SIM_INSERTED_STATUS, &sim_inserted_status, sizeof(int), rid); } } else { if (current_share_modem == 1) { if (rid == MTK_RIL_SOCKET_1) { flightModeBoot(); bootupGetIccid(rid); //query ICCID after AT+ESIMS bootupGetImei(rid); bootupGetImeisv(rid); bootupGetBasebandVersion(rid); bootupGetCalData(rid); RLOGD("get SIM inserted status (Single) [%d]", sim_inserted_status); RIL_onUnsolicitedResponse(RIL_UNSOL_SIM_INSERTED_STATUS, &sim_inserted_status, sizeof(int), rid); } } else if (rid == MTK_RIL_SOCKET_2) { flightModeBoot(); bootupGetIccid(MTK_RIL_SOCKET_1); bootupGetIccid(MTK_RIL_SOCKET_2); bootupGetImei(MTK_RIL_SOCKET_1); bootupGetImei(MTK_RIL_SOCKET_2); bootupGetImeisv(MTK_RIL_SOCKET_1); bootupGetImeisv(MTK_RIL_SOCKET_2); bootupGetBasebandVersion(MTK_RIL_SOCKET_1); bootupGetBasebandVersion(MTK_RIL_SOCKET_2); bootupGetCalData(MTK_RIL_SOCKET_1); RLOGD("get SIM inserted status [%d]", sim_inserted_status); RIL_onUnsolicitedResponse(RIL_UNSOL_SIM_INSERTED_STATUS, &sim_inserted_status, sizeof(int), rid); } } #else flightModeBoot(); bootupGetIccid(rid); bootupGetImei(rid); bootupGetImeisv(rid); bootupGetBasebandVersion(rid); bootupGetCalData(rid); #endif /* MTK_GEMINI */ //[Emu]TODO diff /* assume radio is off on error */ if (isRadioOn(rid) > 0) { setRadioState (RADIO_STATE_SIM_NOT_READY,rid); } }
int main(int argc, char **argv) { const char * rilLibPath = NULL; char **rilArgv; void *dlHandle; const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **); const RIL_RadioFunctions *funcs; char libPath[PROPERTY_VALUE_MAX]; unsigned char hasLibArgs = 0; int modem_type = UNKNOWN_MODEM; int i; umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH); for (i = 1; i < argc ;) { if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) { rilLibPath = argv[i + 1]; i += 2; } else if (0 == strcmp(argv[i], "--")) { i++; hasLibArgs = 1; break; } else { usage(argv[0]); } } //Wait for device ready. if (rilLibPath == NULL) { while(UNKNOWN_MODEM == modem_type){ modem_type = runtime_3g_port_type(); ALOGD("Couldn't find proper modem, retrying..."); s_poll_device_cnt++; if (s_poll_device_cnt > MAX_POLL_DEVICE_CNT){ /* *Maybe no device right now, start to monitor *hotplug event later. */ start_uevent_monitor(); goto done; } sleep(5); } } start_uevent_monitor(); switch (modem_type){ case ZTE_MODEM: rilLibPath = REFERENCE_RIL_ZTE_PATH; break; case HUAWEI_MODEM: case AMAZON_MODEM: default: if (!rilLibPath) rilLibPath = REFERENCE_RIL_DEF_PATH; break; } RLOGE("ril lib path=%s\n", rilLibPath); if (rilLibPath == NULL) { if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) { // No lib sepcified on the command line, and nothing set in props. // Assume "no-ril" case. goto done; } else { rilLibPath = libPath; } } /* special override when in the emulator */ #if 1 { static char* arg_overrides[3]; static char arg_device[32]; int done = 0; #define REFERENCE_RIL_PATH "/system/lib/libreference-ril.so" /* first, read /proc/cmdline into memory */ char buffer[1024], *p, *q; int len; int fd = open("/proc/cmdline",O_RDONLY); if (fd < 0) { RLOGD("could not open /proc/cmdline:%s", strerror(errno)); goto OpenLib; } do { len = read(fd,buffer,sizeof(buffer)); } while (len == -1 && errno == EINTR); if (len < 0) { RLOGD("could not read /proc/cmdline:%s", strerror(errno)); close(fd); goto OpenLib; } close(fd); if (strstr(buffer, "android.qemud=") != NULL) { /* the qemud daemon is launched after rild, so * give it some time to create its GSM socket */ int tries = 5; #define QEMUD_SOCKET_NAME "qemud" while (1) { int fd; sleep(1); fd = qemu_pipe_open("qemud:gsm"); if (fd < 0) { fd = socket_local_client( QEMUD_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM ); } if (fd >= 0) { close(fd); snprintf( arg_device, sizeof(arg_device), "%s/%s", ANDROID_SOCKET_DIR, QEMUD_SOCKET_NAME ); arg_overrides[1] = "-s"; arg_overrides[2] = arg_device; done = 1; break; } RLOGD("could not connect to %s socket: %s", QEMUD_SOCKET_NAME, strerror(errno)); if (--tries == 0) break; } if (!done) { RLOGE("could not connect to %s socket (giving up): %s", QEMUD_SOCKET_NAME, strerror(errno)); while(1) sleep(0x00ffffff); } } /* otherwise, try to see if we passed a device name from the kernel */ if (!done) do { #define KERNEL_OPTION "android.ril=" #define DEV_PREFIX "/dev/" p = strstr( buffer, KERNEL_OPTION ); if (p == NULL) break; p += sizeof(KERNEL_OPTION)-1; q = strpbrk( p, " \t\n\r" ); if (q != NULL) *q = 0; snprintf( arg_device, sizeof(arg_device), DEV_PREFIX "%s", p ); arg_device[sizeof(arg_device)-1] = 0; arg_overrides[1] = "-d"; arg_overrides[2] = arg_device; done = 1; } while (0); if (done) { argv = arg_overrides; argc = 3; i = 1; hasLibArgs = 1; rilLibPath = REFERENCE_RIL_PATH; RLOGD("overriding with %s %s", arg_overrides[1], arg_overrides[2]); } } OpenLib: #endif switchUser(); dlHandle = dlopen(rilLibPath, RTLD_NOW); if (dlHandle == NULL) { RLOGE("dlopen failed: %s", dlerror()); exit(-1); } RIL_startEventLoop(); rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init"); if (rilInit == NULL) { RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath); exit(-1); } if (hasLibArgs) { rilArgv = argv + i - 1; argc = argc -i + 1; } else { static char * newArgv[MAX_LIB_ARGS]; static char args[PROPERTY_VALUE_MAX]; rilArgv = newArgv; property_get(LIB_ARGS_PROPERTY, args, ""); argc = make_argv(args, rilArgv); } // Make sure there's a reasonable argv[0] rilArgv[0] = argv[0]; funcs = rilInit(&s_rilEnv, argc, rilArgv); RIL_register(funcs); done: while(1) { // sleep(UINT32_MAX) seems to return immediately on bionic sleep(0x00ffffff); } }
static const char *readline() { ssize_t count; char *p_read = NULL; char *p_eol = NULL; char *ret; /* this is a little odd. I use *s_ATBufferCur == 0 to * mean "buffer consumed completely". If it points to a character, than * the buffer continues until a \0 */ if (*s_ATBufferCur == '\0') { /* empty buffer */ s_ATBufferCur = s_ATBuffer; *s_ATBufferCur = '\0'; p_read = s_ATBuffer; } else { /* *s_ATBufferCur != '\0' */ /* there's data in the buffer from the last read */ // skip over leading newlines while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') s_ATBufferCur++; p_eol = findNextEOL(s_ATBufferCur); if (p_eol == NULL) { /* a partial line. move it up and prepare to read more */ size_t len; len = strlen(s_ATBufferCur); memmove(s_ATBuffer, s_ATBufferCur, len + 1); p_read = s_ATBuffer + len; s_ATBufferCur = s_ATBuffer; } /* Otherwise, (p_eol !- NULL) there is a complete line */ /* that will be returned the while () loop below */ } while (p_eol == NULL) { if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) { RLOGE("ERROR: Input line exceeded buffer\n"); /* ditch buffer and start over again */ s_ATBufferCur = s_ATBuffer; *s_ATBufferCur = '\0'; p_read = s_ATBuffer; } do { count = read(s_fd, p_read, MAX_AT_RESPONSE - (p_read - s_ATBuffer)); } while (count < 0 && errno == EINTR); if (count > 0) { AT_DUMP( "<< ", p_read, count ); p_read[count] = '\0'; // skip over leading newlines while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') s_ATBufferCur++; p_eol = findNextEOL(s_ATBufferCur); p_read += count; } else if (count <= 0) { /* read error encountered or EOF reached */ if(count == 0) { RLOGD("atchannel: EOF reached"); } else { RLOGD("atchannel: read error %s", strerror(errno)); } return NULL; } } /* a full line in the buffer. Place a \0 over the \r and return */ ret = s_ATBufferCur; *p_eol = '\0'; s_ATBufferCur = p_eol + 1; /* this will always be <= p_read, */ /* and there will be a \0 at *p_read */ RLOGD("AT< %s\n", ret); return ret; }
static void emulator_gemini_opensocket() { int fd; int ret; for (;;) { fd = -1; RLOGI("[Emu]emulator_gemini_opensocket_in\n"); RLOGI("[Emu]s_device_socket %d\n",s_device_socket); RLOGI("[Emu]s_port %d\n",s_port); while (fd < 0) { if (s_port > 0) { fd = socket_loopback_client(s_port, SOCK_STREAM); RLOGI("[Emu]fd1 %d\n",fd); } else if (s_device_socket) { if (!strcmp(s_device_path, "/dev/socket/qemud")) { /* Qemu-specific control socket */ fd = socket_local_client( "qemud", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM ); RLOGI("[Emu]fd2 %d\n",fd); if (fd >= 0 ) { char answer[2]; if ( write(fd, "gsm", 3) != 3 || read(fd, answer, 2) != 2 || memcmp(answer, "OK", 2) != 0) { close(fd); fd = -1; } } } else { fd = socket_local_client( s_device_path, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM ); } RLOGI("[Emu]fd3 %d\n",fd); } else if (s_device_path != NULL) { fd = open (s_device_path, O_RDWR); if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) { /* disable echo on serial ports */ struct termios ios; tcgetattr( fd, &ios ); ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */ ios.c_iflag = 0; tcsetattr( fd, TCSANOW, &ios ); } RLOGI("[Emu]fd4 %d\n",fd); } if (fd < 0) { RLOGI("[Emu]fd<0"); perror ("opening AT interface. retrying..."); sleep(10); /* never returns */ } } s_closed = 0; ret = at_open_emulator(fd, onUnsolicited,is_gemini_emulator); if (ret < 0) { RLOGE ("AT error %d on at_open\n", ret); return 0; } RLOGI("[Emu]RIL_requestTimedCallback"); RIL_requestTimedCallback(initializeCallback, &s_pollSimId, &TIMEVAL_0); #ifdef MTK_GEMINI RIL_requestTimedCallback(initializeCallback, &s_pollSimId2, &TIMEVAL_0); #endif RLOGI("[Emu]RIL_requestTimedCallback out"); // Give initializeCallback a chance to dispatched, since // we don't presently have a cancellation mechanism sleep(1); waitForClose(); RLOGI("Re-opening after close"); } }
/** * Internal send_command implementation * Doesn't lock or call the timeout callback * * timeoutMsec == 0 means infinite timeout */ static int at_send_command_full_nolock(const char *command, ATCommandType type, const char *responsePrefix, const char *smspdu, long long timeoutMsec, ATResponse **pp_outResponse, RILChannelCtx *p_channel) { int err = 0; #ifndef USE_NP struct timespec ts; #endif /*USE_NP*/ if (p_channel->p_response != NULL) { err = AT_ERROR_COMMAND_PENDING; RLOGE("AT_ERROR_COMMAND_PENDING: %s", command); goto error; } err = writeline(command, p_channel); if (err < 0) goto error; p_channel->type = type; p_channel->responsePrefix = responsePrefix; p_channel->smsPDU = smspdu; p_channel->p_response = at_response_new(); #ifndef USE_NP if (timeoutMsec != 0) setTimespecRelative(&ts, timeoutMsec); #endif /*USE_NP*/ while (p_channel->p_response->finalResponse == NULL && p_channel->readerClosed == 0) { if (timeoutMsec != 0) { #ifdef USE_NP err = pthread_cond_timeout_np(&p_channel->commandcond, &p_channel->commandmutex, timeoutMsec); #else err = pthread_cond_timedwait(&p_channel->commandcond, &p_channel->commandmutex, &ts); #endif /*USE_NP*/ } else { err = pthread_cond_wait(&p_channel->commandcond, &p_channel->commandmutex); } if (err == ETIMEDOUT) { err = AT_ERROR_TIMEOUT; goto error; } } if (p_channel->readerClosed > 0) { err = AT_ERROR_CHANNEL_CLOSED; goto error; } if (pp_outResponse == NULL) { at_response_free(p_channel->p_response); } else { /* line reader stores intermediate responses in reverse order */ reverseIntermediates(p_channel->p_response); *pp_outResponse = p_channel->p_response; } p_channel->p_response = NULL; err = 0; error: clearPendingCommand(p_channel); return err; }
static void * mainLoop(void *param) { AT_DUMP("== ", "entering mainLoop()", -1 ); at_set_on_reader_closed(onATReaderClosed); at_set_on_timeout(onATTimeout); initRILChannels(); RLOGI("[Emu]mainloop_in"); RLOGI("[Emu]mainloop_in %d\n",s_device_socket); if(s_device_socket) { emulator_gemini_opensocket(); return NULL; } else { int ret; int i; RILChannelCtx * p_channel; for (;;) { for (i=0; i < RIL_SUPPORT_CHANNELS; i ++) { p_channel = getChannelCtxbyId(i); while (p_channel->fd < 0) { do { p_channel->fd = open(s_mux_path[i], O_RDWR); } while (p_channel->fd < 0 && errno == EINTR); if (p_channel->fd < 0) { perror ("opening AT interface. retrying..."); RLOGE("could not connect to %s: %s", s_mux_path[i], strerror(errno)); sleep(10); /* never returns */ } else { struct termios ios; tcgetattr(p_channel->fd, &ios ); ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */ ios.c_iflag = 0; tcsetattr(p_channel->fd, TCSANOW, &ios ); } } s_closed = 0; ret = at_open(p_channel->fd,onUnsolicited, p_channel); if (ret < 0) { RLOGE ("AT error %d on at_open\n", ret); return 0; } } RIL_requestTimedCallback(initializeCallback, &s_pollSimId, &TIMEVAL_0); #ifdef MTK_GEMINI RIL_requestTimedCallback(initializeCallback, &s_pollSimId2, &TIMEVAL_0); #endif // Give initializeCallback a chance to dispatched, since // we don't presently have a cancellation mechanism sleep(1); waitForClose(); RLOGI("Re-opening after close"); } } }
static void processLine(const char *line, RILChannelCtx *p_channel) { ATResponse *p_response = p_channel->p_response; const char *smsPDU = p_channel->smsPDU; //Move out to the function //pthread_mutex_lock(&p_channel->commandmutex); int isIntermediateResult = 0; if (p_response == NULL) { /* no command pending */ handleUnsolicited(line, p_channel); return; } else { switch (p_channel->type) { case NO_RESULT: //handleUnsolicited(line,p_channel); break; case NUMERIC: if (p_response->p_intermediates == NULL && isdigit(line[0]) ) { addIntermediate(line, p_channel); isIntermediateResult = 1; } else { /* either we already have an intermediate response or * the line doesn't begin with a digit */ //handleUnsolicited(line,p_channel); } break; case SINGLELINE: if (p_response->p_intermediates == NULL && strStartsWith(line, p_channel->responsePrefix) ) { addIntermediate(line, p_channel); isIntermediateResult = 1; } else { /* we already have an intermediate response */ //handleUnsolicited(line,p_channel); } break; case MULTILINE: if (strStartsWith(line, p_channel->responsePrefix)) { addIntermediate(line, p_channel); isIntermediateResult = 1; } else { //handleUnsolicited(line,p_channel); } break; /* atci start */ case RAW: if (!isFinalResponseSuccess(line) && !isFinalResponseErrorEx(line, p_channel) && !isIntermediatePattern(line) ) { addIntermediate(line, p_channel); isIntermediateResult = 1; } break; /* atci end */ default: /* this should never be reached */ RLOGE("Unsupported AT command type %d\n", p_channel->type); //handleUnsolicited(line,p_channel); break; } } if (isIntermediateResult) { /* No need to run the following code*/ } else if (isFinalResponseSuccess(line)) { p_response->success = 1; handleFinalResponse(line, p_channel); } else if (isFinalResponseErrorEx(line, p_channel)) { p_response->success = 0; handleFinalResponse(line, p_channel); } else if (smsPDU != NULL && 0 == strcmp(line, "> ")) { // See eg. TS 27.005 4.3 // Commands like AT+CMGS have a "> " prompt writeCtrlZ(smsPDU, p_channel); smsPDU = NULL; } else if (isIntermediatePattern(line)) { p_response->success = 1; handleFinalResponse(line, p_channel); } else { handleUnsolicited(line, p_channel); } // Move out to the function //pthread_mutex_unlock(&p_channel->commandmutex); }
static void * mainLoop(void *param) { int fd; int ret; char path[50]; int ttys_index; AT_DUMP("== ", "entering mainLoop()", -1 ); at_set_on_reader_closed(onATReaderClosed); at_set_on_timeout(onATTimeout); for (;;) { fd = -1; while (fd < 0) { if (s_port > 0) { fd = socket_loopback_client(s_port, SOCK_STREAM); } else if (s_device_socket) { if (!strcmp(s_device_path, "/dev/socket/qemud")) { /* Qemu-specific control socket */ fd = socket_local_client( "qemud", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM ); if (fd >= 0 ) { char answer[2]; if ( write(fd, "gsm", 3) != 3 || read(fd, answer, 2) != 2 || memcmp(answer, "OK", 2) != 0) { close(fd); fd = -1; } } } else fd = socket_local_client( s_device_path, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM ); } else if (s_device_path != NULL) { fd = open (s_device_path, O_RDWR); if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) { /* disable echo on serial ports */ struct termios ios; tcgetattr( fd, &ios ); ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */ ios.c_iflag = 0; tcsetattr( fd, TCSANOW, &ios ); } } if (fd < 0) { perror ("opening AT interface. retrying..."); sleep(10); /* never returns */ } } RLOGD("FD: %d", fd); s_closed = 0; ret = at_open(fd, onUnsolicited); if (ret < 0) { RLOGE ("AT error %d on at_open\n", ret); return 0; } RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0); // Give initializeCallback a chance to dispatched, since // we don't presently have a cancellation mechanism sleep(1); waitForClose(); RLOGI("Re-opening after close"); } }
const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv) { int ret; int fd = -1; int opt; int index; char *tmp; pthread_attr_t attr; char path[50]; int ttys_index, i; s_rilenv = env; while ( -1 != (opt = getopt(argc, argv, "p:d:s:m:"))) { switch (opt) { case 'p': s_port = atoi(optarg); RLOGI("s_port %s\n", s_port); if (s_port == 0) { usage(argv[0]); return NULL; } RLOGI("Opening loopback port %d\n", s_port); break; case 'd': s_device_path = optarg; RLOGI("Opening tty device1 %s\n", s_device_path); break; case 's': s_device_path = optarg; s_device_socket = 1; //[Emu]TODO create the middleLayer is_gemini_emulator = 1; RLOGI("Opening socket1 %s\n", s_device_path); break; #ifdef MTK_RIL case 'm': RLOGD("Input range: %s %s %s",optarg, argv[1], argv[2]); tmp = strtok(optarg, " "); s_device_range_begin = atoi(tmp) ; tmp = strtok(NULL, " "); s_device_range_end = atoi(tmp); if( (s_device_range_end - s_device_range_begin + 1) != RIL_SUPPORT_CHANNELS) { RLOGE("We can't accept the input configuration for muliple channel since we need %d COM ports", RIL_SUPPORT_CHANNELS); return NULL; } RLOGD("Open the ttyS%d to ttyS%d", s_device_range_begin, s_device_range_end); RLOGD("Link ttyS...."); ttys_index = s_device_range_begin; i = 0; while(ttys_index <= s_device_range_end) { sprintf(path, "/dev/ttyS%d", ttys_index); RLOGD("Unlock %s on Link %s", path, s_mux_path[i]); /*if(chmod(path, 0666) < 0 ) { RLOGD("chomod: system-error: '%s' (code: %d)", strerror(errno), errno); return NULL; }*/ if(symlink(path, s_mux_path[i]) < 0) { RLOGD("symlink: system-error: '%s' (code: %d)", strerror(errno), errno); return NULL; } ttys_index++; i++; } break; #endif default: usage(argv[0]); return NULL; } } RLOGI("while out %s\n", s_device_path); if (s_port < 0 && s_device_path == NULL && (s_device_range_begin < 0 || s_device_range_end < 0) ) { usage(argv[0]); return NULL; } pthread_attr_init (&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // if (is_gemini_emulator){ // ret = pthread_create(&s_tid_mainloop, &attr, mainLoop_emulator, NULL); //}else{ ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL); // } return &s_callbacks; }
int main(int argc, char **argv) { const char * rilLibPath = NULL; char **rilArgv; static char * s_argv[MAX_LIB_ARGS] = {NULL}; void *dlHandle; const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **); const RIL_RadioFunctions *funcs; char libPath[PROPERTY_VALUE_MAX]; unsigned char hasLibArgs = 0; int j = 0; int i; static char clientId[3] = {'0'}; RLOGD("**RIL Daemon Started**"); RLOGD("**RILd param count=%d**", argc); memset(s_argv, 0, sizeof(s_argv)); s_argv[0] = argv[0]; umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH); for (i = 1, j = 1; i < argc ;) { if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) { rilLibPath = argv[i + 1]; i += 2; } else if (0 == strcmp(argv[i], "-c") && (argc - i > 1)) { strncpy(clientId, argv[i+1], strlen(clientId)); i += 2; } else if (0 == strcmp(argv[i], "--")) { i++; hasLibArgs = 1; memcpy(&s_argv[j], &argv[i], argc-i); break; } else { usage(argv[0]); } } #ifdef QCOM_HARDWARE if (atoi(clientId) >= MAX_RILDS) { RLOGE("Max Number of rild's supported is: %d", MAX_RILDS); exit(0); } RLOGD ("RIL Client Id:=%s", clientId); if (strncmp(clientId, "0", MAX_CLIENT_ID_LENGTH)) { if (RIL_setRilSocketName) { RIL_setRilSocketName(clientId); } else { RLOGE("Trying to instantiate multiple rild sockets without a compatible libril!"); } } #endif if (rilLibPath == NULL) { if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) { // No lib sepcified on the command line, and nothing set in props. // Assume "no-ril" case. goto done; } else { rilLibPath = libPath; } } /* special override when in the emulator */ #if 1 { static char arg_device[32]; int done = 0; //连接库地址:/system/lib/libreference-ril.so #define REFERENCE_RIL_PATH "/system/lib/libreference-ril.so" /* first, read /proc/cmdline into memory */ char buffer[1024], *p, *q; int len; int fd = open("/proc/cmdline",O_RDONLY); if (fd < 0) { RLOGD("could not open /proc/cmdline:%s", strerror(errno)); goto OpenLib; } do { len = read(fd,buffer,sizeof(buffer)); } while (len == -1 && errno == EINTR); if (len < 0) { RLOGD("could not read /proc/cmdline:%s", strerror(errno)); close(fd); goto OpenLib; } close(fd); if (strstr(buffer, "android.qemud=") != NULL) { /* the qemud daemon is launched after rild, so * give it some time to create its GSM socket */ int tries = 5; #define QEMUD_SOCKET_NAME "qemud" while (1) { int fd; sleep(1); fd = qemu_pipe_open("qemud:gsm"); if (fd < 0) { fd = socket_local_client( QEMUD_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM ); } if (fd >= 0) { close(fd); snprintf( arg_device, sizeof(arg_device), "%s/%s", ANDROID_SOCKET_DIR, QEMUD_SOCKET_NAME ); memset(s_argv, 0, sizeof(s_argv)); s_argv[1] = "-s"; s_argv[2] = arg_device; done = 1; break; } RLOGD("could not connect to %s socket: %s", QEMUD_SOCKET_NAME, strerror(errno)); if (--tries == 0) break; } if (!done) { RLOGE("could not connect to %s socket (giving up): %s", QEMUD_SOCKET_NAME, strerror(errno)); while(1) sleep(0x00ffffff); } } /* otherwise, try to see if we passed a device name from the kernel */ if (!done) do { #define KERNEL_OPTION "android.ril=" #define DEV_PREFIX "/dev/" p = strstr( buffer, KERNEL_OPTION ); if (p == NULL) break; p += sizeof(KERNEL_OPTION)-1; q = strpbrk( p, " \t\n\r" ); if (q != NULL) *q = 0; snprintf( arg_device, sizeof(arg_device), DEV_PREFIX "%s", p ); arg_device[sizeof(arg_device)-1] = 0; memset(s_argv, 0, sizeof(s_argv)); s_argv[1] = "-d"; s_argv[2] = arg_device; done = 1; } while (0); if (done) { argc = 3; i = 1; hasLibArgs = 1; rilLibPath = REFERENCE_RIL_PATH; RLOGD("overriding with %s %s", s_argv[1], s_argv[2]); } } OpenLib: #endif //切换UID为AID_RADIO switchUser(); // 打开链接库 dlHandle = dlopen(rilLibPath, RTLD_NOW); if (dlHandle == NULL) { RLOGE("dlopen failed: %s", dlerror()); exit(-1); } // 开启EventLoop循环 RIL_startEventLoop(); // 从链接库中(也就是reference-ril.c)寻找RIL_Init函数地址 rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init"); if (rilInit == NULL) { RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath); exit(-1); } if (hasLibArgs) { argc = argc-i+1; } else { static char * newArgv[MAX_LIB_ARGS]; static char args[PROPERTY_VALUE_MAX]; property_get(LIB_ARGS_PROPERTY, args, ""); argc = make_argv(args, s_argv); } // Make sure there's a reasonable argv[0] s_argv[0] = argv[0]; if (argc >= MAX_LIB_ARGS - 2) { RLOGE("Max arguments are passed for rild, args count = %d", argc); exit(0); } #ifdef QCOM_HARDWARE /* Client-id is a qualcomm thing */ s_argv[argc++] = "-c"; s_argv[argc++] = clientId; #endif RLOGD("RIL_Init argc = %d clientId = %s", argc, s_argv[argc-1]); // 初始化过程将s_rilEnv全局变量传递给了reference,然后在reference-ril.c内部将这个值传给了s_rilenv // 而s_rilEnv的各个处理函数是在ril.cpp中实现的 // 调用reference-ril.c中的RIL_Init函数进行初始化INIT,同时得到reference-ril的回调函数 funcs = rilInit(&s_rilEnv, argc, s_argv); #ifdef QCOM_HARDWARE if (funcs == NULL) { /* Pre-multi-client qualcomm vendor libraries won't support "-c" either, so * try again without it. This should only happen on ancient qcoms, so raise * a big fat warning */ argc -= 2; RLOGE("============= Retrying RIL_Init without a client id. This is only required for very old versions,"); RLOGE("============= and you're likely to have more radio breakage elsewhere!"); funcs = rilInit(&s_rilEnv, argc, s_argv); } #endif //注册得到的reference的回调函数 RIL_register(funcs); done: while(1) { // sleep(UINT32_MAX) seems to return immediately on bionic sleep(0x00ffffff); } }