android ril 代码逻辑分析
16lz
2021-01-23
--Ril.h------------------------------------------------------------ typedef struct {
int version; /* set to RIL_VERSION */
RIL_RequestFunc onRequest;
RIL_RadioStateRequest onStateRequest;
RIL_Supports supports;
RIL_Cancel onCancel;
RIL_GetVersion getVersion;
} RIL_RadioFunctions;
struct RIL_Env {
void (*OnRequestComplete)(RIL_Token t, RIL_Errno e,
void *response, size_t responselen);
void (*OnUnsolicitedResponse)(int unsolResponse, const void *data,
size_t datalen);
void* (*RequestTimedCallback) (RIL_TimedCallback callback,
void *param, const struct timeval *relativeTime);
void (*RemoveTimedCallback) (void *callbackInfo);
};
const RIL_RadioFunctions * RIL_Init(const struct RIL_Env *env, int argc, char **argv);
void RIL_register (const RIL_RadioFunctions *callbacks);
void RIL_onRequestComplete(RIL_Token t, RIL_Errno e,
void *response, size_t responselen);
void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
size_t datalen);
void* RIL_requestTimedCallback (RIL_TimedCallback callback,
void *param, const struct timeval *relativeTime);
void RIL_removeTimedCallback(void *callbackInfo); --Rild--------------------------------------------------------------------- static struct RIL_Env s_rilEnv = {
RIL_onRequestComplete,
RIL_onUnsolicitedResponse,
RIL_requestTimedCallback,
RIL_removeTimedCallback
};
int main(int argc, char **argv)
{ const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
const RIL_RadioFunctions *funcs;
dlHandle = dlopen(rilLibPath, RTLD_NOW); RIL_startEventLoop(); rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, " RIL_Init"); funcs = rilInit(& s_rilEnv, argc, rilArgv);
RIL_register(funcs); while(1) {
// sleep(UINT32_MAX) seems to return immediately on bionic
sleep(0x00ffffff);
} } --libRil------------------------------------------------------------ RIL_RadioFunctions s_callbacks = {0, NULL, NULL, NULL, NULL, NULL};
static int s_registerCalled = 0;
static pthread_t s_tid_dispatch;
static pthread_t s_tid_reader;
static int s_started = 0;
static int s_fdListen = -1;
static int s_fdCommand = -1;
static int s_fdDebug = -1;
static int s_fdWakeupRead;
static int s_fdWakeupWrite;
static struct ril_event s_commands_event; // socket fd for writing to client
static struct ril_event s_wakeupfd_event; // wakeup fd for reading
static struct ril_event s_listen_event; // socket fd for linstening
static struct ril_event s_wake_timeout_event;
static struct ril_event s_debug_event; // socket fd for debug linstening
extern "C" void RIL_register (const RIL_RadioFunctions *callbacks) { RIL_startEventLoop();
s_fdListen = android_get_control_socket(SOCKET_NAME_RIL); ret = listen(s_fdListen, 4); /* note: non-persistent so we can accept only one connection at a time */
ril_event_set (& s_listen_event, s_fdListen, false,
listenCallback, NULL);
rilEventAddWakeup (&s_listen_event);
s_fdDebug = android_get_control_socket(SOCKET_NAME_RIL_DEBUG); ret = listen(s_fdDebug, 4);
ril_event_set (& s_debug_event, s_fdDebug, true,
debugCallback, NULL);
rilEventAddWakeup (&s_debug_event); } extern "C" void RIL_startEventLoop(void) {
int ret;
pthread_attr_t attr;
/* spin up eventLoop thread and wait for it to get started */
s_started = 0;
pthread_mutex_lock(&s_startupMutex);
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
while (s_started == 0) {
pthread_cond_wait(&s_startupCond, &s_startupMutex);
}
pthread_mutex_unlock(&s_startupMutex);
} static void *eventLoop (void *param) { { ril_event_init (); pthread_mutex_lock(&s_startupMutex);
s_started = 1;
pthread_cond_broadcast(&s_startupCond);
pthread_mutex_unlock(&s_startupMutex);
ret = pipe(filedes);
s_fdWakeupRead = filedes[0];
s_fdWakeupWrite = filedes[1];
fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);
ril_event_set (& s_wakeupfd_event , s_fdWakeupRead, true,
processWakeupCallback , NULL);
rilEventAddWakeup (& s_wakeupfd_event );
// Only returns on error
ril_event_loop ();
} void ril_event_loop()
{
for (;;) {
memcpy(&rfds, &readFds, sizeof(fd_set)); calcNextTimeout (&tv) n = select( nfds, & rfds, NULL, NULL, ptv);
// Check for timeouts
processTimeouts();
// Check for read-ready
processReadReadies(&rfds, n);
// Fire away
firePending();
}
}
static void processTimeouts()
{
MUTEX_ACQUIRE();
while ((tev != & timer_list) && (timercmp(&now, &tev->timeout, >))) {
next = tev->next;
removeFromList(tev);
addToList(tev, &pending_list);
tev = next;
}
MUTEX_RELEASE();
}
static void processReadReadies(fd_set * rfds, int n)
{
MUTEX_ACQUIRE();
for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) {
struct ril_event * rev = watch_table[i];
if (rev != NULL && FD_ISSET(rev->fd, rfds)) {
addToList(rev, &pending_list);
if (rev->persist == false) {
removeWatch(rev, i);
}
n--;
}
}
MUTEX_RELEASE();
}
static void firePending()
{
struct ril_event * ev = pending_list.next;
while (ev != &pending_list) {
struct ril_event * next = ev->next;
removeFromList(ev);
ev->func(ev->fd, 0, ev->param);
ev = next;
}
} void ril_event_init()
{
MUTEX_INIT();
FD_ZERO(& readFds);
init_list(& timer_list);
init_list(& pending_list);
memset( watch_table, 0, sizeof(watch_table)); } // listener for s_fdListen static void listenCallback (int fd, short flags, void *param) { s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen); ret = fcntl(s_fdCommand, F_SETFL, O_NONBLOCK); p_rs = record_stream_new(s_fdCommand, MAX_COMMAND_BYTES);
ril_event_set (& s_commands_event, s_fdCommand, 1,
processCommandsCallback, p_rs);
rilEventAddWakeup (&s_commands_event);
onNewCommandConnect(); } static void rilEventAddWakeup(struct ril_event *ev) {
ril_event_add(ev); // Add event to watch list
triggerEvLoop(); // trigger event loop to wakeup
} // Add event to watch list
void ril_event_add(struct ril_event * ev)
{
MUTEX_ACQUIRE();
for (int i = 0; i < MAX_FD_EVENTS; i++) {
if (watch_table[i] == NULL) {
watch_table[i] = ev;
ev->index = i;
FD_SET( ev->fd, & readFds);
if (ev->fd >= nfds) nfds = ev->fd+1;
break;
}
}
MUTEX_RELEASE();
} // listener for s_fdCommand static void processCommandsCallback(int fd, short flags, void *param) { ret = record_stream_get_next(p_rs, &p_record, &recordlen); processCommandBuffer(p_record, recordlen); close(s_fdCommand);
s_fdCommand = -1; ril_event_del(&s_commands_event); // Remove event from watch or timer list
record_stream_free(p_rs);
/* start listening for new connections again */
rilEventAddWakeup(&s_listen_event);
onCommandsSocketClosed(); } static CommandInfo s_commands[] = {
#include "ril_commands.h" // there are dispatch and reponse mapping here for Request from Client
}; static int processCommandBuffer(void *buffer, size_t buflen) { pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo)); pRI->pCI = &( s_commands[request]); pRI->pCI-> dispatchFunction(p, pRI); } // dispathc Dail to Reference-ril, it is synchronization operation static void dispatchDial (Parcel &p, RequestInfo *pRI) { s_callbacks. onRequest( pRI->pCI->requestNumber, &dial, sizeOfDial, pRI); } // called by Reference-ril for one Request, and reponse to Client(app) extern "C" void
RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen) { pRI = (RequestInfo *)t; ret = pRI->pCI-> responseFunction(p, response, responselen); sendResponse(p); } // // called by Reference-ril for one unsolicited response extern "C"
void RIL_onUnsolicitedResponse(int unsolResponse, void *data, size_t datalen) { ret = s_unsolResponses[ unsolResponseIndex]
. responseFunction(p, data, datalen); ret = sendResponse(p); } extern "C" void *
RIL_requestTimedCallback (RIL_TimedCallback callback, void *param,
const struct timeval *relativeTime) {
return internalRequestTimedCallback (callback, param, relativeTime);
}
extern "C" void
RIL_removeTimedCallback (void *callbackInfo) {
internalRemoveTimedCallback(callbackInfo);
} --reference-ril------------------------------------------------------------ pthread_t s_tid_mainloop; int main (int argc, char **argv)
{
RIL_register(&s_callbacks);
mainLoop(NULL);
return 0;
} const RIL_RadioFunctions * RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{ s_rilenv = env;
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(& s_tid_mainloop, &attr, mainLoop, NULL);
return & s_callbacks;
}
#else /* RIL_SHLIB */ static void * mainLoop(void *param) { for (;;) { ret = at_open(fd, onUnsolicited);
RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
// Give initializeCallback a chance to dispatched, since
// we don't presently have a cancellation mechanism
sleep(1);
waitForClose(); } } static pthread_t s_tid_reader;
static int s_fd = -1; /* fd of the AT channel */
static ATUnsolHandler s_unsolHandler;
/* for input buffering */
static char s_ATBuffer[MAX_AT_RESPONSE+1];
static char *s_ATBufferCur = s_ATBuffer;
static int s_ackPowerIoctl; /* true if TTY has android byte-count
handshake for low power*/
static int s_readCount = 0; int at_open(int fd, ATUnsolHandler h)
{
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(& s_tid_reader, &attr, readerLoop, &attr); } static void * readerLoop(void *arg) { for (;;) { // Reads a line from the AT channel, returns NULL on timeout.
line = readline();
if (line == NULL) {
break;
}
processLine(line);
}
onReaderClosed();
} 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, "> ")) {
writeCtrlZ(s_smsPDU);
s_smsPDU = NULL;
} else switch (s_type) {
case NO_RESULT:
handleUnsolicited(line);
break; case .... break; default: /* this should never be reached */
LOGE("Unsupported AT command type %d\n", s_type);
handleUnsolicited(line);
break; } pthread_mutex_unlock(& s_commandmutex); } static void handleUnsolicited(const char *line)
{
if (s_unsolHandler != NULL) {
s_unsolHandler(line, NULL);
}
} /**
* 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) } else if ( strStartsWith(s,"+CRING:")
|| strStartsWith(s,"RING")
|| strStartsWith(s,"NO CARRIER")
|| strStartsWith(s,"+CCWA")
) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
NULL, 0);
#ifdef WORKAROUND_FAKE_CGEV
RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
#endif /* WORKAROUND_FAKE_CGEV */
} else if ( strStartsWith(s,"+CREG:")
|| strStartsWith(s,"+CGREG:")
) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED,
NULL, 0);
#ifdef WORKAROUND_FAKE_CGEV
RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
#endif /* WORKAROUND_FAKE_CGEV */
} else if ( strStartsWith(s, "+CMT:")) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_NEW_SMS,
sms_pdu, strlen(sms_pdu));
} else if ( strStartsWith(s, "+CDS:")) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
sms_pdu, strlen(sms_pdu));
} } /** assumes s_commandmutex is held */
static void handleFinalResponse(const char *line)
{
sp_response->finalResponse = strdup(line);
pthread_cond_signal(& s_commandcond);
}
/*** Callback methods from the RIL library to us ***/
* Call from RIL to us to make a RIL_REQUEST
*
* Must be completed with a call to RIL_onRequestComplete()
*
* RIL_onRequestComplete() may be called from any thread, before or after
* this function returns.
*
* Will always be called from the same thread, so returning here implies
* that the radio is ready to process another command (whether or not
* the previous command has completed).
*/ static void onRequest (int request, void *data, size_t datalen, RIL_Token t) { switch (request) { case RIL_REQUEST_SEND_SMS:
requestSendSMS(data, datalen, t);
break;
case RIL_REQUEST_CDMA_SEND_SMS:
requestCdmaSendSMS(data, datalen, t);
break;
case RIL_REQUEST_SETUP_DATA_CALL:
requestSetupDataCall(data, datalen, t);
break;
case RIL_REQUEST_GET_DATA_CALL_PROFILE:
requestGetDataCallProfile(data, datalen, t);
break;
case RIL_REQUEST_SMS_ACKNOWLEDGE:
requestSMSAcknowledge(data, datalen, t);
break; case RIL_REQUEST_GET_CURRENT_CALLS:
requestGetCurrentCalls(data, datalen, t);
break;
case RIL_REQUEST_DIAL:
requestDial(data, datalen, t);
break;
case RIL_REQUEST_HANGUP:
requestHangup(data, datalen, t);
break; case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
// 3GPP 22.030 6.5.5
// "Releases all held calls or sets User Determined User Busy
// (UDUB) for a waiting call."
at_send_command("AT+CHLD=0", NULL);
/* success or failure is ignored by the upper layer here.
it will call GET_CURRENT_CALLS and determine success that way */
RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
break;
case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
// 3GPP 22.030 6.5.5
// "Releases all active calls (if any exist) and accepts
// the other (held or waiting) call."
at_send_command("AT+CHLD=1", NULL);
/* success or failure is ignored by the upper layer here.
it will call GET_CURRENT_CALLS and determine success that way */
RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
break;
case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
// 3GPP 22.030 6.5.5
// "Places all active calls (if any exist) on hold and accepts
// the other (held or waiting) call."
at_send_command("AT+CHLD=2", NULL); case ... break; default:
LOGD("Request not supported. Tech: %d",TECH(sMdmInfo));
RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
break;
} } static void requestDial(void *data, size_t datalen, RIL_Token t) { ret = at_send_command(cmd, NULL); /* success or failure is ignored by the upper layer here.
it will call GET_CURRENT_CALLS and determine success that way */ RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); } int at_send_command (const char *command, ATResponse **pp_outResponse)
{
err = at_send_command_full (command, NO_RESULT, NULL,
NULL, 0, pp_outResponse);
} static int at_send_command_full (const char *command, ATCommandType type,
const char *responsePrefix, const char *smspdu,
long long timeoutMsec, ATResponse **pp_outResponse)
{ if (0 != pthread_equal( s_tid_reader, pthread_self())) {
/* cannot be called from reader thread */
return AT_ERROR_INVALID_THREAD;
} pthread_mutex_lock(& s_commandmutex);
err = at_send_command_full_nolock(command, type,
responsePrefix, smspdu,
timeoutMsec, pp_outResponse);
pthread_mutex_unlock(& s_commandmutex); } static int at_send_command_full_nolock (const char *command, ATCommandType type,
const char *responsePrefix, const char *smspdu,
long long timeoutMsec, ATResponse **pp_outResponse) { err = writeline ( command);
while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
if (timeoutMsec != 0) {
#ifdef USE_NP
err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec);
#else
err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
#endif /*USE_NP*/
} else { // this thread will be wake up by handleFinalResponse()
err = pthread_cond_wait(& s_commandcond, & s_commandmutex);
}
}
at_response_free(sp_response); }
int version; /* set to RIL_VERSION */
RIL_RequestFunc onRequest;
RIL_RadioStateRequest onStateRequest;
RIL_Supports supports;
RIL_Cancel onCancel;
RIL_GetVersion getVersion;
} RIL_RadioFunctions;
struct RIL_Env {
void (*OnRequestComplete)(RIL_Token t, RIL_Errno e,
void *response, size_t responselen);
void (*OnUnsolicitedResponse)(int unsolResponse, const void *data,
size_t datalen);
void* (*RequestTimedCallback) (RIL_TimedCallback callback,
void *param, const struct timeval *relativeTime);
void (*RemoveTimedCallback) (void *callbackInfo);
};
const RIL_RadioFunctions * RIL_Init(const struct RIL_Env *env, int argc, char **argv);
void RIL_register (const RIL_RadioFunctions *callbacks);
void RIL_onRequestComplete(RIL_Token t, RIL_Errno e,
void *response, size_t responselen);
void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
size_t datalen);
void* RIL_requestTimedCallback (RIL_TimedCallback callback,
void *param, const struct timeval *relativeTime);
void RIL_removeTimedCallback(void *callbackInfo); --Rild--------------------------------------------------------------------- static struct RIL_Env s_rilEnv = {
RIL_onRequestComplete,
RIL_onUnsolicitedResponse,
RIL_requestTimedCallback,
RIL_removeTimedCallback
};
int main(int argc, char **argv)
{ const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
const RIL_RadioFunctions *funcs;
dlHandle = dlopen(rilLibPath, RTLD_NOW); RIL_startEventLoop(); rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, " RIL_Init"); funcs = rilInit(& s_rilEnv, argc, rilArgv);
RIL_register(funcs); while(1) {
// sleep(UINT32_MAX) seems to return immediately on bionic
sleep(0x00ffffff);
} } --libRil------------------------------------------------------------ RIL_RadioFunctions s_callbacks = {0, NULL, NULL, NULL, NULL, NULL};
static int s_registerCalled = 0;
static pthread_t s_tid_dispatch;
static pthread_t s_tid_reader;
static int s_started = 0;
static int s_fdListen = -1;
static int s_fdCommand = -1;
static int s_fdDebug = -1;
static int s_fdWakeupRead;
static int s_fdWakeupWrite;
static struct ril_event s_commands_event; // socket fd for writing to client
static struct ril_event s_wakeupfd_event; // wakeup fd for reading
static struct ril_event s_listen_event; // socket fd for linstening
static struct ril_event s_wake_timeout_event;
static struct ril_event s_debug_event; // socket fd for debug linstening
extern "C" void RIL_register (const RIL_RadioFunctions *callbacks) { RIL_startEventLoop();
s_fdListen = android_get_control_socket(SOCKET_NAME_RIL); ret = listen(s_fdListen, 4); /* note: non-persistent so we can accept only one connection at a time */
ril_event_set (& s_listen_event, s_fdListen, false,
listenCallback, NULL);
rilEventAddWakeup (&s_listen_event);
s_fdDebug = android_get_control_socket(SOCKET_NAME_RIL_DEBUG); ret = listen(s_fdDebug, 4);
ril_event_set (& s_debug_event, s_fdDebug, true,
debugCallback, NULL);
rilEventAddWakeup (&s_debug_event); } extern "C" void RIL_startEventLoop(void) {
int ret;
pthread_attr_t attr;
/* spin up eventLoop thread and wait for it to get started */
s_started = 0;
pthread_mutex_lock(&s_startupMutex);
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
while (s_started == 0) {
pthread_cond_wait(&s_startupCond, &s_startupMutex);
}
pthread_mutex_unlock(&s_startupMutex);
} static void *eventLoop (void *param) { { ril_event_init (); pthread_mutex_lock(&s_startupMutex);
s_started = 1;
pthread_cond_broadcast(&s_startupCond);
pthread_mutex_unlock(&s_startupMutex);
ret = pipe(filedes);
s_fdWakeupRead = filedes[0];
s_fdWakeupWrite = filedes[1];
fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);
ril_event_set (& s_wakeupfd_event , s_fdWakeupRead, true,
processWakeupCallback , NULL);
rilEventAddWakeup (& s_wakeupfd_event );
// Only returns on error
ril_event_loop ();
} void ril_event_loop()
{
for (;;) {
memcpy(&rfds, &readFds, sizeof(fd_set)); calcNextTimeout (&tv) n = select( nfds, & rfds, NULL, NULL, ptv);
// Check for timeouts
processTimeouts();
// Check for read-ready
processReadReadies(&rfds, n);
// Fire away
firePending();
}
}
static void processTimeouts()
{
MUTEX_ACQUIRE();
while ((tev != & timer_list) && (timercmp(&now, &tev->timeout, >))) {
next = tev->next;
removeFromList(tev);
addToList(tev, &pending_list);
tev = next;
}
MUTEX_RELEASE();
}
static void processReadReadies(fd_set * rfds, int n)
{
MUTEX_ACQUIRE();
for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) {
struct ril_event * rev = watch_table[i];
if (rev != NULL && FD_ISSET(rev->fd, rfds)) {
addToList(rev, &pending_list);
if (rev->persist == false) {
removeWatch(rev, i);
}
n--;
}
}
MUTEX_RELEASE();
}
static void firePending()
{
struct ril_event * ev = pending_list.next;
while (ev != &pending_list) {
struct ril_event * next = ev->next;
removeFromList(ev);
ev->func(ev->fd, 0, ev->param);
ev = next;
}
} void ril_event_init()
{
MUTEX_INIT();
FD_ZERO(& readFds);
init_list(& timer_list);
init_list(& pending_list);
memset( watch_table, 0, sizeof(watch_table)); } // listener for s_fdListen static void listenCallback (int fd, short flags, void *param) { s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen); ret = fcntl(s_fdCommand, F_SETFL, O_NONBLOCK); p_rs = record_stream_new(s_fdCommand, MAX_COMMAND_BYTES);
ril_event_set (& s_commands_event, s_fdCommand, 1,
processCommandsCallback, p_rs);
rilEventAddWakeup (&s_commands_event);
onNewCommandConnect(); } static void rilEventAddWakeup(struct ril_event *ev) {
ril_event_add(ev); // Add event to watch list
triggerEvLoop(); // trigger event loop to wakeup
} // Add event to watch list
void ril_event_add(struct ril_event * ev)
{
MUTEX_ACQUIRE();
for (int i = 0; i < MAX_FD_EVENTS; i++) {
if (watch_table[i] == NULL) {
watch_table[i] = ev;
ev->index = i;
FD_SET( ev->fd, & readFds);
if (ev->fd >= nfds) nfds = ev->fd+1;
break;
}
}
MUTEX_RELEASE();
} // listener for s_fdCommand static void processCommandsCallback(int fd, short flags, void *param) { ret = record_stream_get_next(p_rs, &p_record, &recordlen); processCommandBuffer(p_record, recordlen); close(s_fdCommand);
s_fdCommand = -1; ril_event_del(&s_commands_event); // Remove event from watch or timer list
record_stream_free(p_rs);
/* start listening for new connections again */
rilEventAddWakeup(&s_listen_event);
onCommandsSocketClosed(); } static CommandInfo s_commands[] = {
#include "ril_commands.h" // there are dispatch and reponse mapping here for Request from Client
}; static int processCommandBuffer(void *buffer, size_t buflen) { pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo)); pRI->pCI = &( s_commands[request]); pRI->pCI-> dispatchFunction(p, pRI); } // dispathc Dail to Reference-ril, it is synchronization operation static void dispatchDial (Parcel &p, RequestInfo *pRI) { s_callbacks. onRequest( pRI->pCI->requestNumber, &dial, sizeOfDial, pRI); } // called by Reference-ril for one Request, and reponse to Client(app) extern "C" void
RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen) { pRI = (RequestInfo *)t; ret = pRI->pCI-> responseFunction(p, response, responselen); sendResponse(p); } // // called by Reference-ril for one unsolicited response extern "C"
void RIL_onUnsolicitedResponse(int unsolResponse, void *data, size_t datalen) { ret = s_unsolResponses[ unsolResponseIndex]
. responseFunction(p, data, datalen); ret = sendResponse(p); } extern "C" void *
RIL_requestTimedCallback (RIL_TimedCallback callback, void *param,
const struct timeval *relativeTime) {
return internalRequestTimedCallback (callback, param, relativeTime);
}
extern "C" void
RIL_removeTimedCallback (void *callbackInfo) {
internalRemoveTimedCallback(callbackInfo);
} --reference-ril------------------------------------------------------------ pthread_t s_tid_mainloop; int main (int argc, char **argv)
{
RIL_register(&s_callbacks);
mainLoop(NULL);
return 0;
} const RIL_RadioFunctions * RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{ s_rilenv = env;
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(& s_tid_mainloop, &attr, mainLoop, NULL);
return & s_callbacks;
}
#else /* RIL_SHLIB */ static void * mainLoop(void *param) { for (;;) { ret = at_open(fd, onUnsolicited);
RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
// Give initializeCallback a chance to dispatched, since
// we don't presently have a cancellation mechanism
sleep(1);
waitForClose(); } } static pthread_t s_tid_reader;
static int s_fd = -1; /* fd of the AT channel */
static ATUnsolHandler s_unsolHandler;
/* for input buffering */
static char s_ATBuffer[MAX_AT_RESPONSE+1];
static char *s_ATBufferCur = s_ATBuffer;
static int s_ackPowerIoctl; /* true if TTY has android byte-count
handshake for low power*/
static int s_readCount = 0; int at_open(int fd, ATUnsolHandler h)
{
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(& s_tid_reader, &attr, readerLoop, &attr); } static void * readerLoop(void *arg) { for (;;) { // Reads a line from the AT channel, returns NULL on timeout.
line = readline();
if (line == NULL) {
break;
}
processLine(line);
}
onReaderClosed();
} 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, "> ")) {
writeCtrlZ(s_smsPDU);
s_smsPDU = NULL;
} else switch (s_type) {
case NO_RESULT:
handleUnsolicited(line);
break; case .... break; default: /* this should never be reached */
LOGE("Unsupported AT command type %d\n", s_type);
handleUnsolicited(line);
break; } pthread_mutex_unlock(& s_commandmutex); } static void handleUnsolicited(const char *line)
{
if (s_unsolHandler != NULL) {
s_unsolHandler(line, NULL);
}
} /**
* 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) } else if ( strStartsWith(s,"+CRING:")
|| strStartsWith(s,"RING")
|| strStartsWith(s,"NO CARRIER")
|| strStartsWith(s,"+CCWA")
) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
NULL, 0);
#ifdef WORKAROUND_FAKE_CGEV
RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
#endif /* WORKAROUND_FAKE_CGEV */
} else if ( strStartsWith(s,"+CREG:")
|| strStartsWith(s,"+CGREG:")
) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED,
NULL, 0);
#ifdef WORKAROUND_FAKE_CGEV
RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
#endif /* WORKAROUND_FAKE_CGEV */
} else if ( strStartsWith(s, "+CMT:")) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_NEW_SMS,
sms_pdu, strlen(sms_pdu));
} else if ( strStartsWith(s, "+CDS:")) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
sms_pdu, strlen(sms_pdu));
} } /** assumes s_commandmutex is held */
static void handleFinalResponse(const char *line)
{
sp_response->finalResponse = strdup(line);
pthread_cond_signal(& s_commandcond);
}
/*** Callback methods from the RIL library to us ***/
* Call from RIL to us to make a RIL_REQUEST
*
* Must be completed with a call to RIL_onRequestComplete()
*
* RIL_onRequestComplete() may be called from any thread, before or after
* this function returns.
*
* Will always be called from the same thread, so returning here implies
* that the radio is ready to process another command (whether or not
* the previous command has completed).
*/ static void onRequest (int request, void *data, size_t datalen, RIL_Token t) { switch (request) { case RIL_REQUEST_SEND_SMS:
requestSendSMS(data, datalen, t);
break;
case RIL_REQUEST_CDMA_SEND_SMS:
requestCdmaSendSMS(data, datalen, t);
break;
case RIL_REQUEST_SETUP_DATA_CALL:
requestSetupDataCall(data, datalen, t);
break;
case RIL_REQUEST_GET_DATA_CALL_PROFILE:
requestGetDataCallProfile(data, datalen, t);
break;
case RIL_REQUEST_SMS_ACKNOWLEDGE:
requestSMSAcknowledge(data, datalen, t);
break; case RIL_REQUEST_GET_CURRENT_CALLS:
requestGetCurrentCalls(data, datalen, t);
break;
case RIL_REQUEST_DIAL:
requestDial(data, datalen, t);
break;
case RIL_REQUEST_HANGUP:
requestHangup(data, datalen, t);
break; case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
// 3GPP 22.030 6.5.5
// "Releases all held calls or sets User Determined User Busy
// (UDUB) for a waiting call."
at_send_command("AT+CHLD=0", NULL);
/* success or failure is ignored by the upper layer here.
it will call GET_CURRENT_CALLS and determine success that way */
RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
break;
case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
// 3GPP 22.030 6.5.5
// "Releases all active calls (if any exist) and accepts
// the other (held or waiting) call."
at_send_command("AT+CHLD=1", NULL);
/* success or failure is ignored by the upper layer here.
it will call GET_CURRENT_CALLS and determine success that way */
RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
break;
case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
// 3GPP 22.030 6.5.5
// "Places all active calls (if any exist) on hold and accepts
// the other (held or waiting) call."
at_send_command("AT+CHLD=2", NULL); case ... break; default:
LOGD("Request not supported. Tech: %d",TECH(sMdmInfo));
RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
break;
} } static void requestDial(void *data, size_t datalen, RIL_Token t) { ret = at_send_command(cmd, NULL); /* success or failure is ignored by the upper layer here.
it will call GET_CURRENT_CALLS and determine success that way */ RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); } int at_send_command (const char *command, ATResponse **pp_outResponse)
{
err = at_send_command_full (command, NO_RESULT, NULL,
NULL, 0, pp_outResponse);
} static int at_send_command_full (const char *command, ATCommandType type,
const char *responsePrefix, const char *smspdu,
long long timeoutMsec, ATResponse **pp_outResponse)
{ if (0 != pthread_equal( s_tid_reader, pthread_self())) {
/* cannot be called from reader thread */
return AT_ERROR_INVALID_THREAD;
} pthread_mutex_lock(& s_commandmutex);
err = at_send_command_full_nolock(command, type,
responsePrefix, smspdu,
timeoutMsec, pp_outResponse);
pthread_mutex_unlock(& s_commandmutex); } static int at_send_command_full_nolock (const char *command, ATCommandType type,
const char *responsePrefix, const char *smspdu,
long long timeoutMsec, ATResponse **pp_outResponse) { err = writeline ( command);
while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
if (timeoutMsec != 0) {
#ifdef USE_NP
err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec);
#else
err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
#endif /*USE_NP*/
} else { // this thread will be wake up by handleFinalResponse()
err = pthread_cond_wait(& s_commandcond, & s_commandmutex);
}
}
at_response_free(sp_response); }
更多相关文章
- 代码中设置drawableleft
- android 3.0 隐藏 系统标题栏
- Android开发中activity切换动画的实现
- Android(安卓)学习 笔记_05. 文件下载
- Android中直播视频技术探究之—摄像头Camera视频源数据采集解析
- 技术博客汇总
- android 2.3 wifi (一)
- AndRoid Notification的清空和修改
- Android中的Chronometer