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 "hril_hdf.h"
17 #ifdef UDEV_SUPPORT
18 #include <libudev.h>
19 #endif
20 #include "dlfcn.h"
21 #include "hdf_base.h"
22 #include "hril_enum.h"
23 #include "modem_adapter.h"
24 #include "parameter.h"
25 #include "stdlib.h"
26 #include "telephony_log_c.h"
27 #include "securec.h"
28 
29 #define RIL_VENDOR_LIB_PATH "const.sys.radio.vendorlib.path"
30 #define VIRTUAL_MODEM_SWITCH  "const.booster.virtual_modem_switch"
31 #define VIRTUAL_MODEM_DEFAULT_SWITCH  "false"
32 #define TEL_SIM_SLOT_COUNT "const.telephony.slotCount"
33 #define DEFAULT_SLOT_COUNT "1"
34 #define BASE_HEX 16
35 
36 static void *g_dlHandle = NULL;
37 static struct HRilReport g_reportOps = {
38     OnCallReport,
39     OnDataReport,
40     OnModemReport,
41     OnNetworkReport,
42     OnSimReport,
43     OnSmsReport,
44     OnTimerCallback
45 };
46 
GetVendorLibPath(char *path)47 static int32_t GetVendorLibPath(char *path)
48 {
49     int32_t code = -1;
50     code = GetParameter(RIL_VENDOR_LIB_PATH, "", path, PARAMETER_SIZE);
51     char simSlotCount[PARAMETER_SIZE] = {0};
52     GetParameter(TEL_SIM_SLOT_COUNT, DEFAULT_SLOT_COUNT, simSlotCount, PARAMETER_SIZE);
53     int32_t slotCount = atoi(simSlotCount);
54     char virtualModemSwitch[PARAMETER_SIZE] = {0};
55     GetParameter(VIRTUAL_MODEM_SWITCH, VIRTUAL_MODEM_DEFAULT_SWITCH, virtualModemSwitch, PARAMETER_SIZE);
56     if (slotCount == 0 && strcmp(virtualModemSwitch, "true") == 0) {
57         if (strcpy_s(path, PARAMETER_SIZE, "libril_msgtransfer.z.so") == EOK) {
58             TELEPHONY_LOGI("virtualModemSwitch on set path libril_msgtransfer.z.so");
59             code = 1;
60         }
61     }
62     if (code > 0) {
63         return HDF_SUCCESS;
64     }
65     TELEPHONY_LOGE("Failed to get vendor library path through system properties. err:%{public}d", code);
66     return HDF_FAILURE;
67 }
68 
69 #ifdef UDEV_SUPPORT
GetPresetInformation(const char *vId, const char *pId)70 static UsbDeviceInfo *GetPresetInformation(const char *vId, const char *pId)
71 {
72     if (vId == NULL || pId == NULL) {
73         return NULL;
74     }
75     char *out = NULL;
76     UsbDeviceInfo *uDevInfo = NULL;
77     int32_t idVendor = (int32_t)strtol(vId, &out, BASE_HEX);
78     int32_t idProduct = (int32_t)strtol(pId, &out, BASE_HEX);
79     for (uint32_t i = 0; i < sizeof(g_usbModemVendorInfo) / sizeof(UsbDeviceInfo); i++) {
80         if (g_usbModemVendorInfo[i].idVendor == idVendor && g_usbModemVendorInfo[i].idProduct == idProduct) {
81             TELEPHONY_LOGI("list index:%{public}d", i);
82             uDevInfo = &g_usbModemVendorInfo[i];
83             break;
84         }
85     }
86     return uDevInfo;
87 }
88 #endif
89 
GetUsbDeviceInfo(void)90 static UsbDeviceInfo *GetUsbDeviceInfo(void)
91 {
92     UsbDeviceInfo *uDevInfo = NULL;
93 #ifdef UDEV_SUPPORT
94     struct udev *udev;
95     struct udev_enumerate *enumerate;
96     struct udev_list_entry *devices, *devListEntry;
97     struct udev_device *dev;
98 
99     udev = udev_new();
100     if (udev == NULL) {
101         TELEPHONY_LOGE("Can't create udev");
102         return uDevInfo;
103     }
104     enumerate = udev_enumerate_new(udev);
105     if (enumerate == NULL) {
106         TELEPHONY_LOGE("Can't create enumerate");
107         udev_unref(udev);
108         return uDevInfo;
109     }
110     udev_enumerate_add_match_subsystem(enumerate, "tty");
111     udev_enumerate_scan_devices(enumerate);
112     devices = udev_enumerate_get_list_entry(enumerate);
113     udev_list_entry_foreach(devListEntry, devices) {
114         const char *path = udev_list_entry_get_name(devListEntry);
115         if (path == NULL) {
116             continue;
117         }
118         dev = udev_device_new_from_syspath(udev, path);
119         if (dev == NULL) {
120             continue;
121         }
122         dev = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device");
123         if (!dev) {
124             TELEPHONY_LOGE("Unable to find parent usb device.");
125             return uDevInfo;
126         }
127         const char *cIdVendor = udev_device_get_sysattr_value(dev, "idVendor");
128         const char *cIdProduct = udev_device_get_sysattr_value(dev, "idProduct");
129         uDevInfo = GetPresetInformation(cIdVendor, cIdProduct);
130         udev_device_unref(dev);
131         if (uDevInfo != NULL) {
132             break;
133         }
134     }
135     udev_enumerate_unref(enumerate);
136     udev_unref(udev);
137 #endif
138     return uDevInfo;
139 }
140 
LoadVendor(void)141 static void LoadVendor(void)
142 {
143     const char *rilLibPath = NULL;
144     char vendorLibPath[PARAMETER_SIZE] = {0};
145     // Pointer to ril init function in vendor ril
146     const HRilOps *(*rilInitOps)(const struct HRilReport *) = NULL;
147     // functions returned by ril init function in vendor ril
148     const HRilOps *ops = NULL;
149 
150     UsbDeviceInfo *uDevInfo = GetUsbDeviceInfo();
151     if (GetVendorLibPath(vendorLibPath) == HDF_SUCCESS) {
152         rilLibPath = vendorLibPath;
153     } else if (uDevInfo != NULL) {
154         rilLibPath = uDevInfo->libPath;
155     } else {
156         TELEPHONY_LOGE("no vendor lib");
157         return;
158     }
159     if (rilLibPath == NULL || rilLibPath[0] == '\0') {
160         TELEPHONY_LOGE("dynamic library path is empty");
161         return;
162     }
163 
164     TELEPHONY_LOGI("RilInit LoadVendor start with rilLibPath:%{public}s", rilLibPath);
165     g_dlHandle = dlopen(rilLibPath, RTLD_NOW);
166     if (g_dlHandle == NULL) {
167         TELEPHONY_LOGE("dlopen %{public}s is fail. %{public}s", rilLibPath, dlerror());
168         return;
169     }
170     rilInitOps = (const HRilOps *(*)(const struct HRilReport *))dlsym(g_dlHandle, "RilInitOps");
171     if (rilInitOps == NULL) {
172         dlclose(g_dlHandle);
173         TELEPHONY_LOGE("RilInit not defined or exported");
174         return;
175     }
176     HRilInit();
177     ops = rilInitOps(&g_reportOps);
178     HRilRegOps(ops);
179     TELEPHONY_LOGI("HRilRegOps completed");
180 }
181 
InitRilAdapter(void)182 void InitRilAdapter(void)
183 {
184     LoadVendor();
185 }
186 
ReleaseRilAdapter(void)187 void ReleaseRilAdapter(void)
188 {
189     if (g_dlHandle == NULL) {
190         TELEPHONY_LOGE("g_dlHandle has been null");
191         return;
192     }
193     dlclose(g_dlHandle);
194 }
195