• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "vendor_adapter.h"
17 
18 #include <fcntl.h>
19 #include <termios.h>
20 
21 #include "parameter.h"
22 
23 #include "at_call.h"
24 #include "at_data.h"
25 #include "at_modem.h"
26 #include "at_network.h"
27 #include "at_sim.h"
28 #include "at_sms.h"
29 #include "at_support.h"
30 #include "vendor_report.h"
31 
32 #include "hril_notification.h"
33 
34 #define DEVICE_PATH "/dev/ttyUSB0"
35 #define DEVICE_PATH_DEFAULT "/dev/ttyUSB"
36 
37 #define AT_TTY_PATH "persist.sys.radio.attty.path"
38 
39 static HRilRadioState g_radioState = HRIL_RADIO_POWER_STATE_UNAVAILABLE;
40 static pthread_mutex_t g_statusMutex = PTHREAD_MUTEX_INITIALIZER;
41 static pthread_cond_t g_statusCond = PTHREAD_COND_INITIALIZER;
42 static pthread_t g_eventListeners;
43 static int32_t g_fd = -1;
44 static int32_t g_atStatus = 0;
45 
46 static const HRilCallReq g_callReqOps = {
47     .GetCallList = ReqGetCallList,
48     .Dial = ReqDial,
49     .Hangup = ReqHangup,
50     .Reject = ReqReject,
51     .Answer = ReqAnswer,
52     .GetClip = ReqGetClip,
53     .SetClip = ReqSetClip,
54     .HoldCall = ReqHoldCall,
55     .UnHoldCall = ReqUnHoldCall,
56     .SwitchCall = ReqSwitchCall,
57     .CombineConference = ReqCombineConference,
58     .SeparateConference = ReqSeparateConference,
59     .CallSupplement = ReqCallSupplement,
60     .GetCallWaiting = ReqGetCallWaiting,
61     .SetCallWaiting = ReqSetCallWaiting,
62     .GetCallTransferInfo = ReqGetCallTransferInfo,
63     .SetCallTransferInfo = ReqSetCallTransferInfo,
64     .GetCallRestriction = ReqGetCallRestriction,
65     .SetCallRestriction = ReqSetCallRestriction,
66     .GetClir = ReqGetClir,
67     .SetClir = ReqSetClir,
68     .StartDtmf = ReqStartDtmf,
69     .SendDtmf = ReqSendDtmf,
70     .StopDtmf = ReqStopDtmf,
71     .GetImsCallList = ReqGetImsCallList,
72     .GetCallPreferenceMode = ReqGetCallPreferenceMode,
73     .SetCallPreferenceMode = ReqSetCallPreferenceMode,
74     .GetLteImsSwitchStatus = ReqGetLteImsSwitchStatus,
75     .SetLteImsSwitchStatus = ReqSetLteImsSwitchStatus,
76     .SetUssd = ReqSetUssd,
77     .GetUssd = ReqGetUssd,
78     .GetMute = ReqGetMute,
79     .SetMute = ReqSetMute,
80     .GetEmergencyCallList = ReqGetEmergencyCallList,
81     .GetCallFailReason = ReqGetCallFailReason,
82 };
83 
84 static const HRilSimReq g_simReqOps = {
85     .GetSimStatus = ReqGetSimStatus,
86     .GetSimImsi = ReqGetSimImsi,
87     .GetSimIO = ReqGetSimIO,
88     .GetSimLockStatus = ReqGetSimLockStatus,
89     .SetSimLock = ReqSetSimLock,
90     .ChangeSimPassword = ReqChangeSimPassword,
91     .UnlockPin = ReqUnlockPin,
92     .UnlockPuk = ReqUnlockPuk,
93     .GetSimPinInputTimes = ReqGetSimPinInputTimes,
94     .UnlockPin2 = ReqUnlockPin2,
95     .UnlockPuk2 = ReqUnlockPuk2,
96     .GetSimPin2InputTimes = ReqGetSimPin2InputTimes,
97     .SetActiveSim = ReqSetActiveSim,
98     .SimStkSendTerminalResponse = ReqSimStkSendTerminalResponse,
99     .SimStkSendEnvelope = ReqSimStkSendEnvelope,
100     .SimStkIsReady = ReqSimStkIsReady,
101     .SetRadioProtocol = ReqSetRadioProtocol,
102     .SimOpenLogicalChannel = ReqSimOpenLogicalChannel,
103     .SimCloseLogicalChannel = ReqSimCloseLogicalChannel,
104     .SimTransmitApduLogicalChannel = ReqSimTransmitApduLogicalChannel,
105     .UnlockSimLock = ReqUnlockSimLock,
106 };
107 
108 static const HRilSmsReq g_smsReqOps = {
109     .SendGsmSms = ReqSendGsmSms,
110     .SendSmsAck = ReqSendSmsAck,
111     .SendCdmaSms = ReqSendCdmaSms,
112     .SendCdmaAck = ReqSendCdmaSmsAck,
113     .AddSimMessage = ReqWriteSimMessage,
114     .DelSimMessage = ReqDelSimMessage,
115     .UpdateSimMessage = ReqWriteSimMessage,
116     .SetSmscAddr = ReqSetSmscAddr,
117     .GetSmscAddr = ReqGetSmscAddr,
118     .SetCBConfig = ReqSetCBConfig,
119     .GetCBConfig = ReqGetCBConfig,
120     .GetCdmaCBConfig = ReqGetCdmaCBConfig,
121     .SetCdmaCBConfig = ReqSetCdmaCBConfig,
122     .AddCdmaSimMessage = ReqAddCdmaSimMessage,
123     .DelCdmaSimMessage = ReqDelCdmaSimMessage,
124     .UpdateCdmaSimMessage = ReqUpdateCdmaSimMessage,
125 };
126 
127 static const HRilNetworkReq g_networkReqOps = {
128     .GetSignalStrength = ReqGetSignalStrength,
129     .GetImsRegStatus = ReqGetImsRegStatus,
130     .GetCsRegStatus = ReqGetCsRegStatus,
131     .GetPsRegStatus = ReqGetPsRegStatus,
132     .GetOperatorInfo = ReqGetOperatorInfo,
133     .GetNetworkSearchInformation = ReqGetNetworkSearchInformation,
134     .GetNetworkSelectionMode = ReqGetNetworkSelectionMode,
135     .SetNetworkSelectionMode = ReqSetNetworkSelectionMode,
136     .SetPreferredNetwork = ReqSetPreferredNetwork,
137     .GetPreferredNetwork = ReqGetPreferredNetwork,
138     .GetNeighboringCellInfoList = ReqGetNeighboringCellInfoList,
139     .GetCurrentCellInfo = ReqGetCurrentCellInfo,
140     .GetRadioCapability = ReqGetRadioCapability,
141     .GetPhysicalChannelConfig = ReqGetPhysicalChannelConfig,
142     .SetLocateUpdates = ReqSetLocateUpdates,
143 };
144 
145 static const HRilDataReq g_dataReqOps = {
146     .SetInitApnInfo = ReqSetInitApnInfo,
147     .ActivatePdpContext = ReqActivatePdpContext,
148     .DeactivatePdpContext = ReqDeactivatePdpContext,
149     .GetPdpContextList = ReqGetPdpContextList,
150     .GetLinkBandwidthInfo = ReqGetLinkBandwidthInfo,
151     .SetLinkBandwidthReportingRule = ReqSetLinkBandwidthReportingRule,
152 };
153 
154 static const HRilModemReq g_modemReqOps = {
155     .SetRadioState = ReqSetRadioState,
156     .GetRadioState = ReqGetRadioState,
157     .GetImei = ReqGetImei,
158     .GetMeid = ReqGetMeid,
159     .GetVoiceRadioTechnology = ReqGetVoiceRadioTechnology,
160 };
161 
162 HRilOps g_hrilOps = {
163     .callOps = &g_callReqOps,
164     .simOps = &g_simReqOps,
165     .smsOps = &g_smsReqOps,
166     .networkOps = &g_networkReqOps,
167     .dataOps = &g_dataReqOps,
168     .modemOps = &g_modemReqOps,
169 };
170 
GetRadioState(void)171 HRilRadioState GetRadioState(void)
172 {
173     return g_radioState;
174 }
175 
SetRadioState(HRilRadioState newState,int32_t rst)176 int32_t SetRadioState(HRilRadioState newState, int32_t rst)
177 {
178     char cmd[MAX_CMD_LENGTH] = {0};
179     ResponseInfo *pResponse = NULL;
180     HRilRadioState oldState;
181     const int32_t timeOut = 10000;
182     (void)memset_s(&oldState, sizeof(HRilRadioState), 0, sizeof(HRilRadioState));
183     struct ReportInfo reportInfo;
184     (void)memset_s(&reportInfo, sizeof(struct ReportInfo), 0, sizeof(struct ReportInfo));
185     if (g_atStatus > 0) {
186         newState = HRIL_RADIO_POWER_STATE_UNAVAILABLE;
187         pthread_cond_signal(&g_statusCond);
188         return -1;
189     }
190     pthread_mutex_lock(&g_statusMutex);
191     oldState = g_radioState;
192     if (oldState != newState || g_atStatus > 0) {
193         g_radioState = newState;
194         pthread_cond_broadcast(&g_statusCond);
195     }
196     pthread_mutex_unlock(&g_statusMutex);
197 
198     if (oldState != g_radioState) {
199         (void)sprintf_s(cmd, MAX_CMD_LENGTH, "AT+CFUN=%u,%d", newState, rst);
200         int32_t err = SendCommandLock(cmd, NULL, timeOut, &pResponse);
201         if (err != 0 || !pResponse->success) {
202             TELEPHONY_LOGE("AT+CFUN send failed");
203             FreeResponseInfo(pResponse);
204             return -1;
205         }
206     } else {
207         TELEPHONY_LOGE("now then is same state");
208         return HRIL_ERR_REPEAT_STATUS;
209     }
210 
211     FreeResponseInfo(pResponse);
212     reportInfo.notifyId = HNOTI_MODEM_RADIO_STATE_UPDATED;
213     reportInfo.type = HRIL_NOTIFICATION;
214     reportInfo.error = HRIL_ERR_SUCCESS;
215     OnModemReport(GetSlotId(NULL), reportInfo, (const uint8_t *)&g_radioState, sizeof(HRilRadioState));
216     return 0;
217 }
218 
AtOnUnusual(void)219 static void AtOnUnusual(void)
220 {
221     ATCloseReadLoop();
222     g_atStatus = 1;
223     g_fd = -1;
224     int32_t err = SetRadioState(HRIL_RADIO_POWER_STATE_OFF, 0);
225     if (err == -1) {
226         TELEPHONY_LOGE("RadioState set failed");
227     }
228 }
229 
WaitAtClose(void)230 static void WaitAtClose(void)
231 {
232     pthread_mutex_lock(&g_statusMutex);
233 
234     while (g_atStatus == 0) {
235         pthread_cond_wait(&g_statusCond, &g_statusMutex);
236     }
237 
238     pthread_mutex_unlock(&g_statusMutex);
239 }
240 
ModemInit(void)241 static int32_t ModemInit(void)
242 {
243     ResponseInfo *pResponse = NULL;
244     int32_t err = SetRadioState(HRIL_RADIO_POWER_STATE_ON, 0);
245     if (err == -1) {
246         TELEPHONY_LOGE("RadioState set failed");
247     }
248 
249     err = SendCommandLock("ATE0Q0V1", NULL, 0, &pResponse);
250     if (err != 0 || !pResponse->success) {
251         TELEPHONY_LOGE("ATE0Q0V1 send failed");
252     }
253     FreeResponseInfo(pResponse);
254     /* Network registration events */
255     err = SendCommandLock("AT+CREG=2", NULL, 0, &pResponse);
256     if (err != 0 || !pResponse->success) {
257         SendCommandLock("AT+CREG=2", NULL, 0, &pResponse);
258     }
259     FreeResponseInfo(pResponse);
260 
261     /* GPRS registration events */
262     err = SendCommandLock("AT+CGREG=2", NULL, 0, &pResponse);
263     if (err != 0 || !pResponse->success) {
264         SendCommandLock("AT+CGREG=2", NULL, 0, &pResponse);
265     }
266     FreeResponseInfo(pResponse);
267     /* Enable the extended format of incoming calls */
268     SendCommandLock("AT+CRC=1", NULL, 0, NULL);
269     /* Set the SMS service type to Phase 2+ version */
270     SendCommandLock("AT+CSMS=1", NULL, 0, NULL);
271     /* Set the new SMS reporting method to +CMTI */
272     SendCommandLock("AT+CNMI=1,2,0,1,1", NULL, 0, NULL);
273     /* Enable active reporting of (U)SIM status */
274     SendCommandLock("AT^SIMST=1", NULL, 0, NULL);
275     /* Disabled  auto-answer */
276     SendCommandLock("ATS0=0", NULL, 0, NULL);
277     /* Extended errors */
278     SendCommandLock("AT+CMEE=1", NULL, 0, NULL);
279     /* Set to signal  reporting */
280     SendCommandLock("AT^HCSQ=3,10", NULL, 0, NULL);
281     SendCommandLock("AT^CURCEX=2,F7FFFFFFFFFFFF", NULL, 0, NULL);
282     /* IMS registration events */
283     SendCommandLock("AT+CIREG=2", NULL, 0, NULL);
284     /*  Call Waiting notifications */
285     SendCommandLock("AT+CCWA=1", NULL, 0, NULL);
286     /* Disabled muted */
287     SendCommandLock("AT+CMUT=0", NULL, 0, NULL);
288     /* Enabled CSSU unsolicited supp service notifications */
289     SendCommandLock("AT+CSSN=0,1", NULL, 0, NULL);
290     /* Set SMS PDU mode */
291     SendCommandLock("AT+CMGF=0", NULL, 0, NULL);
292     /* Set UNICODE character */
293     SendCommandLock("AT+CSCS=\"IRA\"", NULL, 0, NULL);
294     /* Set sms memory */
295     SendCommandLock("AT+CPMS=\"SM\",\"SM\",\"ME\"", NULL, 0, NULL);
296     /* Set to open network time reporting */
297     SendCommandLock("AT^TIME=1", NULL, 0, NULL);
298     /* Set to open network time zone reporting */
299     SendCommandLock("AT+CTZR=1", NULL, 0, NULL);
300     /* Enabled SRVCC status to report actively: This command complies with the 3GPP TS 27.007 protocol. */
301     SendCommandLock("AT+CIREP=1", NULL, 0, NULL);
302 
303     sleep(SLEEP_TIME);
304     TELEPHONY_LOGI("enter to : ModemInit OnModemReport %{public}d", g_radioState);
305     struct ReportInfo reportInfo = {0};
306     reportInfo.notifyId = HNOTI_MODEM_RADIO_STATE_UPDATED;
307     reportInfo.type = HRIL_NOTIFICATION;
308     reportInfo.error = HRIL_ERR_SUCCESS;
309     OnModemReport(GetSlotId(NULL), reportInfo, (const uint8_t *)&g_radioState, sizeof(HRilRadioState));
310     return err;
311 }
312 
EventListeners(void)313 static void EventListeners(void)
314 {
315     int32_t waitNextTryTime = SLEEP_TIME;
316     const char *devicePath = DEVICE_PATH;
317     char atTtyPath[PARAMETER_SIZE] = {0};
318 
319     usleep(DELAY_WAIT_MS); // Prevent slow loading of system properties.
320     if (GetParameter(AT_TTY_PATH, "", atTtyPath, PARAMETER_SIZE) > 0) {
321         devicePath = atTtyPath;
322     }
323 
324     TELEPHONY_LOGI("opening AT interface %{public}s", devicePath);
325     AtSetOnUnusual(AtOnUnusual);
326     for (;;) {
327         while (g_fd < 0) {
328             if (devicePath != NULL) {
329                 g_fd = open(devicePath, O_RDWR);
330             }
331             if (g_fd >= 0 && !memcmp(devicePath, DEVICE_PATH_DEFAULT, sizeof(DEVICE_PATH_DEFAULT) - 1)) {
332                 struct termios ios;
333                 tcgetattr(g_fd, &ios);
334                 ios.c_lflag = 0;
335                 tcsetattr(g_fd, TCSANOW, &ios);
336             }
337             if (g_fd < 0) {
338                 TELEPHONY_LOGE("ril vendorlib,opening AT interface. retrying...");
339                 sleep(waitNextTryTime);
340             }
341         }
342         g_atStatus = 0;
343         int32_t ret = ATStartReadLoop(g_fd, OnNotifyOps);
344         if (ret < 0) {
345             TELEPHONY_LOGE("AtRead error %d\n", ret);
346             return;
347         }
348         ModemInit();
349         sleep(1);
350         WaitAtClose();
351     }
352 }
353 
RilInitOps(const struct HRilReport * reportOps)354 const HRilOps *RilInitOps(const struct HRilReport *reportOps)
355 {
356     pthread_attr_t attr;
357     SetReportOps(reportOps);
358     pthread_attr_init(&attr);
359     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
360     int32_t ret = pthread_create(&g_eventListeners, &attr, (void *(*)(void *))EventListeners, NULL);
361     if (ret < 0) {
362         TELEPHONY_LOGE("EventListeners create failed %d \n", ret);
363     }
364     if (g_hrilOps.smsOps == NULL) {
365         TELEPHONY_LOGE("g_hrilOps.smsOps is null");
366     }
367     TELEPHONY_LOGI("g_hrilOps.smsOps:%{public}p", g_hrilOps.smsOps);
368     return &g_hrilOps;
369 }
370