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 36static void *g_dlHandle = NULL; 37static struct HRilReport g_reportOps = { 38 OnCallReport, 39 OnDataReport, 40 OnModemReport, 41 OnNetworkReport, 42 OnSimReport, 43 OnSmsReport, 44 OnTimerCallback 45}; 46 47static 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 70static 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 90static 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 141static 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 182void InitRilAdapter(void) 183{ 184 LoadVendor(); 185} 186 187void 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