cc8caeff创建于 2025年2月17日历史提交
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <string>
#include "wifi_hal.h"
#include "wifi_ioctl.h"
#include <securec.h>
#include <osal_mem.h>
#include <hdf_log.h>

static const std::string POWER_MODE_SLEEP = "sleep";
static const std::string POWER_MODE_THIRD = "third";
static const std::string POWER_MODE_INIT = "init";

static int32_t SendCommandToDriverByInterfaceName(int32_t sock, char *cmd, const char *interfaceName)
{
    struct ifreq ifr;
    int32_t ret = -1;
    WifiPrivCmd privCmd;

    if (cmd == nullptr || interfaceName == nullptr) {
        HDF_LOGE("SendCommandToDriver: cmd is null or interfaceName is null.");
        return HAL_INVALID_ARGS;
    }
    (void)memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr));
    (void)memset_s(&privCmd, sizeof(privCmd), 0, sizeof(privCmd));
#if (defined(LINUX_VERSION_CODE) && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
    privCmd.buf = static_cast<unsigned char *>(OsalMemCalloc(MAX_PRIV_CMD_SIZE));
    if (privCmd.buf == nullptr) {
        HDF_LOGE("%{public}s :OsalMemCalloc fail", __func__);
        return HAL_NONE;
    }
#endif
    do {
        if (memcpy_s(privCmd.buf, MAX_PRIV_CMD_SIZE, cmd, MAX_CMD_LEN) != EOK) {
            HDF_LOGE("memcpy_s privCmd fail");
            break;
        }
        privCmd.size = MAX_PRIV_CMD_SIZE;
        privCmd.len = MAX_CMD_LEN;
        ifr.ifr_data = reinterpret_cast<char *>(&privCmd);
        if (strcpy_s(ifr.ifr_name, IFNAMSIZ, interfaceName) != EOK) {
            HDF_LOGE("strcpy_s ifr fail");
            break;
        }
        ret = ioctl(sock, SIOCDEVPRIVATE + 1, &ifr);
        if (ret < 0) {
            HDF_LOGE("ioctl %{public}s fail, errno = %{public}d: %{public}s", cmd, errno, strerror(errno));
            if (errno == EOPNOTSUPP) {
                ret = HAL_NOT_SUPPORTED;
            } else {
                ret = HAL_NONE;
            }
        }
        (void)memset_s(cmd, MAX_CMD_LEN, 0, MAX_CMD_LEN);
        if (memcpy_s(cmd, MAX_CMD_LEN, privCmd.buf, MAX_CMD_LEN - 1) != EOK) {
            HDF_LOGE("%{public}s :memcpy_s cmd fail", __func__);
            ret = HAL_NONE;
            break;
        }
    } while (0);
#if (defined(LINUX_VERSION_CODE) && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
    OsalMemFree(privCmd.buf);
#endif
    return ret;
}

static int SendCmdIoctl(const char *ifName, char *cmdBuf)
{
    int ret = -1;

    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        HDF_LOGE("%s :socket error", __func__);
        return ret;
    }

    ret = SendCommandToDriverByInterfaceName(sock, cmdBuf, ifName);
    HDF_LOGI("%s : ret: %d", __func__, ret);
    close(sock);
    return ret;
}

WifiError GetPowerMode(const char *ifName, int *mode)
{
    return HAL_SUCCESS;
}

WifiError SetPowerMode(const char *ifName, int mode)
{
    return HAL_SUCCESS;
}

WifiError SetTxPower(const char *ifName, int mode)
{
    return HAL_SUCCESS;
}

WifiError EnablePowerMode(const char *ifName, int mode)
{
    return HAL_SUCCESS;
}

uint32_t WifiGetSupportedFeatureSet(const char *ifName)
{
    uint32_t ret = 0;
    char cmdBuf[MAX_CMD_LEN] = { 0 };
    size_t cmdLen = strlen(CMD_GET_WIFI_PRIV_FEATURE_CAPABILITY);

    if (ifName == nullptr) {
        HDF_LOGE("WifiGetSupportedFeatureSet iface is null.");
        return ret;
    }
    if (memcpy_s(cmdBuf, MAX_CMD_LEN, CMD_GET_WIFI_PRIV_FEATURE_CAPABILITY, cmdLen) != EOK) {
        HDF_LOGE("%{public}s :memcpy_s cmdBuf fail", __FUNCTION__);
        return ret;
    }
    if (SendCmdIoctl(ifName, cmdBuf) == 0) {
        ret = *(reinterpret_cast<uint32_t *>(cmdBuf));
    } else {
        HDF_LOGI("WifiGetSupportedFeatureSet failed");
    }
    return ret;
}

uint32_t GetChipCaps(const char *ifName)
{
    uint32_t ret = 0;
    char cmdBuf[MAX_CMD_LEN] = { 0 };
    size_t cmdLen = strlen(CMD_WIFI_CATEGORY);

    if (ifName == nullptr) {
        HDF_LOGE("HisiGetWifiCategory ifName is null.");
        return ret;
    }
    if (memcpy_s(cmdBuf, MAX_CMD_LEN, CMD_WIFI_CATEGORY, cmdLen) != EOK) {
        HDF_LOGE("%{public}s :memcpy_s cmdBuf fail", __FUNCTION__);
        return ret;
    }
    if (SendCmdIoctl(ifName, cmdBuf) == 0) {
        if (strncmp(cmdBuf, CMD_WIFI_CATEGORY, cmdLen) != 0) {
            ret = *(reinterpret_cast<uint8_t *>(cmdBuf));
        }
    } else {
        HDF_LOGI("GetChipCaps failed");
    }
    return ret;
}