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 <base/hdi_smq.h>
17 #include <devhost_service_full.h>
18 #include <hdf_device_object.h>
19 #include <hdf_dlist.h>
20 #include <hdf_log.h>
21 #include <hdf_power_state.h>
22 #include <hdf_remote_service.h>
23 #include <thread>
24 #include "sample_hdi.h"
25
26 #define HDF_LOG_TAG sample_driver
27 using OHOS::HDI::Base::SharedMemQueue;
28 using OHOS::HDI::Base::SharedMemQueueMeta;
29 using OHOS::HDI::Base::SmqType;
30
31 struct SampleDevice {
32 struct DListHead listNode;
33 struct HdfDeviceObject *devobj;
34 };
35
36 static struct DListHead g_sampleDeviceList = { nullptr };
37
SampleServicePing(struct HdfDeviceObject * device,const char * info,char ** infoOut)38 static int32_t SampleServicePing(struct HdfDeviceObject *device, const char *info, char **infoOut)
39 {
40 (void)device;
41 HDF_LOGI("Sample:info is %{public}s", info);
42 *infoOut = strdup(info);
43 return 0;
44 }
45
SampleServiceSum(struct HdfDeviceObject * device,int32_t x0,int32_t x1,int32_t * result)46 static int32_t SampleServiceSum(struct HdfDeviceObject *device, int32_t x0, int32_t x1, int32_t *result)
47 {
48 (void)device;
49 *result = x0 + x1;
50 return 0;
51 }
52
SampleServiceCallback(struct HdfDeviceObject * device,struct HdfRemoteService * callback,int32_t code)53 static int32_t SampleServiceCallback(struct HdfDeviceObject *device, struct HdfRemoteService *callback, int32_t code)
54 {
55 (void)device;
56 struct HdfSBuf *dataSbuf = HdfSbufTypedObtain(SBUF_IPC);
57 HdfSbufWriteInt32(dataSbuf, code);
58 int ret = callback->dispatcher->Dispatch(callback, 0, dataSbuf, nullptr);
59 if (ret != HDF_SUCCESS) {
60 HDF_LOGE("failed to do callback, ret = %{public}d", ret);
61 }
62 HdfSbufRecycle(dataSbuf);
63 return ret;
64 }
65
SampleServiceRegisterDevice(struct HdfDeviceObject * device,const char * servName)66 static int32_t SampleServiceRegisterDevice(struct HdfDeviceObject *device, const char *servName)
67 {
68 struct HdfDeviceObject *dev = HdfDeviceObjectAlloc(device, "libsample_driver.z.so");
69 if (dev == nullptr) {
70 HDF_LOGE("failed to alloc device object");
71 return HDF_DEV_ERR_NO_DEVICE;
72 }
73
74 if (HdfDeviceObjectRegister(dev) != HDF_SUCCESS) {
75 HDF_LOGE("failed to register device");
76 HdfDeviceObjectRelease(dev);
77 return HDF_DEV_ERR_NO_DEVICE;
78 }
79
80 if (HdfDeviceObjectPublishService(dev, servName, SERVICE_POLICY_CAPACITY, 0) != HDF_SUCCESS) {
81 HDF_LOGE("failed to publish device service %{public}s", servName);
82 HdfDeviceObjectRelease(dev);
83 return HDF_DEV_ERR_NO_DEVICE;
84 }
85
86 HDF_LOGE("publish device service %{public}s success", servName);
87 struct SampleDevice *sampleDev = static_cast<struct SampleDevice *>(OsalMemAlloc(sizeof(*sampleDev)));
88 if (sampleDev == nullptr) {
89 HdfDeviceObjectRelease(dev);
90 return HDF_DEV_ERR_NO_MEMORY;
91 }
92
93 sampleDev->devobj = dev;
94 if (g_sampleDeviceList.next == nullptr) {
95 DListHeadInit(&g_sampleDeviceList);
96 }
97 DListInsertTail(&sampleDev->listNode, &g_sampleDeviceList);
98
99 HDF_LOGI("register device %{public}s success", servName);
100 return HDF_SUCCESS;
101 }
102
SampleServiceUnregisterDevice(struct HdfDeviceObject * device,const char * servName)103 static int32_t SampleServiceUnregisterDevice(struct HdfDeviceObject *device, const char *servName)
104 {
105 struct SampleDevice *sampleDev = nullptr;
106 struct SampleDevice *sampleDevTmp = nullptr;
107 HDF_LOGI("remove device %{public}s in", servName);
108 (void)device;
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 constexpr int SMQ_TRANS_ELEMENT_MAX = 5;
141 constexpr int SMQ_TRANS_WAIT_TIME = 100;
142 HDF_LOGI("SampleServiceTansSmq in, element=%{public}u", element);
143 if (element > SMQ_TRANS_ELEMENT_MAX) {
144 return HDF_ERR_INVALID_PARAM;
145 }
146 (void)device;
147 static std::shared_ptr<SharedMemQueue<SampleSmqElement>> smq = nullptr;
148 smq = std::make_shared<SharedMemQueue<SampleSmqElement>>(*smqMeta);
149 if (!smq->IsGood()) {
150 HDF_LOGE("failed to create fmq from meta");
151 return HDF_FAILURE;
152 }
153 static size_t elem = static_cast<size_t>(element);
154 std::thread t([]() {
155 HDF_LOGI("SampleServiceTansSmq:smq read thread start, elem=%{public}zu", elem);
156 std::shared_ptr<SharedMemQueue<SampleSmqElement>> smqLocal = smq;
157 size_t elemLocal = elem;
158 smq = nullptr;
159
160 while (true) {
161 SampleSmqElement t[SMQ_TRANS_ELEMENT_MAX] = {};
162 int ret;
163 if (smqLocal->GetMeta()->GetType() == SmqType::SYNCED_SMQ) {
164 ret = smqLocal->Read(&t[0], elemLocal, OHOS::MillisecToNanosec(SMQ_TRANS_WAIT_TIME));
165 } else {
166 ret = smqLocal->ReadNonBlocking(&t[0], elemLocal);
167 }
168 if (ret != HDF_SUCCESS) {
169 HDF_LOGE("failed to read message from smq, %{public}d", ret);
170 break;
171 }
172 for (size_t i = 0; i < elemLocal; i++) {
173 HDF_LOGI(
174 "read message from smq, info[%{public}zu]:%{public}d, %{public}llu",
175 i, t[i].data32, static_cast<unsigned long long>(t[i].data64));
176 }
177 }
178 });
179 t.detach();
180
181 return HDF_SUCCESS;
182 }
183
SampleServiceEndHost(const struct HdfDeviceObject * device)184 static int32_t SampleServiceEndHost(const struct HdfDeviceObject *device)
185 {
186 (void)device;
187 struct IDevHostService *instance = DevHostServiceNewInstance(0, nullptr);
188
189 if (instance == nullptr) {
190 HDF_LOGE("%{public}s parameter is null", __func__);
191 return HDF_FAILURE;
192 }
193
194 struct DevHostServiceFull *fullService = reinterpret_cast<struct DevHostServiceFull *>(instance);
195 struct HdfMessageLooper *looper = &fullService->looper;
196 HDF_LOGW("%{public}s: host %{public}d stop", __func__, fullService->super.hostId);
197 if ((looper != nullptr) && (looper->Stop != nullptr)) {
198 looper->Stop(looper);
199 }
200 return HDF_SUCCESS;
201 }
202
InjectPmState(const struct HdfDeviceObject * device)203 static int32_t InjectPmState(const struct HdfDeviceObject *device)
204 {
205 (void)device;
206 struct IDevHostService *instance = DevHostServiceNewInstance(0, nullptr);
207
208 if (instance == nullptr || instance->PmNotify == nullptr) {
209 HDF_LOGE("%{public}s parameter is null", __func__);
210 return HDF_FAILURE;
211 }
212 (void)instance->PmNotify(nullptr, POWER_STATE_RESUME);
213 (void)instance->PmNotify(instance, POWER_STATE_RESUME);
214 (void)instance->PmNotify(instance, POWER_STATE_SUSPEND);
215 (void)instance->PmNotify(instance, POWER_STATE_MAX);
216
217 return HDF_SUCCESS;
218 }
219
220 static const struct SampleHdi g_sampleHdiImpl = {
221 .ping = SampleServicePing,
222 .sum = SampleServiceSum,
223 .callback = SampleServiceCallback,
224 .registerDevice = SampleServiceRegisterDevice,
225 .unregisterDevice = SampleServiceUnregisterDevice,
226 .updateService = SampleServiceUpdateDevice,
227 .tansSmq = SampleServiceTansSmq,
228 .endHost = SampleServiceEndHost,
229 .injectPmState = InjectPmState,
230 };
231
SampleHdiImplInstance(void)232 const struct SampleHdi *SampleHdiImplInstance(void)
233 {
234 return &g_sampleHdiImpl;
235 }