reference-ril.c
上传用户:rftzhifu
上传日期:2017-02-21
资源大小:229k
文件大小:56k
源码类别:

android开发

开发平台:

Unix_Linux

  1. /* //device/system/reference-ril/reference-ril.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. #include <telephony/ril.h>
  18. #include <stdio.h>
  19. #include <assert.h>
  20. #include <string.h>
  21. #include <errno.h>
  22. #include <unistd.h>
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <fcntl.h>
  26. #include <pthread.h>
  27. #include <alloca.h>
  28. #include "atchannel.h"
  29. #include "at_tok.h"
  30. #include "misc.h"
  31. #include <getopt.h>
  32. #include <sys/socket.h>
  33. #include <cutils/sockets.h>
  34. #include <termios.h>
  35. #define LOG_TAG "RIL"
  36. #include <utils/Log.h>
  37. #define MAX_AT_RESPONSE 0x1000
  38. /* pathname returned from RIL_REQUEST_SETUP_DEFAULT_PDP */
  39. #define PPP_TTY_PATH "/dev/omap_csmi_tty1"
  40. #ifdef USE_TI_COMMANDS
  41. // Enable a workaround
  42. // 1) Make incoming call, do not answer
  43. // 2) Hangup remote end
  44. // Expected: call should disappear from CLCC line
  45. // Actual: Call shows as "ACTIVE" before disappearing
  46. #define WORKAROUND_ERRONEOUS_ANSWER 1
  47. // Some varients of the TI stack do not support the +CGEV unsolicited
  48. // response. However, they seem to send an unsolicited +CME ERROR: 150
  49. #define WORKAROUND_FAKE_CGEV 1
  50. #endif
  51. static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
  52. static RIL_RadioState currentState();
  53. static int onSupports (int requestCode);
  54. static void onCancel (RIL_Token t);
  55. static const char *getVersion();
  56. static int isRadioOn();
  57. static int getSIMStatus();
  58. static void onPDPContextListChanged(void *param);
  59. extern const char * requestToString(int request);
  60. /*** Static Variables ***/
  61. static const RIL_RadioFunctions s_callbacks = {
  62.     RIL_VERSION,
  63.     onRequest,
  64.     currentState,
  65.     onSupports,
  66.     onCancel,
  67.     getVersion
  68. };
  69. #ifdef RIL_SHLIB
  70. static const struct RIL_Env *s_rilenv;
  71. #define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen)
  72. #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
  73. #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)
  74. #endif
  75. static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
  76. static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
  77. static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
  78. static int s_port = -1;
  79. static const char * s_device_path = NULL;
  80. static int          s_device_socket = 0;
  81. /* trigger change to this with s_state_cond */
  82. static int s_closed = 0;
  83. static int sFD;     /* file desc of AT channel */
  84. static char sATBuffer[MAX_AT_RESPONSE+1];
  85. static char *sATBufferCur = NULL;
  86. static const struct timeval TIMEVAL_SIMPOLL = {1,0};
  87. static const struct timeval TIMEVAL_CALLSTATEPOLL = {0,500000};
  88. static const struct timeval TIMEVAL_0 = {0,0};
  89. #ifdef WORKAROUND_ERRONEOUS_ANSWER
  90. // Max number of times we'll try to repoll when we think
  91. // we have a AT+CLCC race condition
  92. #define REPOLL_CALLS_COUNT_MAX 4
  93. // Line index that was incoming or waiting at last poll, or -1 for none
  94. static int s_incomingOrWaitingLine = -1;
  95. // Number of times we've asked for a repoll of AT+CLCC
  96. static int s_repollCallsCount = 0;
  97. // Should we expect a call to be answered in the next CLCC?
  98. static int s_expectAnswer = 0;
  99. #endif /* WORKAROUND_ERRONEOUS_ANSWER */
  100. static void pollSIMState (void *param);
  101. static void setRadioState(RIL_RadioState newState);
  102. static int clccStateToRILState(int state, RIL_CallState *p_state)
  103. {
  104.     switch(state) {
  105.         case 0: *p_state = RIL_CALL_ACTIVE;   return 0;
  106.         case 1: *p_state = RIL_CALL_HOLDING;  return 0;
  107.         case 2: *p_state = RIL_CALL_DIALING;  return 0;
  108.         case 3: *p_state = RIL_CALL_ALERTING; return 0;
  109.         case 4: *p_state = RIL_CALL_INCOMING; return 0;
  110.         case 5: *p_state = RIL_CALL_WAITING;  return 0;
  111.         default: return -1;
  112.     }
  113. }
  114. /**
  115.  * Note: directly modified line and has *p_call point directly into
  116.  * modified line
  117.  */
  118. static int callFromCLCCLine(char *line, RIL_Call *p_call)
  119. {
  120.         //+CLCC: 1,0,2,0,0,"+18005551212",145
  121.         //     index,isMT,state,mode,isMpty(,number,TOA)?
  122.     int err;
  123.     int state;
  124.     int mode;
  125.     err = at_tok_start(&line);
  126.     if (err < 0) goto error;
  127.     err = at_tok_nextint(&line, &(p_call->index));
  128.     if (err < 0) goto error;
  129.     err = at_tok_nextbool(&line, &(p_call->isMT));
  130.     if (err < 0) goto error;
  131.     err = at_tok_nextint(&line, &state);
  132.     if (err < 0) goto error;
  133.     err = clccStateToRILState(state, &(p_call->state));
  134.     if (err < 0) goto error;
  135.     err = at_tok_nextint(&line, &mode);
  136.     if (err < 0) goto error;
  137.     p_call->isVoice = (mode == 0);
  138.     err = at_tok_nextbool(&line, &(p_call->isMpty));
  139.     if (err < 0) goto error;
  140.     if (at_tok_hasmore(&line)) {
  141.         err = at_tok_nextstr(&line, &(p_call->number));
  142.         /* tolerate null here */
  143.         if (err < 0) return 0;
  144.         // Some lame implementations return strings
  145.         // like "NOT AVAILABLE" in the CLCC line
  146.         if (p_call->number != NULL
  147.             && 0 == strspn(p_call->number, "+0123456789")
  148.         ) {
  149.             p_call->number = NULL;
  150.         }
  151.         err = at_tok_nextint(&line, &p_call->toa);
  152.         if (err < 0) goto error;
  153.     }
  154.     return 0;
  155. error:
  156.     LOGE("invalid CLCC linen");
  157.     return -1;
  158. }
  159. /** do post-AT+CFUN=1 initialization */
  160. static void onRadioPowerOn()
  161. {
  162. #ifdef USE_TI_COMMANDS
  163.     /*  Must be after CFUN=1 */
  164.     /*  TI specific -- notifications for CPHS things such */
  165.     /*  as CPHS message waiting indicator */
  166.     at_send_command("AT%CPHS=1", NULL);
  167.     /*  TI specific -- enable NITZ unsol notifs */
  168.     at_send_command("AT%CTZV=1", NULL);
  169. #endif
  170.     pollSIMState(NULL);
  171. }
  172. /** do post- SIM ready initialization */
  173. static void onSIMReady()
  174. {
  175.     at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
  176.     /*
  177.      * Always send SMS messages directly to the TE
  178.      *
  179.      * mode = 1 // discard when link is reserved (link should never be
  180.      *             reserved)
  181.      * mt = 2   // most messages routed to TE
  182.      * bm = 2   // new cell BM's routed to TE
  183.      * ds = 1   // Status reports routed to TE
  184.      * bfr = 1  // flush buffer
  185.      */
  186.     at_send_command("AT+CNMI=1,2,2,1,1", NULL);
  187. }
  188. static void requestRadioPower(void *data, size_t datalen, RIL_Token t)
  189. {
  190.     int onOff;
  191.     int err;
  192.     ATResponse *p_response = NULL;
  193.     assert (datalen >= sizeof(int *));
  194.     onOff = ((int *)data)[0];
  195.     if (onOff == 0 && sState != RADIO_STATE_OFF) {
  196.         err = at_send_command("AT+CFUN=0", &p_response);
  197.        if (err < 0 || p_response->success == 0) goto error;
  198.         setRadioState(RADIO_STATE_OFF);
  199.     } else if (onOff > 0 && sState == RADIO_STATE_OFF) {
  200.         err = at_send_command("AT+CFUN=1", &p_response);
  201.         if (err < 0|| p_response->success == 0) {
  202.             // Some stacks return an error when there is no SIM,
  203.             // but they really turn the RF portion on
  204.             // So, if we get an error, let's check to see if it
  205.             // turned on anyway
  206.             if (isRadioOn() != 1) {
  207.                 goto error;
  208.             }
  209.         }
  210.         setRadioState(RADIO_STATE_SIM_NOT_READY);
  211.     }
  212.     at_response_free(p_response);
  213.     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  214.     return;
  215. error:
  216.     at_response_free(p_response);
  217.     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  218. }
  219. static void requestOrSendPDPContextList(RIL_Token *t);
  220. static void onPDPContextListChanged(void *param)
  221. {
  222.     requestOrSendPDPContextList(NULL);
  223. }
  224. static void requestPDPContextList(void *data, size_t datalen, RIL_Token t)
  225. {
  226.     requestOrSendPDPContextList(&t);
  227. }
  228. static void requestOrSendPDPContextList(RIL_Token *t)
  229. {
  230.     ATResponse *p_response;
  231.     ATLine *p_cur;
  232.     int err;
  233.     int n = 0;
  234.     char *out;
  235.     err = at_send_command_multiline ("AT+CGACT?", "+CGACT:", &p_response);
  236.     if (err != 0 || p_response->success == 0) {
  237.         if (t != NULL)
  238.             RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
  239.         else
  240.             RIL_onUnsolicitedResponse(RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED,
  241.                                       NULL, 0);
  242.         return;
  243.     }
  244.     for (p_cur = p_response->p_intermediates; p_cur != NULL;
  245.          p_cur = p_cur->p_next)
  246.         n++;
  247.     RIL_PDP_Context_Response *responses =
  248.         alloca(n * sizeof(RIL_PDP_Context_Response));
  249.     int i;
  250.     for (i = 0; i < n; i++) {
  251.         responses[i].cid = -1;
  252.         responses[i].active = -1;
  253.         responses[i].type = "";
  254.         responses[i].apn = "";
  255.         responses[i].address = "";
  256.     }
  257.     RIL_PDP_Context_Response *response = responses;
  258.     for (p_cur = p_response->p_intermediates; p_cur != NULL;
  259.          p_cur = p_cur->p_next) {
  260.         char *line = p_cur->line;
  261.         err = at_tok_start(&line);
  262.         if (err < 0)
  263.             goto error;
  264.         err = at_tok_nextint(&line, &response->cid);
  265.         if (err < 0)
  266.             goto error;
  267.         err = at_tok_nextint(&line, &response->active);
  268.         if (err < 0)
  269.             goto error;
  270.         response++;
  271.     }
  272.     at_response_free(p_response);
  273.     err = at_send_command_multiline ("AT+CGDCONT?", "+CGDCONT:", &p_response);
  274.     if (err != 0 || p_response->success == 0) {
  275.         if (t != NULL)
  276.             RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
  277.         else
  278.             RIL_onUnsolicitedResponse(RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED,
  279.                                       NULL, 0);
  280.         return;
  281.     }
  282.     for (p_cur = p_response->p_intermediates; p_cur != NULL;
  283.          p_cur = p_cur->p_next) {
  284.         char *line = p_cur->line;
  285.         int cid;
  286.         char *type;
  287.         char *apn;
  288.         char *address;
  289.         err = at_tok_start(&line);
  290.         if (err < 0)
  291.             goto error;
  292.         err = at_tok_nextint(&line, &cid);
  293.         if (err < 0)
  294.             goto error;
  295.         for (i = 0; i < n; i++) {
  296.             if (responses[i].cid == cid)
  297.                 break;
  298.         }
  299.         if (i >= n) {
  300.             /* details for a context we didn't hear about in the last request */
  301.             continue;
  302.         }
  303.         err = at_tok_nextstr(&line, &out);
  304.         if (err < 0)
  305.             goto error;
  306.         responses[i].type = alloca(strlen(out) + 1);
  307.         strcpy(responses[i].type, out);
  308.         err = at_tok_nextstr(&line, &out);
  309.         if (err < 0)
  310.             goto error;
  311.         responses[i].apn = alloca(strlen(out) + 1);
  312.         strcpy(responses[i].apn, out);
  313.         err = at_tok_nextstr(&line, &out);
  314.         if (err < 0)
  315.             goto error;
  316.         responses[i].address = alloca(strlen(out) + 1);
  317.         strcpy(responses[i].address, out);
  318.     }
  319.     at_response_free(p_response);
  320.     if (t != NULL)
  321.         RIL_onRequestComplete(*t, RIL_E_SUCCESS, responses,
  322.                               n * sizeof(RIL_PDP_Context_Response));
  323.     else
  324.         RIL_onUnsolicitedResponse(RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED,
  325.                                   responses,
  326.                                   n * sizeof(RIL_PDP_Context_Response));
  327.     return;
  328. error:
  329.     if (t != NULL)
  330.         RIL_onRequestComplete(*t, RIL_E_GENERIC_FAILURE, NULL, 0);
  331.     else
  332.         RIL_onUnsolicitedResponse(RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED,
  333.                                   NULL, 0);
  334.     at_response_free(p_response);
  335. }
  336. static void requestQueryNetworkSelectionMode(
  337.                 void *data, size_t datalen, RIL_Token t)
  338. {
  339.     int err;
  340.     ATResponse *p_response = NULL;
  341.     int response = 0;
  342.     char *line;
  343.     err = at_send_command_singleline("AT+COPS?", "+COPS:", &p_response);
  344.     if (err < 0 || p_response->success == 0) {
  345.         goto error;
  346.     }
  347.     line = p_response->p_intermediates->line;
  348.     err = at_tok_start(&line);
  349.     if (err < 0) {
  350.         goto error;
  351.     }
  352.     err = at_tok_nextint(&line, &response);
  353.     if (err < 0) {
  354.         goto error;
  355.     }
  356.     RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
  357.     at_response_free(p_response);
  358.     return;
  359. error:
  360.     at_response_free(p_response);
  361.     LOGE("requestQueryNetworkSelectionMode must never return error when radio is on");
  362.     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  363. }
  364. static void sendCallStateChanged(void *param)
  365. {
  366.     RIL_onUnsolicitedResponse (
  367.         RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
  368.         NULL, 0);
  369. }
  370. static void requestGetCurrentCalls(void *data, size_t datalen, RIL_Token t)
  371. {
  372.     int err;
  373.     ATResponse *p_response;
  374.     ATLine *p_cur;
  375.     int countCalls;
  376.     int countValidCalls;
  377.     RIL_Call *p_calls;
  378.     RIL_Call **pp_calls;
  379.     int i;
  380.     int needRepoll = 0;
  381. #ifdef WORKAROUND_ERRONEOUS_ANSWER
  382.     int prevIncomingOrWaitingLine;
  383.     prevIncomingOrWaitingLine = s_incomingOrWaitingLine;
  384.     s_incomingOrWaitingLine = -1;
  385. #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
  386.     err = at_send_command_multiline ("AT+CLCC", "+CLCC:", &p_response);
  387.     if (err != 0 || p_response->success == 0) {
  388.         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  389.         return;
  390.     }
  391.     /* count the calls */
  392.     for (countCalls = 0, p_cur = p_response->p_intermediates
  393.             ; p_cur != NULL
  394.             ; p_cur = p_cur->p_next
  395.     ) {
  396.         countCalls++;
  397.     }
  398.     /* yes, there's an array of pointers and then an array of structures */
  399.     pp_calls = (RIL_Call **)alloca(countCalls * sizeof(RIL_Call *));
  400.     p_calls = (RIL_Call *)alloca(countCalls * sizeof(RIL_Call));
  401.     memset (p_calls, 0, countCalls * sizeof(RIL_Call));
  402.     /* init the pointer array */
  403.     for(i = 0; i < countCalls ; i++) {
  404.         pp_calls[i] = &(p_calls[i]);
  405.     }
  406.     for (countValidCalls = 0, p_cur = p_response->p_intermediates
  407.             ; p_cur != NULL
  408.             ; p_cur = p_cur->p_next
  409.     ) {
  410.         err = callFromCLCCLine(p_cur->line, p_calls + countValidCalls);
  411.         if (err != 0) {
  412.             continue;
  413.         }
  414. #ifdef WORKAROUND_ERRONEOUS_ANSWER
  415.         if (p_calls[countValidCalls].state == RIL_CALL_INCOMING
  416.             || p_calls[countValidCalls].state == RIL_CALL_WAITING
  417.         ) {
  418.             s_incomingOrWaitingLine = p_calls[countValidCalls].index;
  419.         }
  420. #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
  421.         if (p_calls[countValidCalls].state != RIL_CALL_ACTIVE
  422.             && p_calls[countValidCalls].state != RIL_CALL_HOLDING
  423.         ) {
  424.             needRepoll = 1;
  425.         }
  426.         countValidCalls++;
  427.     }
  428. #ifdef WORKAROUND_ERRONEOUS_ANSWER
  429.     // Basically:
  430.     // A call was incoming or waiting
  431.     // Now it's marked as active
  432.     // But we never answered it
  433.     //
  434.     // This is probably a bug, and the call will probably
  435.     // disappear from the call list in the next poll
  436.     if (prevIncomingOrWaitingLine >= 0
  437.             && s_incomingOrWaitingLine < 0
  438.             && s_expectAnswer == 0
  439.     ) {
  440.         for (i = 0; i < countValidCalls ; i++) {
  441.             if (p_calls[i].index == prevIncomingOrWaitingLine
  442.                     && p_calls[i].state == RIL_CALL_ACTIVE
  443.                     && s_repollCallsCount < REPOLL_CALLS_COUNT_MAX
  444.             ) {
  445.                 LOGI(
  446.                     "Hit WORKAROUND_ERRONOUS_ANSWER case."
  447.                     " Repoll count: %dn", s_repollCallsCount);
  448.                 s_repollCallsCount++;
  449.                 goto error;
  450.             }
  451.         }
  452.     }
  453.     s_expectAnswer = 0;
  454.     s_repollCallsCount = 0;
  455. #endif /*WORKAROUND_ERRONEOUS_ANSWER*/
  456.     RIL_onRequestComplete(t, RIL_E_SUCCESS, pp_calls,
  457.             countValidCalls * sizeof (RIL_Call *));
  458.     at_response_free(p_response);
  459. #ifdef POLL_CALL_STATE
  460.     if (countValidCalls) {  // We don't seem to get a "NO CARRIER" message from
  461.                             // smd, so we're forced to poll until the call ends.
  462. #else
  463.     if (needRepoll) {
  464. #endif
  465.         RIL_requestTimedCallback (sendCallStateChanged, NULL, &TIMEVAL_CALLSTATEPOLL);
  466.     }
  467.     return;
  468. error:
  469.     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  470.     at_response_free(p_response);
  471. }
  472. static void requestDial(void *data, size_t datalen, RIL_Token t)
  473. {
  474.     RIL_Dial *p_dial;
  475.     char *cmd;
  476.     const char *clir;
  477.     int ret;
  478.     p_dial = (RIL_Dial *)data;
  479.     switch (p_dial->clir) {
  480.         case 1: clir = "I"; break;  /*invocation*/
  481.         case 2: clir = "i"; break;  /*suppression*/
  482.         default:
  483.         case 0: clir = ""; break;   /*subscription default*/
  484.     }
  485.     asprintf(&cmd, "ATD%s%s;", p_dial->address, clir);
  486.     ret = at_send_command(cmd, NULL);
  487.     free(cmd);
  488.     /* success or failure is ignored by the upper layer here.
  489.        it will call GET_CURRENT_CALLS and determine success that way */
  490.     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  491. }
  492. static void requestWriteSmsToSim(void *data, size_t datalen, RIL_Token t)
  493. {
  494.     RIL_SMS_WriteArgs *p_args;
  495.     char *cmd;
  496.     int length;
  497.     int err;
  498.     ATResponse *p_response = NULL;
  499.     p_args = (RIL_SMS_WriteArgs *)data;
  500.     length = strlen(p_args->pdu)/2;
  501.     asprintf(&cmd, "AT+CMGW=%d,%d", length, p_args->status);
  502.     err = at_send_command_sms(cmd, p_args->pdu, "+CMGW:", &p_response);
  503.     if (err != 0 || p_response->success == 0) goto error;
  504.     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  505.     at_response_free(p_response);
  506.     return;
  507. error:
  508.     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  509.     at_response_free(p_response);
  510. }
  511. static void requestHangup(void *data, size_t datalen, RIL_Token t)
  512. {
  513.     int *p_line;
  514.     int ret;
  515.     char *cmd;
  516.     p_line = (int *)data;
  517.     // 3GPP 22.030 6.5.5
  518.     // "Releases a specific active call X"
  519.     asprintf(&cmd, "AT+CHLD=1%d", p_line[0]);
  520.     ret = at_send_command(cmd, NULL);
  521.     free(cmd);
  522.     /* success or failure is ignored by the upper layer here.
  523.        it will call GET_CURRENT_CALLS and determine success that way */
  524.     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  525. }
  526. static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
  527. {
  528.     ATResponse *p_response = NULL;
  529.     int err;
  530.     int response[2];
  531.     char *line;
  532.     err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
  533.     if (err < 0 || p_response->success == 0) {
  534.         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  535.         goto error;
  536.     }
  537.     line = p_response->p_intermediates->line;
  538.     err = at_tok_start(&line);
  539.     if (err < 0) goto error;
  540.     err = at_tok_nextint(&line, &(response[0]));
  541.     if (err < 0) goto error;
  542.     err = at_tok_nextint(&line, &(response[1]));
  543.     if (err < 0) goto error;
  544.     RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
  545.     at_response_free(p_response);
  546.     return;
  547. error:
  548.     LOGE("requestSignalStrength must never return an error when radio is on");
  549.     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  550.     at_response_free(p_response);
  551. }
  552. static void requestRegistrationState(int request, void *data,
  553.                                         size_t datalen, RIL_Token t)
  554. {
  555.     int err;
  556.     int response[4];
  557.     char * responseStr[4];
  558.     ATResponse *p_response = NULL;
  559.     const char *cmd;
  560.     const char *prefix;
  561.     char *line, *p;
  562.     int commas;
  563.     int skip;
  564.     int count = 3;
  565.     if (request == RIL_REQUEST_REGISTRATION_STATE) {
  566.         cmd = "AT+CREG?";
  567.         prefix = "+CREG:";
  568.     } else if (request == RIL_REQUEST_GPRS_REGISTRATION_STATE) {
  569.         cmd = "AT+CGREG?";
  570.         prefix = "+CGREG:";
  571.     } else {
  572.         assert(0);
  573.         goto error;
  574.     }
  575.     err = at_send_command_singleline(cmd, prefix, &p_response);
  576.     if (err != 0) goto error;
  577.     line = p_response->p_intermediates->line;
  578.     err = at_tok_start(&line);
  579.     if (err < 0) goto error;
  580.     /* Ok you have to be careful here
  581.      * The solicited version of the CREG response is
  582.      * +CREG: n, stat, [lac, cid]
  583.      * and the unsolicited version is
  584.      * +CREG: stat, [lac, cid]
  585.      * The <n> parameter is basically "is unsolicited creg on?"
  586.      * which it should always be
  587.      *
  588.      * Now we should normally get the solicited version here,
  589.      * but the unsolicited version could have snuck in
  590.      * so we have to handle both
  591.      *
  592.      * Also since the LAC and CID are only reported when registered,
  593.      * we can have 1, 2, 3, or 4 arguments here
  594.      *
  595.      * finally, a +CGREG: answer may have a fifth value that corresponds
  596.      * to the network type, as in;
  597.      *
  598.      *   +CGREG: n, stat [,lac, cid [,networkType]]
  599.      */
  600.     /* count number of commas */
  601.     commas = 0;
  602.     for (p = line ; *p != '' ;p++) {
  603.         if (*p == ',') commas++;
  604.     }
  605.     switch (commas) {
  606.         case 0: /* +CREG: <stat> */
  607.             err = at_tok_nextint(&line, &response[0]);
  608.             if (err < 0) goto error;
  609.             response[1] = -1;
  610.             response[2] = -1;
  611.         break;
  612.         case 1: /* +CREG: <n>, <stat> */
  613.             err = at_tok_nextint(&line, &skip);
  614.             if (err < 0) goto error;
  615.             err = at_tok_nextint(&line, &response[0]);
  616.             if (err < 0) goto error;
  617.             response[1] = -1;
  618.             response[2] = -1;
  619.             if (err < 0) goto error;
  620.         break;
  621.         case 2: /* +CREG: <stat>, <lac>, <cid> */
  622.             err = at_tok_nextint(&line, &response[0]);
  623.             if (err < 0) goto error;
  624.             err = at_tok_nexthexint(&line, &response[1]);
  625.             if (err < 0) goto error;
  626.             err = at_tok_nexthexint(&line, &response[2]);
  627.             if (err < 0) goto error;
  628.         break;
  629.         case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
  630.             err = at_tok_nextint(&line, &skip);
  631.             if (err < 0) goto error;
  632.             err = at_tok_nextint(&line, &response[0]);
  633.             if (err < 0) goto error;
  634.             err = at_tok_nexthexint(&line, &response[1]);
  635.             if (err < 0) goto error;
  636.             err = at_tok_nexthexint(&line, &response[2]);
  637.             if (err < 0) goto error;
  638.         break;
  639.         /* special case for CGREG, there is a fourth parameter
  640.          * that is the network type (unknown/gprs/edge/umts)
  641.          */
  642.         case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */
  643.             err = at_tok_nextint(&line, &skip);
  644.             if (err < 0) goto error;
  645.             err = at_tok_nextint(&line, &response[0]);
  646.             if (err < 0) goto error;
  647.             err = at_tok_nexthexint(&line, &response[1]);
  648.             if (err < 0) goto error;
  649.             err = at_tok_nexthexint(&line, &response[2]);
  650.             if (err < 0) goto error;
  651.             err = at_tok_nexthexint(&line, &response[3]);
  652.             if (err < 0) goto error;
  653.             count = 4;
  654.         break;
  655.         default:
  656.             goto error;
  657.     }
  658.     asprintf(&responseStr[0], "%d", response[0]);
  659.     asprintf(&responseStr[1], "%d", response[1]);
  660.     asprintf(&responseStr[2], "%d", response[2]);
  661.     if (count > 3)
  662.         asprintf(&responseStr[3], "%d", response[3]);
  663.     RIL_onRequestComplete(t, RIL_E_SUCCESS, responseStr, count*sizeof(char*));
  664.     at_response_free(p_response);
  665.     return;
  666. error:
  667.     LOGE("requestRegistrationState must never return an error when radio is on");
  668.     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  669.     at_response_free(p_response);
  670. }
  671. static void requestOperator(void *data, size_t datalen, RIL_Token t)
  672. {
  673.     int err;
  674.     int i;
  675.     int skip;
  676.     ATLine *p_cur;
  677.     char *response[3];
  678.     memset(response, 0, sizeof(response));
  679.     ATResponse *p_response = NULL;
  680.     err = at_send_command_multiline(
  681.         "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?",
  682.         "+COPS:", &p_response);
  683.     /* we expect 3 lines here:
  684.      * +COPS: 0,0,"T - Mobile"
  685.      * +COPS: 0,1,"TMO"
  686.      * +COPS: 0,2,"310170"
  687.      */
  688.     if (err != 0) goto error;
  689.     for (i = 0, p_cur = p_response->p_intermediates
  690.             ; p_cur != NULL
  691.             ; p_cur = p_cur->p_next, i++
  692.     ) {
  693.         char *line = p_cur->line;
  694.         err = at_tok_start(&line);
  695.         if (err < 0) goto error;
  696.         err = at_tok_nextint(&line, &skip);
  697.         if (err < 0) goto error;
  698.         // If we're unregistered, we may just get
  699.         // a "+COPS: 0" response
  700.         if (!at_tok_hasmore(&line)) {
  701.             response[i] = NULL;
  702.             continue;
  703.         }
  704.         err = at_tok_nextint(&line, &skip);
  705.         if (err < 0) goto error;
  706.         // a "+COPS: 0, n" response is also possible
  707.         if (!at_tok_hasmore(&line)) {
  708.             response[i] = NULL;
  709.             continue;
  710.         }
  711.         err = at_tok_nextstr(&line, &(response[i]));
  712.         if (err < 0) goto error;
  713.     }
  714.     if (i != 3) {
  715.         /* expect 3 lines exactly */
  716.         goto error;
  717.     }
  718.     RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
  719.     at_response_free(p_response);
  720.     return;
  721. error:
  722.     LOGE("requestOperator must not return error when radio is on");
  723.     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  724.     at_response_free(p_response);
  725. }
  726. static void requestSendSMS(void *data, size_t datalen, RIL_Token t)
  727. {
  728.     int err;
  729.     const char *smsc;
  730.     const char *pdu;
  731.     int tpLayerLength;
  732.     char *cmd1, *cmd2;
  733.     RIL_SMS_Response response;
  734.     ATResponse *p_response = NULL;
  735.     smsc = ((const char **)data)[0];
  736.     pdu = ((const char **)data)[1];
  737.     tpLayerLength = strlen(pdu)/2;
  738.     // "NULL for default SMSC"
  739.     if (smsc == NULL) {
  740.         smsc= "00";
  741.     }
  742.     asprintf(&cmd1, "AT+CMGS=%d", tpLayerLength);
  743.     asprintf(&cmd2, "%s%s", smsc, pdu);
  744.     err = at_send_command_sms(cmd1, cmd2, "+CMGS:", &p_response);
  745.     if (err != 0 || p_response->success == 0) goto error;
  746.     memset(&response, 0, sizeof(response));
  747.     /* FIXME fill in messageRef and ackPDU */
  748.     RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
  749.     at_response_free(p_response);
  750.     return;
  751. error:
  752.     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  753.     at_response_free(p_response);
  754. }
  755. static void requestSetupDefaultPDP(void *data, size_t datalen, RIL_Token t)
  756. {
  757.     const char *apn;
  758.     char *cmd;
  759.     int err;
  760.     ATResponse *p_response = NULL;
  761.     char *response[2] = { "1", PPP_TTY_PATH };
  762.     apn = ((const char **)data)[0];
  763. #ifdef USE_TI_COMMANDS
  764.     // Config for multislot class 10 (probably default anyway eh?)
  765.     err = at_send_command("AT%CPRIM="GMM","CONFIG MULTISLOT_CLASS=<10>"",
  766.                         NULL);
  767.     err = at_send_command("AT%DATA=2,"UART",1,,"SER","UART",0", NULL);
  768. #endif /* USE_TI_COMMANDS */
  769.     int fd, qmistatus;
  770.     size_t cur = 0;
  771.     size_t len;
  772.     ssize_t written, rlen;
  773.     char status[32] = {0};
  774.     int retry = 10;
  775.     LOGD("requesting data connection to APN '%s'", apn);
  776.     fd = open ("/dev/qmi", O_RDWR);
  777.     if (fd >= 0) { /* the device doesn't exist on the emulator */
  778.     LOGD("opened the qmi devicen");
  779.     asprintf(&cmd, "up:%s", apn);
  780.     len = strlen(cmd);
  781.     while (cur < len) {
  782.     do {
  783.             written = write (fd, cmd + cur, len - cur);
  784.         } while (written < 0 && errno == EINTR);
  785.         if (written < 0) {
  786.                 LOGE("### ERROR writing to /dev/qmi");
  787.                 close(fd);
  788.                 goto error;
  789.             }
  790.             cur += written;
  791.         }
  792.         // wait for interface to come online
  793.         do {
  794.             sleep(1);
  795.             do {
  796.                 rlen = read(fd, status, 31);
  797.             } while (rlen < 0 && errno == EINTR);
  798.             if (rlen < 0) {
  799.                 LOGE("### ERROR reading from /dev/qmi");
  800.                 close(fd);
  801.                 goto error;
  802.             } else {
  803.                 status[rlen] = '';
  804.                 LOGD("### status: %s", status);
  805.             }
  806.         } while (strncmp(status, "STATE=up", 8) && strcmp(status, "online") && --retry);
  807.         close(fd);
  808.         if (retry == 0) {
  809.             LOGE("### Failed to get data connection upn");
  810.         goto error;
  811. }
  812.         qmistatus = system("netcfg rmnet0 dhcp");
  813.         LOGD("netcfg rmnet0 dhcp: status %dn", qmistatus);
  814.     if (qmistatus < 0) goto error;
  815. } else {
  816.         asprintf(&cmd, "AT+CGDCONT=1,"IP","%s",,0,0", apn);
  817.     //FIXME check for error here
  818.     err = at_send_command(cmd, NULL);
  819.     free(cmd);
  820.     // Set required QoS params to default
  821.     err = at_send_command("AT+CGQREQ=1", NULL);
  822.     // Set minimum QoS params to default
  823.     err = at_send_command("AT+CGQMIN=1", NULL);
  824.     // packet-domain event reporting
  825.     err = at_send_command("AT+CGEREP=1,0", NULL);
  826.     // Hangup anything that's happening there now
  827.     err = at_send_command("AT+CGACT=1,0", NULL);
  828.     // Start data on PDP context 1
  829.     err = at_send_command("ATD*99***1#", &p_response);
  830.     if (err < 0 || p_response->success == 0) {
  831.         goto error;
  832.     }
  833.     }
  834.     RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
  835.     at_response_free(p_response);
  836.     return;
  837. error:
  838.     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  839.     at_response_free(p_response);
  840. }
  841. static void requestSMSAcknowledge(void *data, size_t datalen, RIL_Token t)
  842. {
  843.     int ackSuccess;
  844.     int err;
  845.     ackSuccess = ((int *)data)[0];
  846.     if (ackSuccess == 1) {
  847.         err = at_send_command("AT+CNMA=1", NULL);
  848.     } else if (ackSuccess == 0)  {
  849.         err = at_send_command("AT+CNMA=2", NULL);
  850.     } else {
  851.         LOGE("unsupported arg to RIL_REQUEST_SMS_ACKNOWLEDGEn");
  852.         goto error;
  853.     }
  854.     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  855. error:
  856.     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  857. }
  858. static void  requestSIM_IO(void *data, size_t datalen, RIL_Token t)
  859. {
  860.     ATResponse *p_response = NULL;
  861.     RIL_SIM_IO_Response sr;
  862.     int err;
  863.     char *cmd = NULL;
  864.     RIL_SIM_IO *p_args;
  865.     char *line;
  866.     memset(&sr, 0, sizeof(sr));
  867.     p_args = (RIL_SIM_IO *)data;
  868.     /* FIXME handle pin2 */
  869.     if (p_args->data == NULL) {
  870.         asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d",
  871.                     p_args->command, p_args->fileid,
  872.                     p_args->p1, p_args->p2, p_args->p3);
  873.     } else {
  874.         asprintf(&cmd, "AT+CRSM=%d,%d,%d,%d,%d,%s",
  875.                     p_args->command, p_args->fileid,
  876.                     p_args->p1, p_args->p2, p_args->p3, p_args->data);
  877.     }
  878.     err = at_send_command_singleline(cmd, "+CRSM:", &p_response);
  879.     if (err < 0 || p_response->success == 0) {
  880.         goto error;
  881.     }
  882.     line = p_response->p_intermediates->line;
  883.     err = at_tok_start(&line);
  884.     if (err < 0) goto error;
  885.     err = at_tok_nextint(&line, &(sr.sw1));
  886.     if (err < 0) goto error;
  887.     err = at_tok_nextint(&line, &(sr.sw2));
  888.     if (err < 0) goto error;
  889.     if (at_tok_hasmore(&line)) {
  890.         err = at_tok_nextstr(&line, &(sr.simResponse));
  891.         if (err < 0) goto error;
  892.     }
  893.     RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
  894.     at_response_free(p_response);
  895.     free(cmd);
  896.     return;
  897. error:
  898.     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  899.     at_response_free(p_response);
  900.     free(cmd);
  901. }
  902. static void  requestEnterSimPin(void*  data, size_t  datalen, RIL_Token  t)
  903. {
  904.     ATResponse   *p_response = NULL;
  905.     int           err;
  906.     char*         cmd = NULL;
  907.     const char**  strings = (const char**)data;;
  908.     if ( datalen == sizeof(char*) ) {
  909.         asprintf(&cmd, "AT+CPIN=%s", strings[0]);
  910.     } else if ( datalen == 2*sizeof(char*) ) {
  911.         asprintf(&cmd, "AT+CPIN=%s,%s", strings[0], strings[1]);
  912.     } else
  913.         goto error;
  914.     err = at_send_command_singleline(cmd, "+CPIN:", &p_response);
  915.     free(cmd);
  916.     if (err < 0 || p_response->success == 0) {
  917. error:
  918.         RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, NULL, 0);
  919.     } else {
  920.         RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  921.     }
  922.     at_response_free(p_response);
  923. }
  924. static void  requestSendUSSD(void *data, size_t datalen, RIL_Token t)
  925. {
  926.     const char *ussdRequest;
  927.     ussdRequest = (char *)(data);
  928.     RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
  929. // @@@ TODO
  930. }
  931. /*** Callback methods from the RIL library to us ***/
  932. /**
  933.  * Call from RIL to us to make a RIL_REQUEST
  934.  *
  935.  * Must be completed with a call to RIL_onRequestComplete()
  936.  *
  937.  * RIL_onRequestComplete() may be called from any thread, before or after
  938.  * this function returns.
  939.  *
  940.  * Will always be called from the same thread, so returning here implies
  941.  * that the radio is ready to process another command (whether or not
  942.  * the previous command has completed).
  943.  */
  944. static void
  945. onRequest (int request, void *data, size_t datalen, RIL_Token t)
  946. {
  947.     ATResponse *p_response;
  948.     int err;
  949.     LOGD("onRequest: %s", requestToString(request));
  950.     /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
  951.      * when RADIO_STATE_UNAVAILABLE.
  952.      */
  953.     if (sState == RADIO_STATE_UNAVAILABLE
  954.         && request != RIL_REQUEST_GET_SIM_STATUS
  955.     ) {
  956.         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
  957.         return;
  958.     }
  959.     /* Ignore all non-power requests when RADIO_STATE_OFF
  960.      * (except RIL_REQUEST_GET_SIM_STATUS)
  961.      */
  962.     if (sState == RADIO_STATE_OFF
  963.         && !(request == RIL_REQUEST_RADIO_POWER
  964.             || request == RIL_REQUEST_GET_SIM_STATUS)
  965.     ) {
  966.         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
  967.         return;
  968.     }
  969.     switch (request) {
  970.         case RIL_REQUEST_GET_SIM_STATUS: {
  971.             int simStatus;
  972.             simStatus = getSIMStatus();
  973.             RIL_onRequestComplete(t, RIL_E_SUCCESS, &simStatus, sizeof(simStatus));
  974.             break;
  975.         }
  976.         case RIL_REQUEST_GET_CURRENT_CALLS:
  977.             requestGetCurrentCalls(data, datalen, t);
  978.             break;
  979.         case RIL_REQUEST_DIAL:
  980.             requestDial(data, datalen, t);
  981.             break;
  982.         case RIL_REQUEST_HANGUP:
  983.             requestHangup(data, datalen, t);
  984.             break;
  985.         case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
  986.             // 3GPP 22.030 6.5.5
  987.             // "Releases all held calls or sets User Determined User Busy
  988.             //  (UDUB) for a waiting call."
  989.             at_send_command("AT+CHLD=0", NULL);
  990.             /* success or failure is ignored by the upper layer here.
  991.                it will call GET_CURRENT_CALLS and determine success that way */
  992.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  993.             break;
  994.         case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
  995.             // 3GPP 22.030 6.5.5
  996.             // "Releases all active calls (if any exist) and accepts
  997.             //  the other (held or waiting) call."
  998.             at_send_command("AT+CHLD=1", NULL);
  999.             /* success or failure is ignored by the upper layer here.
  1000.                it will call GET_CURRENT_CALLS and determine success that way */
  1001.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  1002.             break;
  1003.         case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
  1004.             // 3GPP 22.030 6.5.5
  1005.             // "Places all active calls (if any exist) on hold and accepts
  1006.             //  the other (held or waiting) call."
  1007.             at_send_command("AT+CHLD=2", NULL);
  1008. #ifdef WORKAROUND_ERRONEOUS_ANSWER
  1009.             s_expectAnswer = 1;
  1010. #endif /* WORKAROUND_ERRONEOUS_ANSWER */
  1011.             /* success or failure is ignored by the upper layer here.
  1012.                it will call GET_CURRENT_CALLS and determine success that way */
  1013.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  1014.             break;
  1015.         case RIL_REQUEST_ANSWER:
  1016.             at_send_command("ATA", NULL);
  1017. #ifdef WORKAROUND_ERRONEOUS_ANSWER
  1018.             s_expectAnswer = 1;
  1019. #endif /* WORKAROUND_ERRONEOUS_ANSWER */
  1020.             /* success or failure is ignored by the upper layer here.
  1021.                it will call GET_CURRENT_CALLS and determine success that way */
  1022.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  1023.             break;
  1024.         case RIL_REQUEST_CONFERENCE:
  1025.             // 3GPP 22.030 6.5.5
  1026.             // "Adds a held call to the conversation"
  1027.             at_send_command("AT+CHLD=3", NULL);
  1028.             /* success or failure is ignored by the upper layer here.
  1029.                it will call GET_CURRENT_CALLS and determine success that way */
  1030.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  1031.             break;
  1032.         case RIL_REQUEST_UDUB:
  1033.             /* user determined user busy */
  1034.             /* sometimes used: ATH */
  1035.             at_send_command("ATH", NULL);
  1036.             /* success or failure is ignored by the upper layer here.
  1037.                it will call GET_CURRENT_CALLS and determine success that way */
  1038.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  1039.             break;
  1040.         case RIL_REQUEST_SEPARATE_CONNECTION:
  1041.             {
  1042.                 char  cmd[12];
  1043.                 int   party = ((int*)data)[0];
  1044.                 // Make sure that party is in a valid range.
  1045.                 // (Note: The Telephony middle layer imposes a range of 1 to 7.
  1046.                 // It's sufficient for us to just make sure it's single digit.)
  1047.                 if (party > 0 && party < 10) {
  1048.                     sprintf(cmd, "AT+CHLD=2%d", party);
  1049.                     at_send_command(cmd, NULL);
  1050.                     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  1051.                 } else {
  1052.                     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  1053.                 }
  1054.             }
  1055.             break;
  1056.         case RIL_REQUEST_SIGNAL_STRENGTH:
  1057.             requestSignalStrength(data, datalen, t);
  1058.             break;
  1059.         case RIL_REQUEST_REGISTRATION_STATE:
  1060.         case RIL_REQUEST_GPRS_REGISTRATION_STATE:
  1061.             requestRegistrationState(request, data, datalen, t);
  1062.             break;
  1063.         case RIL_REQUEST_OPERATOR:
  1064.             requestOperator(data, datalen, t);
  1065.             break;
  1066.         case RIL_REQUEST_RADIO_POWER:
  1067.             requestRadioPower(data, datalen, t);
  1068.             break;
  1069.         case RIL_REQUEST_DTMF: {
  1070.             char c = ((char *)data)[0];
  1071.             char *cmd;
  1072.             asprintf(&cmd, "AT+VTS=%c", (int)c);
  1073.             at_send_command(cmd, NULL);
  1074.             free(cmd);
  1075.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  1076.             break;
  1077.         }
  1078.         case RIL_REQUEST_SEND_SMS:
  1079.             requestSendSMS(data, datalen, t);
  1080.             break;
  1081.         case RIL_REQUEST_SETUP_DEFAULT_PDP:
  1082.             requestSetupDefaultPDP(data, datalen, t);
  1083.             break;
  1084.         case RIL_REQUEST_SMS_ACKNOWLEDGE:
  1085.             requestSMSAcknowledge(data, datalen, t);
  1086.             break;
  1087.         case RIL_REQUEST_GET_IMSI:
  1088.             p_response = NULL;
  1089.             err = at_send_command_numeric("AT+CIMI", &p_response);
  1090.             if (err < 0 || p_response->success == 0) {
  1091.                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  1092.             } else {
  1093.                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
  1094.                     p_response->p_intermediates->line, sizeof(char *));
  1095.             }
  1096.             at_response_free(p_response);
  1097.             break;
  1098.         case RIL_REQUEST_GET_IMEI:
  1099.             p_response = NULL;
  1100.             err = at_send_command_numeric("AT+CGSN", &p_response);
  1101.             if (err < 0 || p_response->success == 0) {
  1102.                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  1103.             } else {
  1104.                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
  1105.                     p_response->p_intermediates->line, sizeof(char *));
  1106.             }
  1107.             at_response_free(p_response);
  1108.             break;
  1109.         case RIL_REQUEST_SIM_IO:
  1110.             requestSIM_IO(data,datalen,t);
  1111.             break;
  1112.         case RIL_REQUEST_SEND_USSD:
  1113.             requestSendUSSD(data, datalen, t);
  1114.             break;
  1115.         case RIL_REQUEST_CANCEL_USSD:
  1116.             p_response = NULL;
  1117.             err = at_send_command_numeric("AT+CUSD=2", &p_response);
  1118.             if (err < 0 || p_response->success == 0) {
  1119.                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  1120.             } else {
  1121.                 RIL_onRequestComplete(t, RIL_E_SUCCESS,
  1122.                     p_response->p_intermediates->line, sizeof(char *));
  1123.             }
  1124.             at_response_free(p_response);
  1125.             break;
  1126.         case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
  1127.             at_send_command("AT+COPS=0", NULL);
  1128.             break;
  1129.         case RIL_REQUEST_PDP_CONTEXT_LIST:
  1130.             requestPDPContextList(data, datalen, t);
  1131.             break;
  1132.         case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
  1133.             requestQueryNetworkSelectionMode(data, datalen, t);
  1134.             break;
  1135.         case RIL_REQUEST_OEM_HOOK_RAW:
  1136.             // echo back data
  1137.             RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
  1138.             break;
  1139.         case RIL_REQUEST_OEM_HOOK_STRINGS: {
  1140.             int i;
  1141.             const char ** cur;
  1142.             LOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);
  1143.             for (i = (datalen / sizeof (char *)), cur = (const char **)data ;
  1144.                     i > 0 ; cur++, i --) {
  1145.                 LOGD("> '%s'", *cur);
  1146.             }
  1147.             // echo back strings
  1148.             RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);
  1149.             break;
  1150.         }
  1151.         case RIL_REQUEST_WRITE_SMS_TO_SIM:
  1152.             requestWriteSmsToSim(data, datalen, t);
  1153.             break;
  1154.         case RIL_REQUEST_DELETE_SMS_ON_SIM: {
  1155.             char * cmd;
  1156.             p_response = NULL;
  1157.             asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);
  1158.             err = at_send_command(cmd, &p_response);
  1159.             free(cmd);
  1160.             if (err < 0 || p_response->success == 0) {
  1161.                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
  1162.             } else {
  1163.                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
  1164.             }
  1165.             at_response_free(p_response);
  1166.             break;
  1167.         }
  1168.         case RIL_REQUEST_ENTER_SIM_PIN:
  1169.         case RIL_REQUEST_ENTER_SIM_PUK:
  1170.         case RIL_REQUEST_ENTER_SIM_PIN2:
  1171.         case RIL_REQUEST_ENTER_SIM_PUK2:
  1172.         case RIL_REQUEST_CHANGE_SIM_PIN:
  1173.         case RIL_REQUEST_CHANGE_SIM_PIN2:
  1174.             requestEnterSimPin(data, datalen, t);
  1175.             break;
  1176.         default:
  1177.             RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
  1178.             break;
  1179.     }
  1180. }
  1181. /**
  1182.  * Synchronous call from the RIL to us to return current radio state.
  1183.  * RADIO_STATE_UNAVAILABLE should be the initial state.
  1184.  */
  1185. static RIL_RadioState
  1186. currentState()
  1187. {
  1188.     return sState;
  1189. }
  1190. /**
  1191.  * Call from RIL to us to find out whether a specific request code
  1192.  * is supported by this implementation.
  1193.  *
  1194.  * Return 1 for "supported" and 0 for "unsupported"
  1195.  */
  1196. static int
  1197. onSupports (int requestCode)
  1198. {
  1199.     //@@@ todo
  1200.     return 1;
  1201. }
  1202. static void onCancel (RIL_Token t)
  1203. {
  1204.     //@@@todo
  1205. }
  1206. static const char * getVersion(void)
  1207. {
  1208.     return "android reference-ril 1.0";
  1209. }
  1210. static void
  1211. setRadioState(RIL_RadioState newState)
  1212. {
  1213.     RIL_RadioState oldState;
  1214.     pthread_mutex_lock(&s_state_mutex);
  1215.     oldState = sState;
  1216.     if (s_closed > 0) {
  1217.         // If we're closed, the only reasonable state is
  1218.         // RADIO_STATE_UNAVAILABLE
  1219.         // This is here because things on the main thread
  1220.         // may attempt to change the radio state after the closed
  1221.         // event happened in another thread
  1222.         newState = RADIO_STATE_UNAVAILABLE;
  1223.     }
  1224.     if (sState != newState || s_closed > 0) {
  1225.         sState = newState;
  1226.         pthread_cond_broadcast (&s_state_cond);
  1227.     }
  1228.     pthread_mutex_unlock(&s_state_mutex);
  1229.     /* do these outside of the mutex */
  1230.     if (sState != oldState) {
  1231.         RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
  1232.                                     NULL, 0);
  1233.         /* FIXME onSimReady() and onRadioPowerOn() cannot be called
  1234.          * from the AT reader thread
  1235.          * Currently, this doesn't happen, but if that changes then these
  1236.          * will need to be dispatched on the request thread
  1237.          */
  1238.         if (sState == RADIO_STATE_SIM_READY) {
  1239.             onSIMReady();
  1240.         } else if (sState == RADIO_STATE_SIM_NOT_READY) {
  1241.             onRadioPowerOn();
  1242.         }
  1243.     }
  1244. }
  1245. /** returns one of RIM_SIM_*. Returns RIL_SIM_NOT_READY on error */
  1246. static int
  1247. getSIMStatus()
  1248. {
  1249.     ATResponse *p_response = NULL;
  1250.     int err;
  1251.     int ret;
  1252.     char *cpinLine;
  1253.     char *cpinResult;
  1254.     if (sState == RADIO_STATE_OFF || sState == RADIO_STATE_UNAVAILABLE) {
  1255.         ret = RIL_SIM_NOT_READY;
  1256.         goto done;
  1257.     }
  1258.     err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
  1259.     if (err != 0) {
  1260.         ret = RIL_SIM_NOT_READY;
  1261.         goto done;
  1262.     }
  1263.     switch (at_get_cme_error(p_response)) {
  1264.         case CME_SUCCESS:
  1265.             break;
  1266.         case CME_SIM_NOT_INSERTED:
  1267.             ret = RIL_SIM_ABSENT;
  1268.             goto done;
  1269.         default:
  1270.             ret = RIL_SIM_NOT_READY;
  1271.             goto done;
  1272.     }
  1273.     /* CPIN? has succeeded, now look at the result */
  1274.     cpinLine = p_response->p_intermediates->line;
  1275.     err = at_tok_start (&cpinLine);
  1276.     if (err < 0) {
  1277.         ret = RIL_SIM_NOT_READY;
  1278.         goto done;
  1279.     }
  1280.     err = at_tok_nextstr(&cpinLine, &cpinResult);
  1281.     if (err < 0) {
  1282.         ret = RIL_SIM_NOT_READY;
  1283.         goto done;
  1284.     }
  1285.     if (0 == strcmp (cpinResult, "SIM PIN")) {
  1286.         ret = RIL_SIM_PIN;
  1287.         goto done;
  1288.     } else if (0 == strcmp (cpinResult, "SIM PUK")) {
  1289.         ret = RIL_SIM_PUK;
  1290.         goto done;
  1291.     } else if (0 == strcmp (cpinResult, "PH-NET PIN")) {
  1292.         return RIL_SIM_NETWORK_PERSONALIZATION;
  1293.     } else if (0 != strcmp (cpinResult, "READY"))  {
  1294.         /* we're treating unsupported lock types as "sim absent" */
  1295.         ret = RIL_SIM_ABSENT;
  1296.         goto done;
  1297.     }
  1298.     at_response_free(p_response);
  1299.     p_response = NULL;
  1300.     cpinResult = NULL;
  1301.     ret = RIL_SIM_READY;
  1302. done:
  1303.     at_response_free(p_response);
  1304.     return ret;
  1305. }
  1306. /**
  1307.  * SIM ready means any commands that access the SIM will work, including:
  1308.  *  AT+CPIN, AT+CSMS, AT+CNMI, AT+CRSM
  1309.  *  (all SMS-related commands)
  1310.  */
  1311. static void pollSIMState (void *param)
  1312. {
  1313.     ATResponse *p_response;
  1314.     int ret;
  1315.     if (sState != RADIO_STATE_SIM_NOT_READY) {
  1316.         // no longer valid to poll
  1317.         return;
  1318.     }
  1319.     switch(getSIMStatus()) {
  1320.         case RIL_SIM_ABSENT:
  1321.         case RIL_SIM_PIN:
  1322.         case RIL_SIM_PUK:
  1323.         case RIL_SIM_NETWORK_PERSONALIZATION:
  1324.         default:
  1325.             setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT);
  1326.         return;
  1327.         case RIL_SIM_NOT_READY:
  1328.             RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
  1329.         return;
  1330.         case RIL_SIM_READY:
  1331.             setRadioState(RADIO_STATE_SIM_READY);
  1332.         return;
  1333.     }
  1334. }
  1335. /** returns 1 if on, 0 if off, and -1 on error */
  1336. static int isRadioOn()
  1337. {
  1338.     ATResponse *p_response = NULL;
  1339.     int err;
  1340.     char *line;
  1341.     char ret;
  1342.     err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response);
  1343.     if (err < 0 || p_response->success == 0) {
  1344.         // assume radio is off
  1345.         goto error;
  1346.     }
  1347.     line = p_response->p_intermediates->line;
  1348.     err = at_tok_start(&line);
  1349.     if (err < 0) goto error;
  1350.     err = at_tok_nextbool(&line, &ret);
  1351.     if (err < 0) goto error;
  1352.     at_response_free(p_response);
  1353.     return (int)ret;
  1354. error:
  1355.     at_response_free(p_response);
  1356.     return -1;
  1357. }
  1358. /**
  1359.  * Initialize everything that can be configured while we're still in
  1360.  * AT+CFUN=0
  1361.  */
  1362. static void initializeCallback(void *param)
  1363. {
  1364.     ATResponse *p_response = NULL;
  1365.     int err;
  1366.     setRadioState (RADIO_STATE_OFF);
  1367.     at_handshake();
  1368.     /* note: we don't check errors here. Everything important will
  1369.        be handled in onATTimeout and onATReaderClosed */
  1370.     /*  atchannel is tolerant of echo but it must */
  1371.     /*  have verbose result codes */
  1372.     at_send_command("ATE0Q0V1", NULL);
  1373.     /*  No auto-answer */
  1374.     at_send_command("ATS0=0", NULL);
  1375.     /*  Extended errors */
  1376.     at_send_command("AT+CMEE=1", NULL);
  1377.     /*  Network registration events */
  1378.     err = at_send_command("AT+CREG=2", &p_response);
  1379.     /* some handsets -- in tethered mode -- don't support CREG=2 */
  1380.     if (err < 0 || p_response->success == 0) {
  1381.         at_send_command("AT+CREG=1", NULL);
  1382.     }
  1383.     at_response_free(p_response);
  1384.     /*  GPRS registration events */
  1385.     at_send_command("AT+CGREG=1", NULL);
  1386.     /*  Call Waiting notifications */
  1387.     at_send_command("AT+CCWA=1", NULL);
  1388.     /*  Alternating voice/data off */
  1389.     at_send_command("AT+CMOD=0", NULL);
  1390.     /*  Not muted */
  1391.     at_send_command("AT+CMUT=0", NULL);
  1392.     /*  +CSSU unsolicited supp service notifications */
  1393.     at_send_command("AT+CSSN=0,1", NULL);
  1394.     /*  no connected line identification */
  1395.     at_send_command("AT+COLP=0", NULL);
  1396.     /*  HEX character set */
  1397.     at_send_command("AT+CSCS="HEX"", NULL);
  1398.     /*  USSD unsolicited */
  1399.     at_send_command("AT+CUSD=1", NULL);
  1400.     /*  Enable +CGEV GPRS event notifications, but don't buffer */
  1401.     at_send_command("AT+CGEREP=1,0", NULL);
  1402.     /*  SMS PDU mode */
  1403.     at_send_command("AT+CMGF=0", NULL);
  1404. #ifdef USE_TI_COMMANDS
  1405.     at_send_command("AT%CPI=3", NULL);
  1406.     /*  TI specific -- notifications when SMS is ready (currently ignored) */
  1407.     at_send_command("AT%CSTAT=1", NULL);
  1408. #endif /* USE_TI_COMMANDS */
  1409.     /* assume radio is off on error */
  1410.     if (isRadioOn() > 0) {
  1411.         setRadioState (RADIO_STATE_SIM_NOT_READY);
  1412.     }
  1413. }
  1414. static void waitForClose()
  1415. {
  1416.     pthread_mutex_lock(&s_state_mutex);
  1417.     while (s_closed == 0) {
  1418.         pthread_cond_wait(&s_state_cond, &s_state_mutex);
  1419.     }
  1420.     pthread_mutex_unlock(&s_state_mutex);
  1421. }
  1422. /**
  1423.  * Called by atchannel when an unsolicited line appears
  1424.  * This is called on atchannel's reader thread. AT commands may
  1425.  * not be issued here
  1426.  */
  1427. static void onUnsolicited (const char *s, const char *sms_pdu)
  1428. {
  1429.     char *line = NULL;
  1430.     int err;
  1431.     /* Ignore unsolicited responses until we're initialized.
  1432.      * This is OK because the RIL library will poll for initial state
  1433.      */
  1434.     if (sState == RADIO_STATE_UNAVAILABLE) {
  1435.         return;
  1436.     }
  1437.     if (strStartsWith(s, "%CTZV:")) {
  1438.         /* TI specific -- NITZ time */
  1439.         char *response;
  1440.         line = strdup(s);
  1441.         at_tok_start(&line);
  1442.         err = at_tok_nextstr(&line, &response);
  1443.         if (err != 0) {
  1444.             LOGE("invalid NITZ line %sn", s);
  1445.         } else {
  1446.             RIL_onUnsolicitedResponse (
  1447.                 RIL_UNSOL_NITZ_TIME_RECEIVED,
  1448.                 response, strlen(response));
  1449.         }
  1450.     } else if (strStartsWith(s,"+CRING:")
  1451.                 || strStartsWith(s,"RING")
  1452.                 || strStartsWith(s,"NO CARRIER")
  1453.                 || strStartsWith(s,"+CCWA")
  1454.     ) {
  1455.         RIL_onUnsolicitedResponse (
  1456.             RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
  1457.             NULL, 0);
  1458. #ifdef WORKAROUND_FAKE_CGEV
  1459.         RIL_requestTimedCallback (onPDPContextListChanged, NULL, NULL);
  1460. #endif /* WORKAROUND_FAKE_CGEV */
  1461.     } else if (strStartsWith(s,"+CREG:")
  1462.                 || strStartsWith(s,"+CGREG:")
  1463.     ) {
  1464.         RIL_onUnsolicitedResponse (
  1465.             RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED,
  1466.             NULL, 0);
  1467. #ifdef WORKAROUND_FAKE_CGEV
  1468.         RIL_requestTimedCallback (onPDPContextListChanged, NULL, NULL);
  1469. #endif /* WORKAROUND_FAKE_CGEV */
  1470.     } else if (strStartsWith(s, "+CMT:")) {
  1471.         RIL_onUnsolicitedResponse (
  1472.             RIL_UNSOL_RESPONSE_NEW_SMS,
  1473.             sms_pdu, strlen(sms_pdu));
  1474.     } else if (strStartsWith(s, "+CDS:")) {
  1475.         RIL_onUnsolicitedResponse (
  1476.             RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
  1477.             sms_pdu, strlen(sms_pdu));
  1478.     } else if (strStartsWith(s, "+CGEV:")) {
  1479.         /* Really, we can ignore NW CLASS and ME CLASS events here,
  1480.          * but right now we don't since extranous
  1481.          * RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED calls are tolerated
  1482.          */
  1483.         /* can't issue AT commands here -- call on main thread */
  1484.         RIL_requestTimedCallback (onPDPContextListChanged, NULL, NULL);
  1485. #ifdef WORKAROUND_FAKE_CGEV
  1486.     } else if (strStartsWith(s, "+CME ERROR: 150")) {
  1487.         RIL_requestTimedCallback (onPDPContextListChanged, NULL, NULL);
  1488. #endif /* WORKAROUND_FAKE_CGEV */
  1489.     }
  1490. }
  1491. /* Called on command or reader thread */
  1492. static void onATReaderClosed()
  1493. {
  1494.     LOGI("AT channel closedn");
  1495.     at_close();
  1496.     s_closed = 1;
  1497.     setRadioState (RADIO_STATE_UNAVAILABLE);
  1498. }
  1499. /* Called on command thread */
  1500. static void onATTimeout()
  1501. {
  1502.     LOGI("AT channel timeout; closingn");
  1503.     at_close();
  1504.     s_closed = 1;
  1505.     /* FIXME cause a radio reset here */
  1506.     setRadioState (RADIO_STATE_UNAVAILABLE);
  1507. }
  1508. static void usage(char *s)
  1509. {
  1510. #ifdef RIL_SHLIB
  1511.     fprintf(stderr, "reference-ril requires: -p <tcp port> or -d /dev/tty_devicen");
  1512. #else
  1513.     fprintf(stderr, "usage: %s [-p <tcp port>] [-d /dev/tty_device]n", s);
  1514.     exit(-1);
  1515. #endif
  1516. }
  1517. static void *
  1518. mainLoop(void *param)
  1519. {
  1520.     int fd;
  1521.     int ret;
  1522.     AT_DUMP("== ", "entering mainLoop()", -1 );
  1523.     at_set_on_reader_closed(onATReaderClosed);
  1524.     at_set_on_timeout(onATTimeout);
  1525.     for (;;) {
  1526.         fd = -1;
  1527.         while  (fd < 0) {
  1528.             if (s_port > 0) {
  1529.                 fd = socket_loopback_client(s_port, SOCK_STREAM);
  1530.             } else if (s_device_socket) {
  1531.                 fd = socket_local_client( s_device_path,
  1532.                                           ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
  1533.                                           SOCK_STREAM );
  1534.             } else if (s_device_path != NULL) {
  1535.                 fd = open (s_device_path, O_RDWR);
  1536.                 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
  1537.                     /* disable echo on serial ports */
  1538.                     struct termios  ios;
  1539.                     tcgetattr( fd, &ios );
  1540.                     ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
  1541.                     tcsetattr( fd, TCSANOW, &ios );
  1542.                 }
  1543.             }
  1544.             if (fd < 0) {
  1545.                 perror ("opening AT interface. retrying...");
  1546.                 sleep(10);
  1547.                 /* never returns */
  1548.             }
  1549.         }
  1550.         s_closed = 0;
  1551.         ret = at_open(fd, onUnsolicited);
  1552.         if (ret < 0) {
  1553.             LOGE ("AT error %d on at_openn", ret);
  1554.             return 0;
  1555.         }
  1556.         RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
  1557.         // Give initializeCallback a chance to dispatched, since
  1558.         // we don't presently have a cancellation mechanism
  1559.         sleep(1);
  1560.         waitForClose();
  1561.         LOGI("Re-opening after close");
  1562.     }
  1563. }
  1564. #ifdef RIL_SHLIB
  1565. pthread_t s_tid_mainloop;
  1566. const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
  1567. {
  1568.     int ret;
  1569.     int fd = -1;
  1570.     int opt;
  1571.     pthread_attr_t attr;
  1572.     s_rilenv = env;
  1573.     while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {
  1574.         switch (opt) {
  1575.             case 'p':
  1576.                 s_port = atoi(optarg);
  1577.                 if (s_port == 0) {
  1578.                     usage(argv[0]);
  1579.                     return NULL;
  1580.                 }
  1581.                 LOGI("Opening loopback port %dn", s_port);
  1582.             break;
  1583.             case 'd':
  1584.                 s_device_path = optarg;
  1585.                 LOGI("Opening tty device %sn", s_device_path);
  1586.             break;
  1587.             case 's':
  1588.                 s_device_path   = optarg;
  1589.                 s_device_socket = 1;
  1590.                 LOGI("Opening socket %sn", s_device_path);
  1591.             break;
  1592.             default:
  1593.                 usage(argv[0]);
  1594.                 return NULL;
  1595.         }
  1596.     }
  1597.     if (s_port < 0 && s_device_path == NULL) {
  1598.         usage(argv[0]);
  1599.         return NULL;
  1600.     }
  1601.     pthread_attr_init (&attr);
  1602.     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  1603.     ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
  1604.     return &s_callbacks;
  1605. }
  1606. #else /* RIL_SHLIB */
  1607. int main (int argc, char **argv)
  1608. {
  1609.     int ret;
  1610.     int fd = -1;
  1611.     int opt;
  1612.     while ( -1 != (opt = getopt(argc, argv, "p:d:"))) {
  1613.         switch (opt) {
  1614.             case 'p':
  1615.                 s_port = atoi(optarg);
  1616.                 if (s_port == 0) {
  1617.                     usage(argv[0]);
  1618.                 }
  1619.                 LOGI("Opening loopback port %dn", s_port);
  1620.             break;
  1621.             case 'd':
  1622.                 s_device_path = optarg;
  1623.                 LOGI("Opening tty device %sn", s_device_path);
  1624.             break;
  1625.             case 's':
  1626.                 s_device_path   = optarg;
  1627.                 s_device_socket = 1;
  1628.                 LOGI("Opening socket %sn", s_device_path);
  1629.             break;
  1630.             default:
  1631.                 usage(argv[0]);
  1632.         }
  1633.     }
  1634.     if (s_port < 0 && s_device_path == NULL) {
  1635.         usage(argv[0]);
  1636.     }
  1637.     RIL_register(&s_callbacks);
  1638.     mainLoop(NULL);
  1639.     return 0;
  1640. }
  1641. #endif /* RIL_SHLIB */