1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <hdf_device_object.h>
17 #include <hdf_dlist.h>
18 #include <hdf_log.h>
19 #include <hdf_remote_service.h>
20 #include <hdi_smq.h>
21 #include <thread>
22 #include "sample_hdi.h"
23
24 #define HDF_LOG_TAG sample_driver
25 using OHOS::HDI::Base::SharedMemQueue;
26 using OHOS::HDI::Base::SharedMemQueueMeta;
27 using OHOS::HDI::Base::SmqType;
28
29 constexpr int SMQ_TRANS_ELEMENT_MAX = 5;
30 constexpr int SMQ_TRANS_WAIT_TIME = 100;
31
32 struct SampleDevice {
33 struct DListHead listNode;
34 struct HdfDeviceObject *devobj;
35 };
36
37 static struct DListHead g_sampleDeviceList = { nullptr };
38
SampleServicePing(struct HdfDeviceObject * device,const char * info,char ** infoOut)39 static int32_t SampleServicePing(struct HdfDeviceObject *device, const char *info, char **infoOut)
40 {
41 (void)device;
42 HDF_LOGI("Sample:info is %{public}s", info);
43 *infoOut = strdup(info);
44 return 0;
45 }
46
SampleServiceSum(struct HdfDeviceObject * device,int32_t x0,int32_t x1,int32_t * result)47 static int32_t SampleServiceSum(struct HdfDeviceObject *device, int32_t x0, int32_t x1, int32_t *result)
48 {
49 (void)device;
50 *result = x0 + x1;
51 return 0;
52 }
53
SampleServiceCallback(struct HdfDeviceObject * device,struct HdfRemoteService * callback,int32_t code)54 static int32_t SampleServiceCallback(struct HdfDeviceObject *device, struct HdfRemoteService *callback, int32_t code)
55 {
56 (void)device;
57 struct HdfSBuf *dataSbuf = HdfSbufTypedObtain(SBUF_IPC);
58 HdfSbufWriteInt32(dataSbuf, code);
59 int ret = callback->dispatcher->Dispatch(callback, 0, dataSbuf, nullptr);
60 if (ret != HDF_SUCCESS) {
61 HDF_LOGE("failed to do callback, ret = %{public}d", ret);
62 }
63 HdfSbufRecycle(dataSbuf);
64 return ret;
65 }
66
SampleServiceRegisterDevice(struct HdfDeviceObject * device,const char * servName)67 static int32_t SampleServiceRegisterDevice(struct HdfDeviceObject *device, const char *servName)
68 {
69 struct HdfDeviceObject *dev = HdfDeviceObjectAlloc(device, "libsample_driver.z.so");
70 if (dev == nullptr) {
71 HDF_LOGE("failed to alloc device object");
72 return HDF_DEV_ERR_NO_DEVICE;
73 }
74
75 if (HdfDeviceObjectRegister(dev) != HDF_SUCCESS) {
76 HDF_LOGE("failed to register device");
77 HdfDeviceObjectRelease(dev);
78 return HDF_DEV_ERR_NO_DEVICE;
79 }
80
81 if (HdfDeviceObjectPublishService(dev, servName, SERVICE_POLICY_CAPACITY, 0) != HDF_SUCCESS) {
82 HDF_LOGE("failed to publish device service %{public}s", servName);
83 HdfDeviceObjectRelease(dev);
84 return HDF_DEV_ERR_NO_DEVICE;
85 }
86
87 HDF_LOGE("publish device service %{public}s success", servName);
88 struct SampleDevice *sampleDev = (struct SampleDevice *)OsalMemAlloc(sizeof(struct SampleDevice));
89 if (sampleDev == nullptr) {
90 HdfDeviceObjectRelease(dev);
91 return HDF_DEV_ERR_NO_MEMORY;
92 }
93
94 sampleDev->devobj = dev;
95 if (g_sampleDeviceList.next == nullptr) {
96 DListHeadInit(&g_sampleDeviceList);
97 }
98 DListInsertTail(&sampleDev->listNode, &g_sampleDeviceList);
99
100 HDF_LOGI("register device %{public}s success", servName);
101 return HDF_SUCCESS;
102 }
103
SampleServiceUnregisterDevice(struct HdfDeviceObject * device,const char * servName)104 static int32_t SampleServiceUnregisterDevice(struct HdfDeviceObject *device, const char *servName)
105 {
106 struct SampleDevice *sampleDev = nullptr;
107 struct SampleDevice *sampleDevTmp = nullptr;
108 HDF_LOGI("remove device %{public}s in", servName);
109 DLIST_FOR_EACH_ENTRY_SAFE(sampleDev, sampleDevTmp, &g_sampleDeviceList, struct SampleDevice, listNode)
110 {
111 if (sampleDev->devobj == nullptr || HdfDeviceGetServiceName(sampleDev->devobj) == nullptr) {
112 DListRemove(&sampleDev->listNode);
113 OsalMemFree(sampleDev);
114 continue;
115 }
116
117 if (strcmp(HdfDeviceGetServiceName(sampleDev->devobj), servName) == 0) {
118 HdfDeviceObjectRelease(sampleDev->devobj);
119 DListRemove(&sampleDev->listNode);
120 OsalMemFree(sampleDev);
121 HDF_LOGI("remove device %{public}s success", servName);
122 }
123 }
124
125 return HDF_SUCCESS;
126 }
127
SampleServiceUpdateDevice(struct HdfDeviceObject * device,const char * servInfo)128 static int32_t SampleServiceUpdateDevice(struct HdfDeviceObject *device, const char *servInfo)
129 {
130 if (HdfDeviceObjectSetServInfo(device, servInfo) != HDF_SUCCESS) {
131 HDF_LOGE("failed to set service info");
132 return HDF_FAILURE;
133 }
134 return HdfDeviceObjectUpdate(device);
135 }
136
SampleServiceTansSmq(struct HdfDeviceObject * device,SharedMemQueueMeta<SampleSmqElement> * smqMeta,uint32_t element)137 static int32_t SampleServiceTansSmq(
138 struct HdfDeviceObject *device, SharedMemQueueMeta<SampleSmqElement> *smqMeta, uint32_t element)
139 {
140 HDF_LOGI("SampleServiceTansSmq in, element=%{public}u", element);
141 if (element > SMQ_TRANS_ELEMENT_MAX) {
142 return HDF_ERR_INVALID_PARAM;
143 }
144 static std::shared_ptr<SharedMemQueue<SampleSmqElement>> smq = nullptr;
145 smq = std::make_shared<SharedMemQueue<SampleSmqElement>>(*smqMeta);
146 if (!smq->IsGood()) {
147 HDF_LOGE("failed to create fmq from meta");
148 return HDF_FAILURE;
149 }
150 static size_t elem = static_cast<size_t>(element);
151 std::thread t([&]() {
152 HDF_LOGI("SampleServiceTansSmq:smq read thread start, elem=%{public}zu", elem);
153 std::shared_ptr<SharedMemQueue<SampleSmqElement>> smqLocal = smq;
154 size_t elemLocal = elem;
155 smq = nullptr;
156
157 while (true) {
158 SampleSmqElement t[SMQ_TRANS_ELEMENT_MAX] = {};
159 int ret;
160 if (smqLocal->GetMeta()->GetType() == SmqType::SYNCED_SMQ) {
161 ret = smqLocal->Read(&t[0], elemLocal, OHOS::MillisecToNanosec(SMQ_TRANS_WAIT_TIME));
162 } else {
163 ret = smqLocal->ReadNonBlocking(&t[0], elemLocal);
164 }
165 if (ret != HDF_SUCCESS) {
166 HDF_LOGE("failed to read message from smq, %{public}d", ret);
167 break;
168 }
169 for (size_t i = 0; i < elemLocal; i++) {
170 HDF_LOGI(
171 "read message from smq, info[%{public}zu]:%{public}d, %{public}llu",
172 i, t[i].data32, (unsigned long long)t[i].data64);
173 }
174 }
175 });
176 t.detach();
177
178 return HDF_SUCCESS;
179 }
180
181 static const struct SampleHdi g_sampleHdiImpl = {
182 .ping = SampleServicePing,
183 .sum = SampleServiceSum,
184 .callback = SampleServiceCallback,
185 .registerDevice = SampleServiceRegisterDevice,
186 .unregisterDevice = SampleServiceUnregisterDevice,
187 .updateService = SampleServiceUpdateDevice,
188 .tansSmq = SampleServiceTansSmq,
189 };
190
SampleHdiImplInstance(void)191 const struct SampleHdi *SampleHdiImplInstance(void)
192 {
193 return &g_sampleHdiImpl;
194 }