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 };
173 
174 static const HRilModemReq g_modemReqOps = {
175     .SetRadioState = ReqSetRadioState,
176     .GetRadioState = ReqGetRadioState,
177     .GetImei = ReqGetImei,
178     .GetImeiSv = ReqGetImeiSv,
179     .GetMeid = ReqGetMeid,
180     .GetVoiceRadioTechnology = ReqGetVoiceRadioTechnology,
181 };
182 
183 HRilOps g_hrilOps = {
184     .callOps = &g_callReqOps,
185     .simOps = &g_simReqOps,
186     .smsOps = &g_smsReqOps,
187     .networkOps = &g_networkReqOps,
188     .dataOps = &g_dataReqOps,
189     .modemOps = &g_modemReqOps,
190 };
191 
GetRadioState(void)192 HRilRadioState GetRadioState(void)
193 {
194     return g_radioState;
195 }
196 
SetRadioState(HRilRadioState newState,int32_t rst)197 int32_t SetRadioState(HRilRadioState newState, int32_t rst)
198 {
199     char cmd[MAX_CMD_LENGTH] = {0};
200     ResponseInfo *pResponse = NULL;
201     HRilRadioState oldState;
202     const int32_t timeOut = 10000;
203     (void)memset_s(&oldState, sizeof(HRilRadioState), 0, sizeof(HRilRadioState));
204     struct ReportInfo reportInfo;
205     (void)memset_s(&reportInfo, sizeof(struct ReportInfo), 0, sizeof(struct ReportInfo));
206     if (g_atStatus > 0) {
207         pthread_cond_signal(&g_statusCond);
208         return -1;
209     }
210 
211     pthread_mutex_lock(&g_statusMutex);
212     oldState = g_radioState;
213     if (oldState == newState) {
214         TELEPHONY_LOGE("now then is same state");
215         pthread_mutex_unlock(&g_statusMutex);
216         return HRIL_ERR_REPEAT_STATUS;
217     }
218     g_radioState = newState;
219     pthread_cond_broadcast(&g_statusCond);
220     pthread_mutex_unlock(&g_statusMutex);
221 
222     if (oldState != g_radioState) {
223         (void)sprintf_s(cmd, MAX_CMD_LENGTH, "AT+CFUN=%u,%d", newState, rst);
224         int32_t err = SendCommandLock(cmd, NULL, timeOut, &pResponse);
225         if (err != 0 || pResponse == NULL || !pResponse->success) {
226             TELEPHONY_LOGE("AT+CFUN send failed");
227             FreeResponseInfo(pResponse);
228             return -1;
229         }
230     }
231 
232     FreeResponseInfo(pResponse);
233     reportInfo.notifyId = HNOTI_MODEM_RADIO_STATE_UPDATED;
234     reportInfo.type = HRIL_NOTIFICATION;
235     reportInfo.error = HRIL_ERR_SUCCESS;
236     OnModemReport(GetSlotId(NULL), reportInfo, (const uint8_t *)&g_radioState, sizeof(HRilRadioState));
237     return 0;
238 }
239 
AtOnUnusual(void)240 static void AtOnUnusual(void)
241 {
242     ATCloseReadLoop();
243     g_atStatus = 1;
244     g_fd = -1;
245     int32_t err = SetRadioState(HRIL_RADIO_POWER_STATE_OFF, 0);
246     if (err == -1) {
247         TELEPHONY_LOGE("RadioState set failed");
248     }
249 }
250 
WaitAtClose(void)251 static void WaitAtClose(void)
252 {
253     pthread_mutex_lock(&g_statusMutex);
254 
255     while (g_atStatus == 0) {
256         pthread_cond_wait(&g_statusCond, &g_statusMutex);
257     }
258 
259     pthread_mutex_unlock(&g_statusMutex);
260 }
261 
ModemInit(void)262 static int32_t ModemInit(void)
263 {
264     ResponseInfo *pResponse = NULL;
265     int32_t err = SendCommandLock("ATE0Q0V1", NULL, 0, &pResponse);
266     if (err != 0 || pResponse == NULL || !pResponse->success) {
267         TELEPHONY_LOGE("ATE0Q0V1 send failed");
268     }
269     FreeResponseInfo(pResponse);
270     /* Network registration events */
271     err = SendCommandLock("AT+CREG=2", NULL, 0, &pResponse);
272     if (err != 0 || !pResponse->success) {
273         FreeResponseInfo(pResponse);
274         SendCommandLock("AT+CREG=2", NULL, 0, &pResponse);
275     }
276     FreeResponseInfo(pResponse);
277 
278     /* GPRS registration events */
279     err = SendCommandLock("AT+CGREG=2", NULL, 0, &pResponse);
280     if (err != 0 || !pResponse->success) {
281         FreeResponseInfo(pResponse);
282         SendCommandLock("AT+CGREG=2", NULL, 0, &pResponse);
283     }
284     FreeResponseInfo(pResponse);
285     /* Enable the extended format of incoming calls */
286     SendCommandLock("AT+CRC=1", NULL, 0, NULL);
287     /* Set the SMS service type to Phase 2+ version */
288     SendCommandLock("AT+CSMS=1", NULL, 0, NULL);
289     /* Set the new SMS reporting method to +CMTI */
290     SendCommandLock("AT+CNMI=1,2,0,1,1", NULL, 0, NULL);
291     /* Enable active reporting of (U)SIM status */
292     SendCommandLock("AT^SIMST=1", NULL, 0, NULL);
293     /* Disabled  auto-answer */
294     SendCommandLock("ATS0=0", NULL, 0, NULL);
295     /* Extended errors */
296     SendCommandLock("AT+CMEE=1", NULL, 0, NULL);
297     /* Set to signal  reporting */
298     SendCommandLock("AT^HCSQ=3,10", NULL, 0, NULL);
299     SendCommandLock("AT^CURCEX=2,F7FFFFFFFFFFFF", NULL, 0, NULL);
300     /* IMS registration events */
301     SendCommandLock("AT+CIREG=2", NULL, 0, NULL);
302     /*  Call Waiting notifications */
303     SendCommandLock("AT+CCWA=1", NULL, 0, NULL);
304     /* Disabled muted */
305     SendCommandLock("AT+CMUT=0", NULL, 0, NULL);
306     /* Enabled CSSU unsolicited supp service notifications */
307     SendCommandLock("AT+CSSN=0,1", NULL, 0, NULL);
308     /* Set SMS PDU mode */
309     SendCommandLock("AT+CMGF=0", NULL, 0, NULL);
310     /* Set UNICODE character */
311     SendCommandLock("AT+CSCS=\"IRA\"", NULL, 0, NULL);
312     /* Set sms memory */
313     SendCommandLock("AT+CPMS=\"SM\",\"SM\",\"ME\"", NULL, 0, NULL);
314     /* Set to open network time reporting */
315     SendCommandLock("AT^TIME=1", NULL, 0, NULL);
316     /* Set to open network time zone reporting */
317     SendCommandLock("AT+CTZR=1", NULL, 0, NULL);
318     /* Enabled SRVCC status to report actively: This command complies with the 3GPP TS 27.007 protocol. */
319     SendCommandLock("AT+CIREP=1", NULL, 0, NULL);
320 
321     err = SetRadioState(HRIL_RADIO_POWER_STATE_ON, 0);
322     if (err == -1) {
323         TELEPHONY_LOGE("RadioState set failed");
324         struct ReportInfo reportInfo = { 0 };
325         reportInfo.notifyId = HNOTI_MODEM_RADIO_STATE_UPDATED;
326         reportInfo.type = HRIL_NOTIFICATION;
327         reportInfo.error = HRIL_ERR_SUCCESS;
328         OnModemReport(GetSlotId(NULL), reportInfo, (const uint8_t *)&g_radioState, sizeof(HRilRadioState));
329     }
330     TELEPHONY_LOGI("ModemInit finish radioState %{public}d", g_radioState);
331     return err;
332 }
333 
EventListeners(void)334 static void EventListeners(void)
335 {
336     prctl(PR_SET_NAME, "hril_event_listeners");
337     int32_t waitNextTryTime = SLEEP_TIME;
338     const char *devicePath = DEVICE_PATH;
339     char atTtyPath[PARAMETER_SIZE] = {0};
340 
341     usleep(DELAY_WAIT_MS); // Prevent slow loading of system properties.
342     if (GetParameter(AT_TTY_PATH, "", atTtyPath, PARAMETER_SIZE) > 0) {
343         devicePath = atTtyPath;
344     }
345 
346     TELEPHONY_LOGI("opening AT interface %{public}s", devicePath);
347     AtSetOnUnusual(AtOnUnusual);
348     while (TRUE) {
349         while (g_fd < 0) {
350             if (devicePath != NULL) {
351                 g_fd = open(devicePath, O_RDWR);
352             }
353             if (g_fd < 0) {
354                 TELEPHONY_LOGE("ril vendorlib,opening AT interface. retrying...");
355                 sleep(waitNextTryTime);
356             } else if (!memcmp(devicePath, DEVICE_PATH_DEFAULT, sizeof(DEVICE_PATH_DEFAULT) - 1)) {
357                 struct termios ios;
358                 tcgetattr(g_fd, &ios);
359                 ios.c_lflag = 0;
360                 tcsetattr(g_fd, TCSANOW, &ios);
361             }
362         }
363         g_atStatus = 0;
364         int32_t ret = ATStartReadLoop(g_fd, OnNotifyOps);
365         if (ret < 0) {
366             TELEPHONY_LOGE("AtRead error %d\n", ret);
367             return;
368         }
369         ModemInit();
370         sleep(1);
371         WaitAtClose();
372     }
373 }
374 
RilInitOps(const struct HRilReport * reportOps)375 const HRilOps *RilInitOps(const struct HRilReport *reportOps)
376 {
377     pthread_attr_t attr;
378     SetReportOps(reportOps);
379     pthread_attr_init(&attr);
380     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
381     int32_t ret = pthread_create(&g_eventListeners, &attr, (void *(*)(void *))EventListeners, NULL);
382     if (ret < 0) {
383         TELEPHONY_LOGE("EventListeners create failed %d \n", ret);
384     }
385     return &g_hrilOps;
386 }
387