/* * 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 #include #include #include #include #include #include "sample_hdi.h" #define HDF_LOG_TAG sample_driver using OHOS::HDI::Base::SharedMemQueue; using OHOS::HDI::Base::SharedMemQueueMeta; using OHOS::HDI::Base::SmqType; constexpr int SMQ_TRANS_ELEMENT_MAX = 5; constexpr int SMQ_TRANS_WAIT_TIME = 100; struct SampleDevice { struct DListHead listNode; struct HdfDeviceObject *devobj; }; static struct DListHead g_sampleDeviceList = { nullptr }; static int32_t SampleServicePing(struct HdfDeviceObject *device, const char *info, char **infoOut) { (void)device; HDF_LOGI("Sample:info is %{public}s", info); *infoOut = strdup(info); return 0; } static int32_t SampleServiceSum(struct HdfDeviceObject *device, int32_t x0, int32_t x1, int32_t *result) { (void)device; *result = x0 + x1; return 0; } static int32_t SampleServiceCallback(struct HdfDeviceObject *device, struct HdfRemoteService *callback, int32_t code) { (void)device; struct HdfSBuf *dataSbuf = HdfSbufTypedObtain(SBUF_IPC); HdfSbufWriteInt32(dataSbuf, code); int ret = callback->dispatcher->Dispatch(callback, 0, dataSbuf, nullptr); if (ret != HDF_SUCCESS) { HDF_LOGE("failed to do callback, ret = %{public}d", ret); } HdfSbufRecycle(dataSbuf); return ret; } static int32_t SampleServiceRegisterDevice(struct HdfDeviceObject *device, const char *servName) { struct HdfDeviceObject *dev = HdfDeviceObjectAlloc(device, "libsample_driver.z.so"); if (dev == nullptr) { HDF_LOGE("failed to alloc device object"); return HDF_DEV_ERR_NO_DEVICE; } if (HdfDeviceObjectRegister(dev) != HDF_SUCCESS) { HDF_LOGE("failed to register device"); HdfDeviceObjectRelease(dev); return HDF_DEV_ERR_NO_DEVICE; } if (HdfDeviceObjectPublishService(dev, servName, SERVICE_POLICY_CAPACITY, 0) != HDF_SUCCESS) { HDF_LOGE("failed to publish device service %{public}s", servName); HdfDeviceObjectRelease(dev); return HDF_DEV_ERR_NO_DEVICE; } HDF_LOGE("publish device service %{public}s success", servName); struct SampleDevice *sampleDev = (struct SampleDevice *)OsalMemAlloc(sizeof(struct SampleDevice)); if (sampleDev == nullptr) { HdfDeviceObjectRelease(dev); return HDF_DEV_ERR_NO_MEMORY; } sampleDev->devobj = dev; if (g_sampleDeviceList.next == nullptr) { DListHeadInit(&g_sampleDeviceList); } DListInsertTail(&sampleDev->listNode, &g_sampleDeviceList); HDF_LOGI("register device %{public}s success", servName); return HDF_SUCCESS; } static int32_t SampleServiceUnregisterDevice(struct HdfDeviceObject *device, const char *servName) { struct SampleDevice *sampleDev = nullptr; struct SampleDevice *sampleDevTmp = nullptr; HDF_LOGI("remove device %{public}s in", servName); DLIST_FOR_EACH_ENTRY_SAFE(sampleDev, sampleDevTmp, &g_sampleDeviceList, struct SampleDevice, listNode) { if (sampleDev->devobj == nullptr || HdfDeviceGetServiceName(sampleDev->devobj) == nullptr) { DListRemove(&sampleDev->listNode); OsalMemFree(sampleDev); continue; } if (strcmp(HdfDeviceGetServiceName(sampleDev->devobj), servName) == 0) { HdfDeviceObjectRelease(sampleDev->devobj); DListRemove(&sampleDev->listNode); OsalMemFree(sampleDev); HDF_LOGI("remove device %{public}s success", servName); } } return HDF_SUCCESS; } static int32_t SampleServiceUpdateDevice(struct HdfDeviceObject *device, const char *servInfo) { if (HdfDeviceObjectSetServInfo(device, servInfo) != HDF_SUCCESS) { HDF_LOGE("failed to set service info"); return HDF_FAILURE; } return HdfDeviceObjectUpdate(device); } static int32_t SampleServiceTansSmq( struct HdfDeviceObject *device, SharedMemQueueMeta *smqMeta, uint32_t element) { HDF_LOGI("SampleServiceTansSmq in, element=%{public}u", element); if (element > SMQ_TRANS_ELEMENT_MAX) { return HDF_ERR_INVALID_PARAM; } static std::shared_ptr> smq = nullptr; smq = std::make_shared>(*smqMeta); if (!smq->IsGood()) { HDF_LOGE("failed to create fmq from meta"); return HDF_FAILURE; } static size_t elem = static_cast(element); std::thread t([&]() { HDF_LOGI("SampleServiceTansSmq:smq read thread start, elem=%{public}zu", elem); std::shared_ptr> smqLocal = smq; size_t elemLocal = elem; smq = nullptr; while (true) { SampleSmqElement t[SMQ_TRANS_ELEMENT_MAX] = {}; int ret; if (smqLocal->GetMeta()->GetType() == SmqType::SYNCED_SMQ) { ret = smqLocal->Read(&t[0], elemLocal, OHOS::MillisecToNanosec(SMQ_TRANS_WAIT_TIME)); } else { ret = smqLocal->ReadNonBlocking(&t[0], elemLocal); } if (ret != HDF_SUCCESS) { HDF_LOGE("failed to read message from smq, %{public}d", ret); break; } for (size_t i = 0; i < elemLocal; i++) { HDF_LOGI( "read message from smq, info[%{public}zu]:%{public}d, %{public}llu", i, t[i].data32, (unsigned long long)t[i].data64); } } }); t.detach(); return HDF_SUCCESS; } static const struct SampleHdi g_sampleHdiImpl = { .ping = SampleServicePing, .sum = SampleServiceSum, .callback = SampleServiceCallback, .registerDevice = SampleServiceRegisterDevice, .unregisterDevice = SampleServiceUnregisterDevice, .updateService = SampleServiceUpdateDevice, .tansSmq = SampleServiceTansSmq, }; const struct SampleHdi *SampleHdiImplInstance(void) { return &g_sampleHdiImpl; }