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