* 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 "device_service_stub.h"
#include "devsvc_manager_clnt.h"
#include "hdf_base.h"
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "osal_mem.h"
int DeviceServiceStubDispatch(
struct HdfRemoteService *stub, int code, struct HdfSBuf *data, struct HdfSBuf *reply)
{
struct DeviceServiceStub *service = (struct DeviceServiceStub *)stub;
struct IDeviceIoService *ioService = service->super.deviceObject.service;
int ret = HDF_FAILURE;
if (ioService == NULL) {
return HDF_FAILURE;
}
struct HdfDeviceIoClient client = {
.device = &service->super.deviceObject,
.priv = NULL,
};
if (ioService->Dispatch != NULL) {
ret = ioService->Dispatch(&client, code, data, reply);
}
return ret;
}
static struct HdfRemoteDispatcher g_deviceServiceDispatcher = {
.Dispatch = DeviceServiceStubDispatch
};
int DeviceServiceStubPublishService(struct HdfDeviceNode *service)
{
int status = HDF_FAILURE;
struct DeviceServiceStub *fullService = (struct DeviceServiceStub *)service;
if (service->servName == NULL) {
HDF_LOGE("device %x miss service name", service->devId);
return HDF_ERR_INVALID_OBJECT;
}
if (fullService->remote != NULL) {
HDF_LOGE("%{public}s:service %{public}s already published", __func__, service->servName);
return HDF_ERR_INVALID_OBJECT;
}
if (service->policy != SERVICE_POLICY_PUBLIC && service->policy != SERVICE_POLICY_CAPACITY) {
return HDF_ERR_NOT_SUPPORT;
}
fullService->remote = HdfRemoteServiceObtain((struct HdfObject *)fullService, &g_deviceServiceDispatcher);
if (fullService->remote == NULL) {
return HDF_ERR_MALLOC_FAIL;
}
do {
if (service->interfaceDesc != NULL &&
!HdfRemoteServiceSetInterfaceDesc(fullService->remote, service->interfaceDesc)) {
HDF_LOGE("failed to set device service interface desc");
break;
}
struct DevSvcManagerClnt *serviceManager = DevSvcManagerClntGetInstance();
if (serviceManager == NULL) {
HDF_LOGE("device service stub failed to publish, svcmgr clnt invalid");
status = HDF_DEV_ERR_NO_DEVICE;
break;
}
status = DevSvcManagerClntAddService(service->servName, service->deviceObject.deviceClass,
&fullService->super.deviceObject, service->servInfo);
if (status != HDF_SUCCESS) {
break;
}
service->servStatus = true;
return HDF_SUCCESS;
} while (0);
HdfRemoteServiceRecycle(fullService->remote);
fullService->remote = NULL;
return status;
}
int DeviceServiceStubRemoveService(struct HdfDeviceNode *deviceNode)
{
struct DevSvcManagerClnt *serviceManager = DevSvcManagerClntGetInstance();
if (serviceManager == NULL) {
return HDF_FAILURE;
}
DevSvcManagerClntRemoveService(deviceNode->servName);
struct DeviceServiceStub *instance = (struct DeviceServiceStub *)deviceNode;
HdfRemoteServiceRecycle(instance->remote);
instance->remote = NULL;
return HDF_SUCCESS;
}
void DeviceServiceStubConstruct(struct DeviceServiceStub *inst)
{
HdfDeviceNodeConstruct(&inst->super);
struct IDeviceNode *serviceIf = (struct IDeviceNode *)inst;
if (serviceIf != NULL) {
serviceIf->PublishService = DeviceServiceStubPublishService;
serviceIf->RemoveService = DeviceServiceStubRemoveService;
}
}
struct HdfObject *DeviceServiceStubCreate(void)
{
struct DeviceServiceStub *instance =
(struct DeviceServiceStub *)OsalMemCalloc(sizeof(struct DeviceServiceStub));
if (instance != NULL) {
DeviceServiceStubConstruct(instance);
}
return (struct HdfObject *)instance;
}
void DeviceServiceStubRelease(struct HdfObject *object)
{
struct DeviceServiceStub *instance = (struct DeviceServiceStub *)object;
if (instance != NULL) {
if (instance->remote != NULL) {
HdfRemoteServiceRecycle(instance->remote);
instance->remote = NULL;
}
HdfDeviceNodeDestruct(&instance->super);
OsalMemFree(instance);
}
}
bool HdfDeviceObjectCheckInterfaceDesc(struct HdfDeviceObject *dev, struct HdfSBuf *data)
{
if (dev == NULL || data == NULL) {
return false;
}
struct HdfDeviceNode *devNode = CONTAINER_OF(dev, struct HdfDeviceNode, deviceObject);
struct DeviceServiceStub *instance = (struct DeviceServiceStub *)devNode;
return HdfRemoteServiceCheckInterfaceToken(instance->remote, data);
}