1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "hdf_vnode_adapter.h"
10 #include <osal_cdev.h>
11 #include <osal_mem.h>
12 #include <osal_sem.h>
13 #include <osal_uaccess.h>
14 #include <securec.h>
15 #include "devsvc_manager_clnt.h"
16 #include "hdf_device_node_ext.h"
17 #include "hdf_log.h"
18 #include "hdf_sbuf.h"
19
20 #define HDF_LOG_TAG hdf_vnode
21 #define VOID_DATA_SIZE 4
22 #define EVENT_QUEUE_MAX 100
23 #define MAX_RW_SIZE (1024 * 1204) // 1M
24
25 enum HdfVNodeClientStatus {
26 VNODE_CLIENT_RUNNING,
27 VNODE_CLIENT_LISTENING,
28 VNODE_CLIENT_STOPPED,
29 VNODE_CLIENT_EXITED,
30 };
31
32 struct HdfVNodeAdapterClient {
33 struct HdfVNodeAdapter *adapter;
34 struct HdfDeviceIoClient ioServiceClient;
35 wait_queue_head_t pollWait;
36 struct HdfIoService *serv;
37 struct OsalMutex mutex;
38 struct DListHead eventQueue;
39 struct DListHead listNode;
40 int32_t eventQueueSize;
41 int32_t wakeup;
42 uint32_t status;
43 };
44
45 struct HdfIoServiceKClient {
46 struct HdfIoService ioService;
47 struct HdfDeviceIoClient client;
48 };
49
HdfKIoServiceDispatch(struct HdfObject * service,int cmdId,struct HdfSBuf * data,struct HdfSBuf * reply)50 int HdfKIoServiceDispatch(struct HdfObject *service, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
51 {
52 struct HdfIoService *ioService = (struct HdfIoService*)service;
53 struct HdfIoServiceKClient *kClient = NULL;
54
55 if (ioService == NULL || ioService->dispatcher == NULL) {
56 return HDF_ERR_INVALID_PARAM;
57 }
58
59 kClient = CONTAINER_OF(ioService, struct HdfIoServiceKClient, ioService);
60 if (kClient->client.device == NULL || kClient->client.device->service == NULL ||
61 kClient->client.device->service->Dispatch == NULL) {
62 return HDF_ERR_INVALID_OBJECT;
63 }
64
65 return kClient->client.device->service->Dispatch(&kClient->client, cmdId, data, reply);
66 }
67
HdfHdfIoServiceKClientInstance(struct HdfDeviceObject * deviceObject)68 static struct HdfIoServiceKClient *HdfHdfIoServiceKClientInstance(struct HdfDeviceObject *deviceObject)
69 {
70 static struct HdfIoDispatcher kDispatcher = {
71 .Dispatch = HdfKIoServiceDispatch,
72 };
73
74 struct HdfIoServiceKClient *client = OsalMemCalloc(sizeof(struct HdfIoServiceKClient));
75 if (client == NULL) {
76 return NULL;
77 }
78
79 client->client.device = deviceObject;
80 if (deviceObject->service != NULL && deviceObject->service->Open != NULL) {
81 if (deviceObject->service->Open(&client->client) != HDF_SUCCESS) {
82 OsalMemFree(client);
83 return NULL;
84 }
85 }
86
87 client->ioService.dispatcher = &kDispatcher;
88 return client;
89 }
90
HdfIoServiceAdapterObtain(const char * serviceName)91 struct HdfIoService *HdfIoServiceAdapterObtain(const char *serviceName)
92 {
93 struct DevSvcManagerClnt *svcMgr = NULL;
94 struct HdfDeviceObject *deviceObject = NULL;
95 struct HdfIoServiceKClient *kClient = NULL;
96
97 if (serviceName == NULL) {
98 return NULL;
99 }
100
101 svcMgr = DevSvcManagerClntGetInstance();
102 if (svcMgr == NULL || svcMgr->devSvcMgrIf == NULL) {
103 return NULL;
104 }
105 deviceObject = svcMgr->devSvcMgrIf->GetObject(svcMgr->devSvcMgrIf, serviceName);
106 if (deviceObject == NULL) {
107 return NULL;
108 }
109
110 kClient = HdfHdfIoServiceKClientInstance(deviceObject);
111 if (kClient == NULL) {
112 return NULL;
113 }
114
115 return &kClient->ioService;
116 }
117
HdfIoServiceAdapterRecycle(struct HdfIoService * ioService)118 void HdfIoServiceAdapterRecycle(struct HdfIoService *ioService)
119 {
120 struct HdfIoServiceKClient *kClient = NULL;
121
122 if (ioService == NULL) {
123 return;
124 }
125
126 kClient = CONTAINER_OF(ioService, struct HdfIoServiceKClient, ioService);
127 if (kClient->client.device != NULL && kClient->client.device->service != NULL &&
128 kClient->client.device->service->Release != NULL) {
129 kClient->client.device->service->Release(&kClient->client);
130 }
131 OsalMemFree(kClient);
132 }
133
HdfSbufCopyFromUser(uintptr_t data,size_t size)134 static struct HdfSBuf *HdfSbufCopyFromUser(uintptr_t data, size_t size)
135 {
136 uint8_t *kData = NULL;
137 struct HdfSBuf *sbuf = NULL;
138
139 if (size == 0) {
140 return HdfSbufObtain(VOID_DATA_SIZE);
141 }
142
143 kData = OsalMemAlloc(size);
144 if (kData == NULL) {
145 HDF_LOGE("%s:oom", __func__);
146 return NULL;
147 }
148 if (CopyFromUser((void*)kData, (void*)data, size) != 0) {
149 HDF_LOGE("%s:failed to copy from user", __func__);
150 OsalMemFree(kData);
151 return NULL;
152 }
153
154 sbuf = HdfSbufBind((uintptr_t)kData, size);
155 if (sbuf == NULL) {
156 OsalMemFree(kData);
157 }
158 HdfSbufTransDataOwnership(sbuf);
159
160 return sbuf;
161 }
162
HdfSbufCopyToUser(const struct HdfSBuf * sbuf,void * dstUser,size_t dstUserSize)163 static int HdfSbufCopyToUser(const struct HdfSBuf *sbuf, void *dstUser, size_t dstUserSize)
164 {
165 size_t sbufSize = HdfSbufGetDataSize(sbuf);
166 if (sbufSize == 0) {
167 return HDF_SUCCESS;
168 }
169 if (dstUserSize < sbufSize) {
170 HDF_LOGE("%s: readBuffer too small %zu", __func__, sbufSize);
171 return HDF_DEV_ERR_NORANGE;
172 }
173
174 if (CopyToUser(dstUser, HdfSbufGetData(sbuf), sbufSize) != 0) {
175 HDF_LOGE("%s: failed to copy buff data", __func__);
176 return HDF_ERR_IO;
177 }
178
179 return HDF_SUCCESS;
180 }
181
DevEventFree(struct HdfDevEvent * event)182 static void DevEventFree(struct HdfDevEvent *event)
183 {
184 if (event == NULL) {
185 return;
186 }
187 if (event->data != NULL) {
188 HdfSbufRecycle(event->data);
189 event->data = NULL;
190 }
191 OsalMemFree(event);
192 }
193
HdfVNodeAdapterServCall(const struct HdfVNodeAdapterClient * client,unsigned long arg)194 static int HdfVNodeAdapterServCall(const struct HdfVNodeAdapterClient *client, unsigned long arg)
195 {
196 struct HdfWriteReadBuf bwr;
197 struct HdfWriteReadBuf *bwrUser = (struct HdfWriteReadBuf *)((uintptr_t)arg);
198 struct HdfSBuf *data = NULL;
199 struct HdfSBuf *reply = NULL;
200 int ret;
201
202 if (client->serv == NULL || client->adapter == NULL ||
203 client->adapter->ioService.dispatcher == NULL ||
204 client->adapter->ioService.dispatcher->Dispatch == NULL) {
205 return HDF_ERR_INVALID_OBJECT;
206 }
207
208 if (bwrUser == NULL) {
209 return HDF_ERR_INVALID_PARAM;
210 }
211 if (CopyFromUser(&bwr, (void*)bwrUser, sizeof(bwr)) != 0) {
212 HDF_LOGE("copy from user failed");
213 return HDF_FAILURE;
214 }
215 if (bwr.writeSize > MAX_RW_SIZE || bwr.readSize > MAX_RW_SIZE) {
216 return HDF_ERR_INVALID_PARAM;
217 }
218
219 data = HdfSbufCopyFromUser(bwr.writeBuffer, bwr.writeSize);
220 if (data == NULL) {
221 HDF_LOGE("vnode adapter bind data is null");
222 return HDF_FAILURE;
223 }
224 reply = HdfSbufObtainDefaultSize();
225 if (reply == NULL) {
226 HDF_LOGE("%s: oom", __func__);
227 HdfSbufRecycle(data);
228 return HDF_FAILURE;
229 }
230 (void)HdfSbufWriteUint64(reply, (uintptr_t)&client->ioServiceClient);
231 ret = client->adapter->ioService.dispatcher->Dispatch(client->adapter->ioService.target,
232 bwr.cmdCode, data, reply);
233 if (bwr.readSize != 0 && HdfSbufCopyToUser(reply, (void*)(uintptr_t)bwr.readBuffer, bwr.readSize) != HDF_SUCCESS) {
234 HdfSbufRecycle(data);
235 HdfSbufRecycle(reply);
236 return HDF_ERR_IO;
237 }
238 bwr.readConsumed = HdfSbufGetDataSize(reply);
239 if (CopyToUser(bwrUser, &bwr, sizeof(struct HdfWriteReadBuf)) != 0) {
240 HDF_LOGE("%s: fail to copy bwr", __func__);
241 ret = HDF_FAILURE;
242 }
243
244 HdfSbufRecycle(data);
245 HdfSbufRecycle(reply);
246 return ret;
247 }
248
HdfVNodeAdapterReadDevEvent(struct HdfVNodeAdapterClient * client,unsigned long arg)249 static int HdfVNodeAdapterReadDevEvent(struct HdfVNodeAdapterClient *client, unsigned long arg)
250 {
251 struct HdfWriteReadBuf bwr;
252 struct HdfWriteReadBuf *bwrUser = (struct HdfWriteReadBuf *)((uintptr_t)arg);
253 struct HdfDevEvent *event = NULL;
254 size_t eventSize;
255
256 int ret = HDF_SUCCESS;
257 if (bwrUser == NULL) {
258 return HDF_ERR_INVALID_PARAM;
259 }
260
261 if (CopyFromUser(&bwr, (void*)bwrUser, sizeof(bwr)) != 0) {
262 HDF_LOGE("Copy from user failed");
263 return HDF_FAILURE;
264 }
265
266 if (bwr.readSize > MAX_RW_SIZE) {
267 return HDF_ERR_INVALID_PARAM;
268 }
269 OsalMutexLock(&client->mutex);
270
271 if (DListIsEmpty(&client->eventQueue)) {
272 OsalMutexUnlock(&client->mutex);
273 return HDF_DEV_ERR_NODATA;
274 }
275
276 event = CONTAINER_OF(client->eventQueue.next, struct HdfDevEvent, listNode);
277 eventSize = HdfSbufGetDataSize(event->data);
278 if (eventSize > bwr.readSize) {
279 bwr.readSize = eventSize;
280 ret = HDF_DEV_ERR_NORANGE;
281 } else {
282 if (HdfSbufCopyToUser(event->data, (void *)(uintptr_t)bwr.readBuffer, bwr.readSize) != HDF_SUCCESS) {
283 OsalMutexUnlock(&client->mutex);
284 return HDF_ERR_IO;
285 }
286 bwr.readConsumed = eventSize;
287 bwr.cmdCode = (int32_t)event->id;
288 }
289
290 if (CopyToUser(bwrUser, &bwr, sizeof(struct HdfWriteReadBuf)) != 0) {
291 HDF_LOGE("%s: failed to copy bwr", __func__);
292 ret = HDF_ERR_IO;
293 }
294 if (ret == HDF_SUCCESS) {
295 DListRemove(&event->listNode);
296 DevEventFree(event);
297 client->eventQueueSize--;
298 }
299
300 OsalMutexUnlock(&client->mutex);
301 return ret;
302 }
303
HdfVnodeAdapterDropOldEventLocked(struct HdfVNodeAdapterClient * client)304 static void HdfVnodeAdapterDropOldEventLocked(struct HdfVNodeAdapterClient *client)
305 {
306 struct HdfDevEvent *dropEvent = CONTAINER_OF(client->eventQueue.next, struct HdfDevEvent, listNode);
307 if (client->adapter != NULL) {
308 const char *nodePath = client->adapter->vNodePath;
309 HDF_LOGE("dev(%{public}s) event queue full, drop old one", nodePath == NULL ? "unknown" : nodePath);
310 }
311
312 DListRemove(&dropEvent->listNode);
313 DevEventFree(dropEvent);
314 client->eventQueueSize--;
315 }
316
VNodeAdapterSendDevEventToClient(struct HdfVNodeAdapterClient * vnodeClient,uint32_t id,const struct HdfSBuf * data)317 static int VNodeAdapterSendDevEventToClient(struct HdfVNodeAdapterClient *vnodeClient,
318 uint32_t id, const struct HdfSBuf *data)
319 {
320 struct HdfDevEvent *event = NULL;
321
322 OsalMutexLock(&vnodeClient->mutex);
323 if (vnodeClient->status != VNODE_CLIENT_LISTENING) {
324 OsalMutexUnlock(&vnodeClient->mutex);
325 return HDF_SUCCESS;
326 }
327 if (vnodeClient->eventQueueSize >= EVENT_QUEUE_MAX) {
328 HdfVnodeAdapterDropOldEventLocked(vnodeClient);
329 }
330 event = OsalMemAlloc(sizeof(struct HdfDevEvent));
331 if (event == NULL) {
332 OsalMutexUnlock(&vnodeClient->mutex);
333 return HDF_DEV_ERR_NO_MEMORY;
334 }
335 event->id = id;
336 event->data = HdfSbufCopy(data);
337 if (event->data == NULL) {
338 OsalMutexUnlock(&vnodeClient->mutex);
339 HDF_LOGE("%s: sbuf oom", __func__);
340 OsalMemFree(event);
341 return HDF_DEV_ERR_NO_MEMORY;
342 }
343 DListInsertTail(&event->listNode, &vnodeClient->eventQueue);
344 vnodeClient->eventQueueSize++;
345 wake_up_interruptible(&vnodeClient->pollWait);
346 OsalMutexUnlock(&vnodeClient->mutex);
347
348 return HDF_SUCCESS;
349 }
350
HdfVNodeAdapterSendDevEvent(struct HdfVNodeAdapter * adapter,struct HdfVNodeAdapterClient * vnodeClient,uint32_t id,const struct HdfSBuf * data)351 static int HdfVNodeAdapterSendDevEvent(struct HdfVNodeAdapter *adapter, struct HdfVNodeAdapterClient *vnodeClient,
352 uint32_t id, const struct HdfSBuf *data)
353 {
354 struct HdfVNodeAdapterClient *client = NULL;
355 int ret = HDF_FAILURE;
356
357 if (adapter == NULL || data == NULL || HdfSbufGetDataSize(data) == 0) {
358 return HDF_ERR_INVALID_PARAM;
359 }
360 OsalMutexLock(&adapter->mutex);
361 DLIST_FOR_EACH_ENTRY(client, &adapter->clientList, struct HdfVNodeAdapterClient, listNode) {
362 if (vnodeClient != NULL && client != vnodeClient) {
363 continue;
364 }
365 ret = VNodeAdapterSendDevEventToClient(client, id, data);
366 if (ret != HDF_SUCCESS) {
367 break;
368 }
369 }
370 OsalMutexUnlock(&adapter->mutex);
371 return ret;
372 }
373
HdfVNodeAdapterClientStartListening(struct HdfVNodeAdapterClient * client)374 static void HdfVNodeAdapterClientStartListening(struct HdfVNodeAdapterClient *client)
375 {
376 OsalMutexLock(&client->mutex);
377 client->status = VNODE_CLIENT_LISTENING;
378 OsalMutexUnlock(&client->mutex);
379 }
380
HdfVnodeCleanEventQueue(struct HdfVNodeAdapterClient * client)381 static void HdfVnodeCleanEventQueue(struct HdfVNodeAdapterClient *client)
382 {
383 struct HdfDevEvent *event = NULL;
384 struct HdfDevEvent *eventTemp = NULL;
385 DLIST_FOR_EACH_ENTRY_SAFE(event, eventTemp, &client->eventQueue, struct HdfDevEvent, listNode) {
386 DListRemove(&event->listNode);
387 DevEventFree(event);
388 }
389 }
390
HdfVNodeAdapterClientStopListening(struct HdfVNodeAdapterClient * client)391 static void HdfVNodeAdapterClientStopListening(struct HdfVNodeAdapterClient *client)
392 {
393 OsalMutexLock(&client->mutex);
394 client->status = VNODE_CLIENT_STOPPED;
395 HdfVnodeCleanEventQueue(client);
396 wake_up_interruptible(&client->pollWait);
397 OsalMutexUnlock(&client->mutex);
398 }
399
HdfVNodeAdapterClientExitListening(struct HdfVNodeAdapterClient * client)400 static void HdfVNodeAdapterClientExitListening(struct HdfVNodeAdapterClient *client)
401 {
402 OsalMutexLock(&client->mutex);
403 client->status = VNODE_CLIENT_EXITED;
404 HdfVnodeCleanEventQueue(client);
405 wake_up_interruptible(&client->pollWait);
406 OsalMutexUnlock(&client->mutex);
407 }
408
HdfVNodeAdapterClientWakeup(struct HdfVNodeAdapterClient * client)409 static void HdfVNodeAdapterClientWakeup(struct HdfVNodeAdapterClient *client)
410 {
411 OsalMutexLock(&client->mutex);
412 if (client->status != VNODE_CLIENT_LISTENING) {
413 OsalMutexUnlock(&client->mutex);
414 return;
415 }
416 client->wakeup++;
417 wake_up_interruptible(&client->pollWait);
418 OsalMutexUnlock(&client->mutex);
419 }
420
HdfVNodeAdapterIoctl(struct file * filep,unsigned int cmd,unsigned long arg)421 static long HdfVNodeAdapterIoctl(struct file *filep, unsigned int cmd, unsigned long arg)
422 {
423 struct HdfVNodeAdapterClient *client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
424 if (client == NULL) {
425 return HDF_DEV_ERR_NO_DEVICE;
426 }
427 switch (cmd) {
428 case HDF_WRITE_READ:
429 return HdfVNodeAdapterServCall(client, arg);
430 case HDF_READ_DEV_EVENT:
431 return HdfVNodeAdapterReadDevEvent(client, arg);
432 case HDF_LISTEN_EVENT_START:
433 HdfVNodeAdapterClientStartListening(client);
434 break;
435 case HDF_LISTEN_EVENT_STOP:
436 HdfVNodeAdapterClientStopListening(client);
437 break;
438 case HDF_LISTEN_EVENT_WAKEUP:
439 HdfVNodeAdapterClientWakeup(client);
440 break;
441 case HDF_LISTEN_EVENT_EXIT:
442 HdfVNodeAdapterClientExitListening(client);
443 break;
444 default:
445 return HDF_FAILURE;
446 }
447
448 return HDF_SUCCESS;
449 }
450
HdfNewVNodeAdapterClient(struct HdfVNodeAdapter * adapter)451 static struct HdfVNodeAdapterClient *HdfNewVNodeAdapterClient(struct HdfVNodeAdapter *adapter)
452 {
453 struct HdfVNodeAdapterClient *client = OsalMemCalloc(sizeof(struct HdfVNodeAdapterClient));
454 if (client == NULL) {
455 HDF_LOGE("%s: oom", __func__);
456 return NULL;
457 }
458 if (OsalMutexInit(&client->mutex) != HDF_SUCCESS) {
459 OsalMemFree(client);
460 HDF_LOGE("%s: no mutex", __func__);
461 return NULL;
462 }
463
464 DListHeadInit(&client->eventQueue);
465 client->eventQueueSize = 0;
466 client->serv = &adapter->ioService;
467 client->status = VNODE_CLIENT_RUNNING;
468 client->adapter = adapter;
469 client->ioServiceClient.device = (struct HdfDeviceObject *)adapter->ioService.target;
470 client->ioServiceClient.priv = NULL;
471 client->wakeup = 0;
472 init_waitqueue_head(&client->pollWait);
473 OsalMutexLock(&adapter->mutex);
474 DListInsertTail(&client->listNode, &adapter->clientList);
475 OsalMutexUnlock(&adapter->mutex);
476
477 return client;
478 }
479
HdfDestoryVNodeAdapterClient(struct HdfVNodeAdapterClient * client)480 static void HdfDestoryVNodeAdapterClient(struct HdfVNodeAdapterClient *client)
481 {
482 struct HdfDevEvent *event = NULL;
483 struct HdfDevEvent *eventTemp = NULL;
484
485 client->status = VNODE_CLIENT_STOPPED;
486
487 OsalMutexLock(&client->adapter->mutex);
488 DListRemove(&client->listNode);
489 OsalMutexUnlock(&client->adapter->mutex);
490
491 OsalMutexLock(&client->mutex);
492 DLIST_FOR_EACH_ENTRY_SAFE(event, eventTemp, &client->eventQueue, struct HdfDevEvent, listNode) {
493 DListRemove(&event->listNode);
494 DevEventFree(event);
495 }
496 OsalMutexUnlock(&client->mutex);
497 OsalMutexDestroy(&client->mutex);
498 OsalMemFree(client);
499 }
500
HdfVNodeAdapterOpen(struct OsalCdev * cdev,struct file * filep)501 int HdfVNodeAdapterOpen(struct OsalCdev *cdev, struct file *filep)
502 {
503 struct HdfVNodeAdapter *adapter = (struct HdfVNodeAdapter *)OsalGetCdevPriv(cdev);
504 struct HdfVNodeAdapterClient *client = NULL;
505 int32_t ret;
506
507 if (adapter == NULL) {
508 HDF_LOGE("Vnode adapter dispatcher is null");
509 return HDF_FAILURE;
510 }
511 client = HdfNewVNodeAdapterClient(adapter);
512 if (client == NULL) {
513 return ETXTBSY;
514 }
515 OsalSetFilePriv(filep, client);
516 if (client->ioServiceClient.device != NULL && client->ioServiceClient.device->service != NULL &&
517 client->ioServiceClient.device->service->Open != NULL) {
518 ret = client->ioServiceClient.device->service->Open(&client->ioServiceClient);
519 if (ret != HDF_SUCCESS) {
520 HdfDestoryVNodeAdapterClient(client);
521 return ret;
522 }
523 }
524
525 return HDF_SUCCESS;
526 }
527
HdfVNodeAdapterPoll(struct file * filep,poll_table * wait)528 static unsigned int HdfVNodeAdapterPoll(struct file *filep, poll_table *wait)
529 {
530 unsigned int mask = 0;
531 struct HdfVNodeAdapterClient *client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
532 if (client == NULL) {
533 mask |= POLLERR;
534 return mask;
535 }
536 poll_wait(filep, &client->pollWait, wait);
537 OsalMutexLock(&client->mutex);
538 if (client->status == VNODE_CLIENT_EXITED) {
539 mask |= POLLHUP;
540 } else if (!DListIsEmpty(&client->eventQueue)) {
541 mask |= POLLIN;
542 } else if (client->wakeup > 0) {
543 mask |= POLLIN;
544 client->wakeup--;
545 }
546 OsalMutexUnlock(&client->mutex);
547
548 return mask;
549 }
550
HdfVNodeAdapterClose(struct OsalCdev * cdev,struct file * filep)551 static int HdfVNodeAdapterClose(struct OsalCdev *cdev, struct file *filep)
552 {
553 struct HdfVNodeAdapterClient *client = NULL;
554 (void)cdev;
555 client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
556 if (client->ioServiceClient.device != NULL && client->ioServiceClient.device->service != NULL &&
557 client->ioServiceClient.device->service->Release != NULL) {
558 client->ioServiceClient.device->service->Release(&client->ioServiceClient);
559 }
560 HdfDestoryVNodeAdapterClient(client);
561 OsalSetFilePriv(filep, NULL);
562 return HDF_SUCCESS;
563 }
564
HdfIoServiceAdapterRegCdev(struct HdfVNodeAdapter * vnodeAdapter,const struct OsalCdevOps * fileOps,uint32_t mode)565 struct HdfIoService *HdfIoServiceAdapterRegCdev(struct HdfVNodeAdapter *vnodeAdapter,
566 const struct OsalCdevOps *fileOps, uint32_t mode)
567 {
568 int32_t ret;
569 DListHeadInit(&vnodeAdapter->clientList);
570 if (OsalMutexInit(&vnodeAdapter->mutex) != HDF_SUCCESS) {
571 HDF_LOGE("vnode adapter out of mutex");
572 goto ERROR;
573 }
574 vnodeAdapter->cdev = OsalAllocCdev(fileOps);
575 if (vnodeAdapter->cdev == NULL) {
576 HDF_LOGE("fail to alloc osalcdev");
577 OsalMutexDestroy(&vnodeAdapter->mutex);
578 goto ERROR;
579 }
580 ret = OsalRegisterCdev(vnodeAdapter->cdev, vnodeAdapter->vNodePath, mode, vnodeAdapter);
581 if (ret != 0) {
582 HDF_LOGE("failed to register dev node %s, ret is: %d", vnodeAdapter->vNodePath, ret);
583 OsalMutexDestroy(&vnodeAdapter->mutex);
584 goto ERROR;
585 }
586 return &vnodeAdapter->ioService;
587 ERROR:
588 OsalMemFree(vnodeAdapter->vNodePath);
589 OsalMemFree(vnodeAdapter);
590 return NULL;
591 }
592
HdfIoServiceAdapterPublish(const char * serviceName,uint32_t mode)593 struct HdfIoService *HdfIoServiceAdapterPublish(const char *serviceName, uint32_t mode)
594 {
595 int nodePathLength;
596 struct HdfVNodeAdapter *vnodeAdapter = NULL;
597 static const struct OsalCdevOps fileOps = {
598 .open = HdfVNodeAdapterOpen,
599 .release = HdfVNodeAdapterClose,
600 .ioctl = HdfVNodeAdapterIoctl,
601 .poll = HdfVNodeAdapterPoll,
602 };
603
604 if ((serviceName == NULL) || (mode > MAX_MODE_SIZE)) {
605 HDF_LOGE("input param is invalid, mode is %x", mode);
606 return NULL;
607 }
608
609 vnodeAdapter = (struct HdfVNodeAdapter *)OsalMemCalloc(sizeof(struct HdfVNodeAdapter));
610 if (vnodeAdapter == NULL) {
611 HDF_LOGE("alloc remote service is null");
612 return NULL;
613 }
614
615 nodePathLength = strlen(serviceName) + strlen(DEV_NODE_PATH) + 1;
616 vnodeAdapter->vNodePath = (char *)OsalMemCalloc(nodePathLength);
617 if (vnodeAdapter->vNodePath == NULL) {
618 HDF_LOGE("alloc vnode path is null");
619 OsalMemFree(vnodeAdapter);
620 return NULL;
621 }
622
623 if (sprintf_s(vnodeAdapter->vNodePath, nodePathLength, "%s%s", DEV_NODE_PATH, serviceName) < 0) {
624 HDF_LOGE("failed to get node path");
625 OsalMemFree(vnodeAdapter->vNodePath);
626 OsalMemFree(vnodeAdapter);
627 return NULL;
628 }
629 return HdfIoServiceAdapterRegCdev(vnodeAdapter, &fileOps, mode);
630 }
631
HdfIoServiceAdapterRemove(struct HdfIoService * service)632 void HdfIoServiceAdapterRemove(struct HdfIoService *service)
633 {
634 if (service != NULL) {
635 struct HdfVNodeAdapter *vnodeAdapter = (struct HdfVNodeAdapter *)service;
636 if (vnodeAdapter->vNodePath != NULL) {
637 OsalUnregisterCdev(vnodeAdapter->cdev);
638 OsalFreeCdev(vnodeAdapter->cdev);
639 OsalMemFree(vnodeAdapter->vNodePath);
640 }
641 OsalMutexDestroy(&vnodeAdapter->mutex);
642 OsalMemFree(vnodeAdapter);
643 }
644 }
645
HdfDeviceSendEvent(const struct HdfDeviceObject * deviceObject,uint32_t id,const struct HdfSBuf * data)646 int32_t HdfDeviceSendEvent(const struct HdfDeviceObject *deviceObject, uint32_t id, const struct HdfSBuf *data)
647 {
648 struct HdfDeviceNode *deviceNode = NULL;
649 struct HdfVNodeAdapter *adapter = NULL;
650
651 if (deviceObject == NULL || data == NULL) {
652 return HDF_ERR_INVALID_PARAM;
653 }
654
655 deviceNode = CONTAINER_OF(deviceObject, struct HdfDeviceNode, deviceObject);
656 if (deviceNode->policy != SERVICE_POLICY_CAPACITY) {
657 return HDF_ERR_NOT_SUPPORT;
658 }
659
660 adapter = (struct HdfVNodeAdapter *)(((struct DeviceNodeExt*)deviceNode)->ioService);
661 return HdfVNodeAdapterSendDevEvent(adapter, NULL, id, data);
662 }
663
HdfDeviceSendEventToClient(const struct HdfDeviceIoClient * client,uint32_t id,const struct HdfSBuf * data)664 int32_t HdfDeviceSendEventToClient(const struct HdfDeviceIoClient *client, uint32_t id, const struct HdfSBuf *data)
665 {
666 struct HdfVNodeAdapterClient *vnodeClient = NULL;
667 if (client == NULL || client->device == NULL) {
668 return HDF_ERR_INVALID_PARAM;
669 }
670
671 vnodeClient = CONTAINER_OF(client, struct HdfVNodeAdapterClient, ioServiceClient);
672 if (vnodeClient->adapter == NULL) {
673 return HDF_ERR_INVALID_PARAM;
674 }
675
676 return HdfVNodeAdapterSendDevEvent(vnodeClient->adapter, vnodeClient, id, data);
677 }
678