d9cb774e创建于 2022年3月10日历史提交
/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * 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 "devhost_service_proxy.h"
#include "dev_attribute_serialize.h"
#include "devmgr_service_full.h"
#include "hdf_base.h"
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "osal_mem.h"
#include "osal_message.h"

#define HDF_LOG_TAG devhost_service_proxy

static int32_t DevHostServiceProxyOpsDevice(
    struct IDevHostService *inst, const struct HdfDeviceInfo *attribute, int opsCode)
{
    int status = HDF_FAILURE;
    struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
    struct DevHostServiceProxy *hostClnt = (struct DevHostServiceProxy *)inst;
    if (hostClnt->remote == NULL || data == NULL) {
        HDF_LOGE("Adding device failed, hostClnt->remote or data or reply is null");
        goto FINISHED;
    }

    DeviceAttributeSerialize(attribute, data);
    status = hostClnt->remote->dispatcher->Dispatch(hostClnt->remote, DEVHOST_SERVICE_ADD_DEVICE, data, NULL);
FINISHED:
    if (data != NULL) {
        HdfSbufRecycle(data);
    }
    return status;
}

static int32_t DevHostServiceProxyAddDevice(
    struct IDevHostService *inst, const struct HdfDeviceInfo *attribute)
{
    return DevHostServiceProxyOpsDevice(inst, attribute, DEVHOST_SERVICE_ADD_DEVICE);
}

static int32_t DevHostServiceProxyDelDevice(
    struct IDevHostService *inst, devid_t devid)
{
    int status = HDF_FAILURE;
    struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
    struct DevHostServiceProxy *hostClnt = (struct DevHostServiceProxy *)inst;
    if (hostClnt->remote == NULL || data == NULL) {
        HDF_LOGE("Del device failed, hostClnt->remote or data is null");
        goto FINISHED;
    }

    HdfSbufWriteUint32(data, devid);
    status = hostClnt->remote->dispatcher->Dispatch(hostClnt->remote, DEVHOST_SERVICE_DEL_DEVICE, data, NULL);

FINISHED:
    if (data != NULL) {
        HdfSbufRecycle(data);
    }
    return status;
}

void DevHostServiceProxyOnRemoteDied(struct HdfDeathRecipient *recipient, struct HdfRemoteService *service)
{
    if (recipient == NULL || service == NULL) {
        return;
    }

    struct HdfMessageTask *task = DevmgrServiceFullGetMessageTask();
    if (task == NULL) {
        return;
    }
    struct HdfMessage *message = HdfMessageObtain(0);
    if (message == NULL) {
        return;
    }
    struct DevHostServiceProxy *proxy = HDF_SLIST_CONTAINER_OF(
        struct HdfDeathRecipient, recipient, struct DevHostServiceProxy, recipient);
    message->messageId = DEVMGR_MESSAGE_DEVHOST_DIED;
    message->data[0] = (void *)(uintptr_t)proxy->hostId;
    HDF_LOGD("%{public}s: host %{public}u dead, respawn it", __FUNCTION__, proxy->hostId);
    task->SendMessage(task, message, false);
}

void DevHostServiceProxyConstruct(
    struct DevHostServiceProxy *inst, struct HdfRemoteService *remote)
{
    inst->remote = remote;
    inst->super.AddDevice = DevHostServiceProxyAddDevice;
    inst->super.DelDevice = DevHostServiceProxyDelDevice;
    inst->recipient.OnRemoteDied = DevHostServiceProxyOnRemoteDied;
    HdfRemoteServiceAddDeathRecipient(remote, &inst->recipient);
}

struct IDevHostService *DevHostServiceProxyObtain(uint32_t hostId, struct HdfRemoteService *remote)
{
    struct DevHostServiceProxy *instance =
        (struct DevHostServiceProxy *)OsalMemCalloc(sizeof(struct DevHostServiceProxy));
    if (instance != NULL) {
        instance->hostId = hostId;
        DevHostServiceProxyConstruct(instance, remote);
    }
    return (struct IDevHostService *)instance;
}

void DevHostServiceProxyRecycle(struct DevHostServiceProxy *inst)
{
    if (inst != NULL) {
        if (inst->remote != NULL) {
            HdfRemoteServiceRecycle(inst->remote);
            inst->remote = NULL;
        }
        OsalMemFree(inst);
    }
}