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