111fccf17Sopenharmony_ci/*
211fccf17Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd.
311fccf17Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
411fccf17Sopenharmony_ci * you may not use this file except in compliance with the License.
511fccf17Sopenharmony_ci * You may obtain a copy of the License at
611fccf17Sopenharmony_ci *
711fccf17Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
811fccf17Sopenharmony_ci *
911fccf17Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1011fccf17Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1111fccf17Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1211fccf17Sopenharmony_ci * See the License for the specific language governing permissions and
1311fccf17Sopenharmony_ci * limitations under the License.
1411fccf17Sopenharmony_ci */
1511fccf17Sopenharmony_ci
1611fccf17Sopenharmony_ci#include "hril_hdf.h"
1711fccf17Sopenharmony_ci#ifdef UDEV_SUPPORT
1811fccf17Sopenharmony_ci#include <libudev.h>
1911fccf17Sopenharmony_ci#endif
2011fccf17Sopenharmony_ci#include "dlfcn.h"
2111fccf17Sopenharmony_ci#include "hdf_base.h"
2211fccf17Sopenharmony_ci#include "hril_enum.h"
2311fccf17Sopenharmony_ci#include "modem_adapter.h"
2411fccf17Sopenharmony_ci#include "parameter.h"
2511fccf17Sopenharmony_ci#include "stdlib.h"
2611fccf17Sopenharmony_ci#include "telephony_log_c.h"
2711fccf17Sopenharmony_ci#include "securec.h"
2811fccf17Sopenharmony_ci
2911fccf17Sopenharmony_ci#define RIL_VENDOR_LIB_PATH "const.sys.radio.vendorlib.path"
3011fccf17Sopenharmony_ci#define VIRTUAL_MODEM_SWITCH  "const.booster.virtual_modem_switch"
3111fccf17Sopenharmony_ci#define VIRTUAL_MODEM_DEFAULT_SWITCH  "false"
3211fccf17Sopenharmony_ci#define TEL_SIM_SLOT_COUNT "const.telephony.slotCount"
3311fccf17Sopenharmony_ci#define DEFAULT_SLOT_COUNT "1"
3411fccf17Sopenharmony_ci#define BASE_HEX 16
3511fccf17Sopenharmony_ci
3611fccf17Sopenharmony_cistatic void *g_dlHandle = NULL;
3711fccf17Sopenharmony_cistatic struct HRilReport g_reportOps = {
3811fccf17Sopenharmony_ci    OnCallReport,
3911fccf17Sopenharmony_ci    OnDataReport,
4011fccf17Sopenharmony_ci    OnModemReport,
4111fccf17Sopenharmony_ci    OnNetworkReport,
4211fccf17Sopenharmony_ci    OnSimReport,
4311fccf17Sopenharmony_ci    OnSmsReport,
4411fccf17Sopenharmony_ci    OnTimerCallback
4511fccf17Sopenharmony_ci};
4611fccf17Sopenharmony_ci
4711fccf17Sopenharmony_cistatic int32_t GetVendorLibPath(char *path)
4811fccf17Sopenharmony_ci{
4911fccf17Sopenharmony_ci    int32_t code = -1;
5011fccf17Sopenharmony_ci    code = GetParameter(RIL_VENDOR_LIB_PATH, "", path, PARAMETER_SIZE);
5111fccf17Sopenharmony_ci    char simSlotCount[PARAMETER_SIZE] = {0};
5211fccf17Sopenharmony_ci    GetParameter(TEL_SIM_SLOT_COUNT, DEFAULT_SLOT_COUNT, simSlotCount, PARAMETER_SIZE);
5311fccf17Sopenharmony_ci    int32_t slotCount = atoi(simSlotCount);
5411fccf17Sopenharmony_ci    char virtualModemSwitch[PARAMETER_SIZE] = {0};
5511fccf17Sopenharmony_ci    GetParameter(VIRTUAL_MODEM_SWITCH, VIRTUAL_MODEM_DEFAULT_SWITCH, virtualModemSwitch, PARAMETER_SIZE);
5611fccf17Sopenharmony_ci    if (slotCount == 0 && strcmp(virtualModemSwitch, "true") == 0) {
5711fccf17Sopenharmony_ci        if (strcpy_s(path, PARAMETER_SIZE, "libril_msgtransfer.z.so") == EOK) {
5811fccf17Sopenharmony_ci            TELEPHONY_LOGI("virtualModemSwitch on set path libril_msgtransfer.z.so");
5911fccf17Sopenharmony_ci            code = 1;
6011fccf17Sopenharmony_ci        }
6111fccf17Sopenharmony_ci    }
6211fccf17Sopenharmony_ci    if (code > 0) {
6311fccf17Sopenharmony_ci        return HDF_SUCCESS;
6411fccf17Sopenharmony_ci    }
6511fccf17Sopenharmony_ci    TELEPHONY_LOGE("Failed to get vendor library path through system properties. err:%{public}d", code);
6611fccf17Sopenharmony_ci    return HDF_FAILURE;
6711fccf17Sopenharmony_ci}
6811fccf17Sopenharmony_ci
6911fccf17Sopenharmony_ci#ifdef UDEV_SUPPORT
7011fccf17Sopenharmony_cistatic UsbDeviceInfo *GetPresetInformation(const char *vId, const char *pId)
7111fccf17Sopenharmony_ci{
7211fccf17Sopenharmony_ci    if (vId == NULL || pId == NULL) {
7311fccf17Sopenharmony_ci        return NULL;
7411fccf17Sopenharmony_ci    }
7511fccf17Sopenharmony_ci    char *out = NULL;
7611fccf17Sopenharmony_ci    UsbDeviceInfo *uDevInfo = NULL;
7711fccf17Sopenharmony_ci    int32_t idVendor = (int32_t)strtol(vId, &out, BASE_HEX);
7811fccf17Sopenharmony_ci    int32_t idProduct = (int32_t)strtol(pId, &out, BASE_HEX);
7911fccf17Sopenharmony_ci    for (uint32_t i = 0; i < sizeof(g_usbModemVendorInfo) / sizeof(UsbDeviceInfo); i++) {
8011fccf17Sopenharmony_ci        if (g_usbModemVendorInfo[i].idVendor == idVendor && g_usbModemVendorInfo[i].idProduct == idProduct) {
8111fccf17Sopenharmony_ci            TELEPHONY_LOGI("list index:%{public}d", i);
8211fccf17Sopenharmony_ci            uDevInfo = &g_usbModemVendorInfo[i];
8311fccf17Sopenharmony_ci            break;
8411fccf17Sopenharmony_ci        }
8511fccf17Sopenharmony_ci    }
8611fccf17Sopenharmony_ci    return uDevInfo;
8711fccf17Sopenharmony_ci}
8811fccf17Sopenharmony_ci#endif
8911fccf17Sopenharmony_ci
9011fccf17Sopenharmony_cistatic UsbDeviceInfo *GetUsbDeviceInfo(void)
9111fccf17Sopenharmony_ci{
9211fccf17Sopenharmony_ci    UsbDeviceInfo *uDevInfo = NULL;
9311fccf17Sopenharmony_ci#ifdef UDEV_SUPPORT
9411fccf17Sopenharmony_ci    struct udev *udev;
9511fccf17Sopenharmony_ci    struct udev_enumerate *enumerate;
9611fccf17Sopenharmony_ci    struct udev_list_entry *devices, *devListEntry;
9711fccf17Sopenharmony_ci    struct udev_device *dev;
9811fccf17Sopenharmony_ci
9911fccf17Sopenharmony_ci    udev = udev_new();
10011fccf17Sopenharmony_ci    if (udev == NULL) {
10111fccf17Sopenharmony_ci        TELEPHONY_LOGE("Can't create udev");
10211fccf17Sopenharmony_ci        return uDevInfo;
10311fccf17Sopenharmony_ci    }
10411fccf17Sopenharmony_ci    enumerate = udev_enumerate_new(udev);
10511fccf17Sopenharmony_ci    if (enumerate == NULL) {
10611fccf17Sopenharmony_ci        TELEPHONY_LOGE("Can't create enumerate");
10711fccf17Sopenharmony_ci        udev_unref(udev);
10811fccf17Sopenharmony_ci        return uDevInfo;
10911fccf17Sopenharmony_ci    }
11011fccf17Sopenharmony_ci    udev_enumerate_add_match_subsystem(enumerate, "tty");
11111fccf17Sopenharmony_ci    udev_enumerate_scan_devices(enumerate);
11211fccf17Sopenharmony_ci    devices = udev_enumerate_get_list_entry(enumerate);
11311fccf17Sopenharmony_ci    udev_list_entry_foreach(devListEntry, devices) {
11411fccf17Sopenharmony_ci        const char *path = udev_list_entry_get_name(devListEntry);
11511fccf17Sopenharmony_ci        if (path == NULL) {
11611fccf17Sopenharmony_ci            continue;
11711fccf17Sopenharmony_ci        }
11811fccf17Sopenharmony_ci        dev = udev_device_new_from_syspath(udev, path);
11911fccf17Sopenharmony_ci        if (dev == NULL) {
12011fccf17Sopenharmony_ci            continue;
12111fccf17Sopenharmony_ci        }
12211fccf17Sopenharmony_ci        dev = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device");
12311fccf17Sopenharmony_ci        if (!dev) {
12411fccf17Sopenharmony_ci            TELEPHONY_LOGE("Unable to find parent usb device.");
12511fccf17Sopenharmony_ci            return uDevInfo;
12611fccf17Sopenharmony_ci        }
12711fccf17Sopenharmony_ci        const char *cIdVendor = udev_device_get_sysattr_value(dev, "idVendor");
12811fccf17Sopenharmony_ci        const char *cIdProduct = udev_device_get_sysattr_value(dev, "idProduct");
12911fccf17Sopenharmony_ci        uDevInfo = GetPresetInformation(cIdVendor, cIdProduct);
13011fccf17Sopenharmony_ci        udev_device_unref(dev);
13111fccf17Sopenharmony_ci        if (uDevInfo != NULL) {
13211fccf17Sopenharmony_ci            break;
13311fccf17Sopenharmony_ci        }
13411fccf17Sopenharmony_ci    }
13511fccf17Sopenharmony_ci    udev_enumerate_unref(enumerate);
13611fccf17Sopenharmony_ci    udev_unref(udev);
13711fccf17Sopenharmony_ci#endif
13811fccf17Sopenharmony_ci    return uDevInfo;
13911fccf17Sopenharmony_ci}
14011fccf17Sopenharmony_ci
14111fccf17Sopenharmony_cistatic void LoadVendor(void)
14211fccf17Sopenharmony_ci{
14311fccf17Sopenharmony_ci    const char *rilLibPath = NULL;
14411fccf17Sopenharmony_ci    char vendorLibPath[PARAMETER_SIZE] = {0};
14511fccf17Sopenharmony_ci    // Pointer to ril init function in vendor ril
14611fccf17Sopenharmony_ci    const HRilOps *(*rilInitOps)(const struct HRilReport *) = NULL;
14711fccf17Sopenharmony_ci    // functions returned by ril init function in vendor ril
14811fccf17Sopenharmony_ci    const HRilOps *ops = NULL;
14911fccf17Sopenharmony_ci
15011fccf17Sopenharmony_ci    UsbDeviceInfo *uDevInfo = GetUsbDeviceInfo();
15111fccf17Sopenharmony_ci    if (GetVendorLibPath(vendorLibPath) == HDF_SUCCESS) {
15211fccf17Sopenharmony_ci        rilLibPath = vendorLibPath;
15311fccf17Sopenharmony_ci    } else if (uDevInfo != NULL) {
15411fccf17Sopenharmony_ci        rilLibPath = uDevInfo->libPath;
15511fccf17Sopenharmony_ci    } else {
15611fccf17Sopenharmony_ci        TELEPHONY_LOGE("no vendor lib");
15711fccf17Sopenharmony_ci        return;
15811fccf17Sopenharmony_ci    }
15911fccf17Sopenharmony_ci    if (rilLibPath == NULL || rilLibPath[0] == '\0') {
16011fccf17Sopenharmony_ci        TELEPHONY_LOGE("dynamic library path is empty");
16111fccf17Sopenharmony_ci        return;
16211fccf17Sopenharmony_ci    }
16311fccf17Sopenharmony_ci
16411fccf17Sopenharmony_ci    TELEPHONY_LOGI("RilInit LoadVendor start with rilLibPath:%{public}s", rilLibPath);
16511fccf17Sopenharmony_ci    g_dlHandle = dlopen(rilLibPath, RTLD_NOW);
16611fccf17Sopenharmony_ci    if (g_dlHandle == NULL) {
16711fccf17Sopenharmony_ci        TELEPHONY_LOGE("dlopen %{public}s is fail. %{public}s", rilLibPath, dlerror());
16811fccf17Sopenharmony_ci        return;
16911fccf17Sopenharmony_ci    }
17011fccf17Sopenharmony_ci    rilInitOps = (const HRilOps *(*)(const struct HRilReport *))dlsym(g_dlHandle, "RilInitOps");
17111fccf17Sopenharmony_ci    if (rilInitOps == NULL) {
17211fccf17Sopenharmony_ci        dlclose(g_dlHandle);
17311fccf17Sopenharmony_ci        TELEPHONY_LOGE("RilInit not defined or exported");
17411fccf17Sopenharmony_ci        return;
17511fccf17Sopenharmony_ci    }
17611fccf17Sopenharmony_ci    HRilInit();
17711fccf17Sopenharmony_ci    ops = rilInitOps(&g_reportOps);
17811fccf17Sopenharmony_ci    HRilRegOps(ops);
17911fccf17Sopenharmony_ci    TELEPHONY_LOGI("HRilRegOps completed");
18011fccf17Sopenharmony_ci}
18111fccf17Sopenharmony_ci
18211fccf17Sopenharmony_civoid InitRilAdapter(void)
18311fccf17Sopenharmony_ci{
18411fccf17Sopenharmony_ci    LoadVendor();
18511fccf17Sopenharmony_ci}
18611fccf17Sopenharmony_ci
18711fccf17Sopenharmony_civoid ReleaseRilAdapter(void)
18811fccf17Sopenharmony_ci{
18911fccf17Sopenharmony_ci    if (g_dlHandle == NULL) {
19011fccf17Sopenharmony_ci        TELEPHONY_LOGE("g_dlHandle has been null");
19111fccf17Sopenharmony_ci        return;
19211fccf17Sopenharmony_ci    }
19311fccf17Sopenharmony_ci    dlclose(g_dlHandle);
19411fccf17Sopenharmony_ci}
195