• 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 <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 }