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