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_syscall_adapter.h"
17 #include "hdf_log.h"
18 #include "hdf_sbuf.h"
19 #include "osal_mem.h"
20 #include "devsvc_manager_clnt.h"
21
22 #define HDF_LOG_TAG hdf_syscall_adapter
23
HdfSyscallAdapterDispatch(struct HdfObject * service,int cmdId,struct HdfSBuf * data,struct HdfSBuf * reply)24 int HdfSyscallAdapterDispatch (struct HdfObject *service, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
25 {
26 struct HdfIoService *ioService = (struct HdfIoService*)service;
27 struct HdfSyscallAdapter *adapter = NULL;
28
29 if (ioService == NULL || ioService->dispatcher == NULL) {
30 return HDF_ERR_INVALID_PARAM;
31 }
32
33 adapter = CONTAINER_OF(ioService, struct HdfSyscallAdapter, super);
34
35 if (adapter->client.device == NULL || adapter->client.device->service == NULL ||
36 adapter->client.device->service->Dispatch == NULL) {
37 return HDF_ERR_INVALID_OBJECT;
38 }
39
40 return adapter->client.device->service->Dispatch(&adapter->client, cmdId, data, reply);
41 }
42
HdfSyscallAdapterInstance(struct HdfDeviceObject * deviceObject)43 static struct HdfSyscallAdapter *HdfSyscallAdapterInstance(struct HdfDeviceObject *deviceObject)
44 {
45 struct HdfSyscallAdapter *adapter = NULL;
46
47 static struct HdfIoDispatcher kDispatcher = {
48 .Dispatch = HdfSyscallAdapterDispatch,
49 };
50
51 adapter = CONTAINER_OF(deviceObject, struct HdfSyscallAdapter, deviceObject);
52
53 if (adapter == NULL) {
54 return NULL;
55 }
56
57 DListHeadInit(&adapter->listenerList);
58 if (OsalMutexInit(&adapter->mutex)) {
59 HDF_LOGE("%s: Failed to create mutex", __func__);
60 OsalMemFree(adapter);
61 return NULL;
62 }
63
64 if (deviceObject == NULL) {
65 OsalMutexDestroy(&adapter->mutex);
66 OsalMemFree(adapter);
67 return NULL;
68 }
69
70 adapter->client.device = deviceObject;
71
72 if (deviceObject->service != NULL && deviceObject->service->Open != NULL) {
73 if (deviceObject->service->Open(&adapter->client) != HDF_SUCCESS) {
74 OsalMutexDestroy(&adapter->mutex);
75 OsalMemFree(adapter);
76 return NULL;
77 }
78 }
79
80 adapter->super.dispatcher = &kDispatcher;
81 return adapter;
82 }
83
HdfIoServiceAdapterObtain(const char * serviceName)84 struct HdfIoService *HdfIoServiceAdapterObtain(const char *serviceName)
85 {
86 struct HdfSyscallAdapter *adapter = NULL;
87 struct HdfDeviceObject *deviceObject = NULL;
88
89 int ret;
90
91 if (serviceName == NULL) {
92 return NULL;
93 }
94
95 ret = HdfLoadDriverByServiceName(serviceName);
96 if (ret != HDF_SUCCESS) {
97 HDF_LOGE("%s: load %s driver failed", __func__, serviceName);
98 return NULL;
99 }
100
101 deviceObject = DevSvcManagerClntGetDeviceObject(serviceName);
102 if (deviceObject == NULL) {
103 return NULL;
104 }
105
106 adapter = HdfSyscallAdapterInstance(deviceObject);
107 if (adapter == NULL) {
108 return NULL;
109 }
110
111 return &adapter->super;
112 }
113
HdfIoServiceAdapterRecycle(struct HdfIoService * ioService)114 void HdfIoServiceAdapterRecycle(struct HdfIoService *ioService)
115 {
116 struct HdfSyscallAdapter *adapter = NULL;
117
118 if (ioService == NULL) {
119 return;
120 }
121
122 adapter = CONTAINER_OF(ioService, struct HdfSyscallAdapter, super);
123 if (adapter->client.device != NULL && adapter->client.device->service != NULL &&
124 adapter->client.device->service->Release != NULL) {
125 adapter->client.device->service->Release(&adapter->client);
126 }
127
128 OsalMutexDestroy(&adapter->mutex);
129 }
130
AddListenerToAdapterLocked(struct HdfSyscallAdapter * adapter,struct HdfDevEventlistener * listener)131 static bool AddListenerToAdapterLocked(struct HdfSyscallAdapter *adapter, struct HdfDevEventlistener *listener)
132 {
133 struct HdfDevEventlistener *it = NULL;
134 DLIST_FOR_EACH_ENTRY(it, &adapter->listenerList, struct HdfDevEventlistener, listNode) {
135 if (it == listener) {
136 HDF_LOGE("Add a listener for duplicate dev-event");
137 return false;
138 }
139 }
140 DListInsertTail(&listener->listNode, &adapter->listenerList);
141 return true;
142 }
143
HdfDeviceRegisterEventListener(struct HdfIoService * target,struct HdfDevEventlistener * listener)144 int32_t HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener)
145 {
146 if (target == NULL || listener == NULL) {
147 return HDF_ERR_INVALID_PARAM;
148 }
149
150 if (listener->callBack == NULL && listener->onReceive == NULL) {
151 HDF_LOGE("Listener onReceive func not implemented");
152 return HDF_ERR_INVALID_OBJECT;
153 }
154
155 struct HdfSyscallAdapter *adapter = CONTAINER_OF(target, struct HdfSyscallAdapter, super);
156
157 OsalMutexLock(&adapter->mutex);
158 if (!AddListenerToAdapterLocked(adapter, listener)) {
159 OsalMutexUnlock(&adapter->mutex);
160 return HDF_ERR_INVALID_PARAM;
161 }
162 OsalMutexUnlock(&adapter->mutex);
163 return HDF_SUCCESS;
164 }
165
HdfDeviceUnregisterEventListener(struct HdfIoService * target,struct HdfDevEventlistener * listener)166 int32_t HdfDeviceUnregisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener)
167 {
168 if (target == NULL || listener == NULL) {
169 return HDF_ERR_INVALID_PARAM;
170 }
171
172 if (listener->listNode.next == NULL || listener->listNode.prev == NULL) {
173 HDF_LOGE("%s: broken listener, may double unregister", __func__);
174 return HDF_ERR_INVALID_OBJECT;
175 }
176
177 struct HdfSyscallAdapter *adapter = CONTAINER_OF(target, struct HdfSyscallAdapter, super);
178 OsalMutexLock(&adapter->mutex);
179 DListRemove(&listener->listNode);
180 OsalMutexUnlock(&adapter->mutex);
181 return HDF_SUCCESS;
182 }
183
HdfDeviceSendEvent(const struct HdfDeviceObject * deviceObject,uint32_t id,const struct HdfSBuf * data)184 int32_t HdfDeviceSendEvent(const struct HdfDeviceObject *deviceObject, uint32_t id, const struct HdfSBuf *data)
185 {
186 const struct HdfSyscallAdapter *adapter = NULL;
187
188 if (deviceObject == NULL || data == NULL) {
189 return HDF_ERR_INVALID_PARAM;
190 }
191
192 struct HdfDeviceObject *inputDriverObject = GetHdfDeviceObject();
193
194 if (inputDriverObject == NULL) {
195 return HDF_ERR_NOT_SUPPORT;
196 }
197
198 if (deviceObject == inputDriverObject) {
199 adapter = CONTAINER_OF(deviceObject, struct HdfSyscallAdapter, deviceObject);
200 struct HdfDevEventlistener *listener = NULL;
201 DLIST_FOR_EACH_ENTRY(listener, &adapter->listenerList, struct HdfDevEventlistener, listNode) {
202 OsalMutexLock(&adapter->mutex);
203 if (listener->onReceive != NULL) {
204 (void)listener->onReceive(listener, &adapter->super, id, data);
205 } else if (listener->callBack != NULL) {
206 (void)listener->callBack(listener->priv, id, data);
207 }
208 OsalMutexUnlock(&adapter->mutex);
209 }
210 }
211 return HDF_SUCCESS;
212 }
213