• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }