/* * 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_full.h" #include "dev_attribute_serialize.h" #include "devmgr_service_clnt.h" #include "hdf_base.h" #include "hdf_device_info.h" #include "hdf_device_node.h" #include "hdf_log.h" #include "osal_message.h" #include "power_state_token.h" #define HDF_LOG_TAG devhost_service_full static int32_t DevHostServiceFullDispatchMessage(struct HdfMessageTask *task, struct HdfMessage *msg) { struct DevHostServiceFull *hostService = HDF_SLIST_CONTAINER_OF(struct HdfMessageTask, task, struct DevHostServiceFull, task); int status = HDF_SUCCESS; switch (msg->messageId) { case DEVHOST_MESSAGE_ADD_DEVICE: { struct HdfDeviceInfo *attribute = (struct HdfDeviceInfo *)msg->data[0]; status = DevHostServiceAddDevice(&hostService->super.super, attribute); if (status != HDF_SUCCESS) { HDF_LOGE("DevHostServiceAddDevice failed and return %{public}d", status); } break; } case DEVHOST_MESSAGE_DEL_DEVICE: { devid_t devid = (devid_t)((uintptr_t)msg->data[0]); status = DevHostServiceDelDevice(&hostService->super.super, devid); if (status != HDF_SUCCESS) { HDF_LOGE("DevHostServiceDelDevice failed and return %{public}d", status); } break; } default: { HDF_LOGE("DevHostServiceFullDispatchMessage unknown message %{public}d", msg->messageId); break; } } return status; } static int DevHostServiceFullOpsDevice(struct IDevHostService *devHostService, uintptr_t parm, int cmdCode) { if (devHostService == NULL) { HDF_LOGE("input is null"); return HDF_FAILURE; } struct DevHostServiceFull *inst = (struct DevHostServiceFull *)devHostService; struct HdfMessageTask *task = &inst->task; struct HdfMessage *message = HdfMessageObtain(0); if (message == NULL) { HDF_LOGE("HdfMessageObtain(0) return null"); return HDF_ERR_MALLOC_FAIL; } message->messageId = cmdCode; message->data[0] = (void *)parm; return task->SendMessage(task, message, true); } static int DevHostServiceFullAddDevice(struct IDevHostService *devHostService, const struct HdfDeviceInfo *attribute) { return DevHostServiceFullOpsDevice(devHostService, (uintptr_t)attribute, DEVHOST_MESSAGE_ADD_DEVICE); } static int DevHostServiceFullDelDevice(struct IDevHostService *devHostService, devid_t devid) { return DevHostServiceFullOpsDevice(devHostService, (uintptr_t)devid, DEVHOST_MESSAGE_DEL_DEVICE); } static int DevHostServiceFullDispatchPowerState(struct HdfDevice *device, uint32_t state) { struct HdfDeviceNode *deviceNode = NULL; int ret = HDF_SUCCESS; int result = HDF_SUCCESS; if (IsPowerWakeState(state)) { DLIST_FOR_EACH_ENTRY(deviceNode, &device->devNodes, struct HdfDeviceNode, entry) { if (deviceNode->powerToken != NULL) { ret = PowerStateChange(deviceNode->powerToken, state); if (ret != HDF_SUCCESS) { HDF_LOGE("device %{public}s failed to resume(%{public}d) %{public}d", deviceNode->driver->entry->moduleName, state, ret); result = HDF_FAILURE; } } } } else { DLIST_FOR_EACH_ENTRY_REVERSE(deviceNode, &device->devNodes, struct HdfDeviceNode, entry) { if (deviceNode->powerToken != NULL) { ret = PowerStateChange(deviceNode->powerToken, state); if (ret != HDF_SUCCESS) { HDF_LOGE("device %{public}s failed to suspend(%{public}d) %{public}d", deviceNode->driver->entry->moduleName, state, ret); result = HDF_FAILURE; } } } } return result; } static uint32_t SysEventToPowerState(uint32_t sysEvent) { switch (sysEvent) { case KEVENT_POWER_SUSPEND: return POWER_STATE_SUSPEND; case KEVENT_POWER_DISPLAY_OFF: return POWER_STATE_DOZE_SUSPEND; case KEVENT_POWER_RESUME: return POWER_STATE_RESUME; case KEVENT_POWER_DISPLAY_ON: return POWER_STATE_DOZE_RESUME; default: return POWER_STATE_MAX; } } static int OnSysEventReceived( struct HdfSysEventNotifyNode *self, uint64_t eventClass, uint32_t event, const char *content) { (void)(content); if (self == NULL) { return HDF_ERR_INVALID_PARAM; } struct DevHostService *hostService = CONTAINER_OF(self, struct DevHostService, sysEventNotifyNode); HDF_LOGI("host receive eventClass=%{public}llu, event=%{public}u", (unsigned long long)eventClass, event); return hostService->super.PmNotify(&hostService->super, SysEventToPowerState(event)); } static int DevHostServiceFullStartService(struct IDevHostService *service) { struct DevHostService *hostService = (struct DevHostService *)service; if (hostService == NULL) { HDF_LOGE("Start device service failed, hostService is null"); return HDF_FAILURE; } int ret = DevmgrServiceClntAttachDeviceHost(hostService->hostId, service); if (ret != HDF_SUCCESS) { HDF_LOGE("failed to start host service, attach host error %{public}d", ret); return ret; } hostService->sysEventNotifyNode.callback = OnSysEventReceived; ret = HdfSysEventNotifyRegister(&hostService->sysEventNotifyNode, HDF_SYSEVENT_CLASS_POWER); if (ret != HDF_SUCCESS) { HDF_LOGW("failed to register power event listener"); } else { HDF_LOGD("host register power event listener success"); } return HDF_SUCCESS; } int DevHostServiceFullPmNotify(struct IDevHostService *service, uint32_t state) { struct DevHostService *hostService = (struct DevHostService *)service; int result = HDF_SUCCESS; if (hostService == NULL || !IsValidPowerState(state)) { return HDF_ERR_INVALID_PARAM; } struct HdfDevice *device = NULL; if (IsPowerWakeState(state)) { DLIST_FOR_EACH_ENTRY_REVERSE(device, &hostService->devices, struct HdfDevice, node) { if (DevHostServiceFullDispatchPowerState(device, state) != HDF_SUCCESS) { result = HDF_FAILURE; } } } else { DLIST_FOR_EACH_ENTRY(device, &hostService->devices, struct HdfDevice, node) { if (DevHostServiceFullDispatchPowerState(device, state)) { result = HDF_FAILURE; } } } return result; } void DevHostServiceFullConstruct(struct DevHostServiceFull *inst) { struct IDevHostService *hostServiceIf = &inst->super.super; static struct IHdfMessageHandler handler = { .Dispatch = DevHostServiceFullDispatchMessage }; DevHostServiceConstruct(&inst->super); hostServiceIf->AddDevice = DevHostServiceFullAddDevice; hostServiceIf->DelDevice = DevHostServiceFullDelDevice; hostServiceIf->StartService = DevHostServiceFullStartService; hostServiceIf->PmNotify = DevHostServiceFullPmNotify; HdfMessageLooperConstruct(&inst->looper); HdfMessageTaskConstruct(&inst->task, &inst->looper, &handler); } void DevHostServiceFullDestruct(struct DevHostServiceFull *inst) { if (inst != NULL) { DevHostServiceDestruct(&inst->super); if (inst->looper.Stop != NULL) { inst->looper.Stop(&inst->looper); } } }