• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 %u", __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 
308     HDF_LOGE("dev event queue full, drop old one");
309     DListRemove(&dropEvent->listNode);
310     DevEventFree(dropEvent);
311     client->eventQueueSize--;
312 }
313 
VNodeAdapterSendDevEventToClient(struct HdfVNodeAdapterClient * vnodeClient,uint32_t id,const struct HdfSBuf * data)314 static int VNodeAdapterSendDevEventToClient(struct HdfVNodeAdapterClient *vnodeClient,
315     uint32_t id, const struct HdfSBuf *data)
316 {
317     struct HdfDevEvent *event = NULL;
318 
319     OsalMutexLock(&vnodeClient->mutex);
320     if (vnodeClient->status != VNODE_CLIENT_LISTENING) {
321         OsalMutexUnlock(&vnodeClient->mutex);
322         return HDF_SUCCESS;
323     }
324     if (vnodeClient->eventQueueSize >= EVENT_QUEUE_MAX) {
325         HdfVnodeAdapterDropOldEventLocked(vnodeClient);
326     }
327     event = OsalMemAlloc(sizeof(struct HdfDevEvent));
328     if (event == NULL) {
329         OsalMutexUnlock(&vnodeClient->mutex);
330         return HDF_DEV_ERR_NO_MEMORY;
331     }
332     event->id = id;
333     event->data = HdfSbufCopy(data);
334     if (event->data == NULL) {
335         OsalMutexUnlock(&vnodeClient->mutex);
336         HDF_LOGE("%s: sbuf oom", __func__);
337         OsalMemFree(event);
338         return HDF_DEV_ERR_NO_MEMORY;
339     }
340     DListInsertTail(&event->listNode, &vnodeClient->eventQueue);
341     vnodeClient->eventQueueSize++;
342     wake_up_interruptible(&vnodeClient->pollWait);
343     OsalMutexUnlock(&vnodeClient->mutex);
344 
345     return HDF_SUCCESS;
346 }
347 
HdfVNodeAdapterSendDevEvent(struct HdfVNodeAdapter * adapter,struct HdfVNodeAdapterClient * vnodeClient,uint32_t id,const struct HdfSBuf * data)348 static int HdfVNodeAdapterSendDevEvent(struct HdfVNodeAdapter *adapter, struct HdfVNodeAdapterClient *vnodeClient,
349     uint32_t id, const struct HdfSBuf *data)
350 {
351     struct HdfVNodeAdapterClient *client = NULL;
352     int ret = HDF_FAILURE;
353 
354     if (adapter == NULL || data == NULL || HdfSbufGetDataSize(data) == 0) {
355         return HDF_ERR_INVALID_PARAM;
356     }
357     OsalMutexLock(&adapter->mutex);
358     DLIST_FOR_EACH_ENTRY(client, &adapter->clientList, struct HdfVNodeAdapterClient, listNode) {
359         if (vnodeClient != NULL && client != vnodeClient) {
360             continue;
361         }
362         ret = VNodeAdapterSendDevEventToClient(client, id, data);
363         if (ret != HDF_SUCCESS) {
364             break;
365         }
366     }
367     OsalMutexUnlock(&adapter->mutex);
368     return ret;
369 }
370 
HdfVNodeAdapterClientStartListening(struct HdfVNodeAdapterClient * client)371 static void HdfVNodeAdapterClientStartListening(struct HdfVNodeAdapterClient *client)
372 {
373     OsalMutexLock(&client->mutex);
374     client->status = VNODE_CLIENT_LISTENING;
375     OsalMutexUnlock(&client->mutex);
376 }
377 
HdfVnodeCleanEventQueue(struct HdfVNodeAdapterClient * client)378 static void HdfVnodeCleanEventQueue(struct HdfVNodeAdapterClient *client)
379 {
380     struct HdfDevEvent *event = NULL;
381     struct HdfDevEvent *eventTemp = NULL;
382     DLIST_FOR_EACH_ENTRY_SAFE(event, eventTemp, &client->eventQueue, struct HdfDevEvent, listNode) {
383         DListRemove(&event->listNode);
384         DevEventFree(event);
385     }
386 }
387 
HdfVNodeAdapterClientStopListening(struct HdfVNodeAdapterClient * client)388 static void HdfVNodeAdapterClientStopListening(struct HdfVNodeAdapterClient *client)
389 {
390     OsalMutexLock(&client->mutex);
391     client->status = VNODE_CLIENT_STOPPED;
392     HdfVnodeCleanEventQueue(client);
393     wake_up_interruptible(&client->pollWait);
394     OsalMutexUnlock(&client->mutex);
395 }
396 
HdfVNodeAdapterClientExitListening(struct HdfVNodeAdapterClient * client)397 static void HdfVNodeAdapterClientExitListening(struct HdfVNodeAdapterClient *client)
398 {
399     OsalMutexLock(&client->mutex);
400     client->status = VNODE_CLIENT_EXITED;
401     HdfVnodeCleanEventQueue(client);
402     wake_up_interruptible(&client->pollWait);
403     OsalMutexUnlock(&client->mutex);
404 }
405 
HdfVNodeAdapterClientWakeup(struct HdfVNodeAdapterClient * client)406 static void HdfVNodeAdapterClientWakeup(struct HdfVNodeAdapterClient *client)
407 {
408     OsalMutexLock(&client->mutex);
409     if (client->status != VNODE_CLIENT_LISTENING) {
410         OsalMutexUnlock(&client->mutex);
411         return;
412     }
413     client->wakeup++;
414     wake_up_interruptible(&client->pollWait);
415     OsalMutexUnlock(&client->mutex);
416 }
417 
HdfVNodeAdapterIoctl(struct file * filep,unsigned int cmd,unsigned long arg)418 static long HdfVNodeAdapterIoctl(struct file *filep,  unsigned int cmd, unsigned long arg)
419 {
420     struct HdfVNodeAdapterClient *client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
421     if (client == NULL) {
422         return HDF_DEV_ERR_NO_DEVICE;
423     }
424     switch (cmd) {
425         case HDF_WRITE_READ:
426             return HdfVNodeAdapterServCall(client, arg);
427         case HDF_READ_DEV_EVENT:
428             return HdfVNodeAdapterReadDevEvent(client, arg);
429         case HDF_LISTEN_EVENT_START:
430             HdfVNodeAdapterClientStartListening(client);
431             break;
432         case HDF_LISTEN_EVENT_STOP:
433             HdfVNodeAdapterClientStopListening(client);
434             break;
435         case HDF_LISTEN_EVENT_WAKEUP:
436             HdfVNodeAdapterClientWakeup(client);
437             break;
438         case HDF_LISTEN_EVENT_EXIT:
439             HdfVNodeAdapterClientExitListening(client);
440             break;
441         default:
442             return HDF_FAILURE;
443     }
444 
445     return HDF_SUCCESS;
446 }
447 
HdfNewVNodeAdapterClient(struct HdfVNodeAdapter * adapter)448 static struct HdfVNodeAdapterClient *HdfNewVNodeAdapterClient(struct HdfVNodeAdapter *adapter)
449 {
450     struct HdfVNodeAdapterClient *client = OsalMemCalloc(sizeof(struct HdfVNodeAdapterClient));
451     if (client == NULL) {
452         HDF_LOGE("%s: oom", __func__);
453         return NULL;
454     }
455     if (OsalMutexInit(&client->mutex) != HDF_SUCCESS) {
456         OsalMemFree(client);
457         HDF_LOGE("%s: no mutex", __func__);
458         return NULL;
459     }
460 
461     DListHeadInit(&client->eventQueue);
462     client->eventQueueSize = 0;
463     client->serv = &adapter->ioService;
464     client->status = VNODE_CLIENT_RUNNING;
465     client->adapter = adapter;
466     client->ioServiceClient.device = (struct HdfDeviceObject *)adapter->ioService.target;
467     client->ioServiceClient.priv = NULL;
468     client->wakeup = 0;
469     init_waitqueue_head(&client->pollWait);
470     OsalMutexLock(&adapter->mutex);
471     DListInsertTail(&client->listNode, &adapter->clientList);
472     OsalMutexUnlock(&adapter->mutex);
473 
474     return client;
475 }
476 
HdfDestoryVNodeAdapterClient(struct HdfVNodeAdapterClient * client)477 static void HdfDestoryVNodeAdapterClient(struct HdfVNodeAdapterClient *client)
478 {
479     struct HdfDevEvent *event = NULL;
480     struct HdfDevEvent *eventTemp = NULL;
481 
482     client->status = VNODE_CLIENT_STOPPED;
483 
484     OsalMutexLock(&client->adapter->mutex);
485     DListRemove(&client->listNode);
486     OsalMutexUnlock(&client->adapter->mutex);
487 
488     OsalMutexLock(&client->mutex);
489     DLIST_FOR_EACH_ENTRY_SAFE(event, eventTemp, &client->eventQueue, struct HdfDevEvent, listNode) {
490         DListRemove(&event->listNode);
491         DevEventFree(event);
492     }
493     OsalMutexUnlock(&client->mutex);
494     OsalMutexDestroy(&client->mutex);
495     OsalMemFree(client);
496 }
497 
HdfVNodeAdapterOpen(struct OsalCdev * cdev,struct file * filep)498 int HdfVNodeAdapterOpen(struct OsalCdev *cdev, struct file *filep)
499 {
500     struct HdfVNodeAdapter *adapter = (struct HdfVNodeAdapter *)OsalGetCdevPriv(cdev);
501     struct HdfVNodeAdapterClient *client = NULL;
502     int32_t ret;
503 
504     if (adapter == NULL) {
505         HDF_LOGE("Vnode adapter dispatcher is null");
506         return HDF_FAILURE;
507     }
508     client = HdfNewVNodeAdapterClient(adapter);
509     if (client == NULL) {
510         return ETXTBSY;
511     }
512     OsalSetFilePriv(filep, client);
513     if (client->ioServiceClient.device != NULL && client->ioServiceClient.device->service != NULL &&
514         client->ioServiceClient.device->service->Open != NULL) {
515         ret = client->ioServiceClient.device->service->Open(&client->ioServiceClient);
516         if (ret != HDF_SUCCESS) {
517             HdfDestoryVNodeAdapterClient(client);
518             return ret;
519         }
520     }
521 
522     return HDF_SUCCESS;
523 }
524 
HdfVNodeAdapterPoll(struct file * filep,poll_table * wait)525 static unsigned int HdfVNodeAdapterPoll(struct file *filep, poll_table *wait)
526 {
527     unsigned int mask = 0;
528     struct HdfVNodeAdapterClient *client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
529     if (client == NULL) {
530         mask |= POLLERR;
531         return mask;
532     }
533     poll_wait(filep, &client->pollWait, wait);
534     OsalMutexLock(&client->mutex);
535     if (client->status == VNODE_CLIENT_EXITED) {
536         mask |= POLLHUP;
537     } else if (!DListIsEmpty(&client->eventQueue)) {
538         mask |= POLLIN;
539     } else if (client->wakeup > 0) {
540         mask |= POLLIN;
541         client->wakeup--;
542     }
543     OsalMutexUnlock(&client->mutex);
544 
545     return mask;
546 }
547 
HdfVNodeAdapterClose(struct OsalCdev * cdev,struct file * filep)548 static int HdfVNodeAdapterClose(struct OsalCdev *cdev, struct file *filep)
549 {
550     struct HdfVNodeAdapterClient *client = NULL;
551     (void)cdev;
552     client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
553     if (client->ioServiceClient.device != NULL && client->ioServiceClient.device->service != NULL &&
554         client->ioServiceClient.device->service->Release != NULL) {
555         client->ioServiceClient.device->service->Release(&client->ioServiceClient);
556     }
557     HdfDestoryVNodeAdapterClient(client);
558     OsalSetFilePriv(filep, NULL);
559     return HDF_SUCCESS;
560 }
561 
HdfIoServiceAdapterRegCdev(struct HdfVNodeAdapter * vnodeAdapter,const struct OsalCdevOps * fileOps,uint32_t mode)562 struct HdfIoService *HdfIoServiceAdapterRegCdev(struct HdfVNodeAdapter *vnodeAdapter,
563     const struct OsalCdevOps *fileOps, uint32_t mode)
564 {
565     int32_t ret;
566     DListHeadInit(&vnodeAdapter->clientList);
567     if (OsalMutexInit(&vnodeAdapter->mutex) != HDF_SUCCESS) {
568         HDF_LOGE("vnode adapter out of mutex");
569         goto ERROR;
570     }
571     vnodeAdapter->cdev = OsalAllocCdev(fileOps);
572     if (vnodeAdapter->cdev == NULL) {
573         HDF_LOGE("fail to alloc osalcdev");
574         OsalMutexDestroy(&vnodeAdapter->mutex);
575         goto ERROR;
576     }
577     ret = OsalRegisterCdev(vnodeAdapter->cdev, vnodeAdapter->vNodePath, mode, vnodeAdapter);
578     if (ret != 0) {
579         HDF_LOGE("failed to register dev node %s, ret is: %d", vnodeAdapter->vNodePath, ret);
580         OsalMutexDestroy(&vnodeAdapter->mutex);
581         goto ERROR;
582     }
583     return &vnodeAdapter->ioService;
584 ERROR:
585     OsalMemFree(vnodeAdapter->vNodePath);
586     OsalMemFree(vnodeAdapter);
587     return NULL;
588 }
589 
HdfIoServiceAdapterPublish(const char * serviceName,uint32_t mode)590 struct HdfIoService *HdfIoServiceAdapterPublish(const char *serviceName, uint32_t mode)
591 {
592     int nodePathLength;
593     struct HdfVNodeAdapter *vnodeAdapter = NULL;
594     static const struct OsalCdevOps fileOps = {
595         .open = HdfVNodeAdapterOpen,
596         .release = HdfVNodeAdapterClose,
597         .ioctl = HdfVNodeAdapterIoctl,
598         .poll = HdfVNodeAdapterPoll,
599     };
600 
601     if ((serviceName == NULL) || (mode > MAX_MODE_SIZE)) {
602         HDF_LOGE("input param is invalid, mode is %x", mode);
603         return NULL;
604     }
605 
606     vnodeAdapter = (struct HdfVNodeAdapter *)OsalMemCalloc(sizeof(struct HdfVNodeAdapter));
607     if (vnodeAdapter == NULL) {
608         HDF_LOGE("alloc remote service is null");
609         return NULL;
610     }
611 
612     nodePathLength = strlen(serviceName) + strlen(DEV_NODE_PATH) + 1;
613     vnodeAdapter->vNodePath = (char *)OsalMemCalloc(nodePathLength);
614     if (vnodeAdapter->vNodePath == NULL) {
615         HDF_LOGE("alloc vnode path is null");
616         OsalMemFree(vnodeAdapter);
617         return NULL;
618     }
619 
620     if (sprintf_s(vnodeAdapter->vNodePath, nodePathLength, "%s%s", DEV_NODE_PATH, serviceName) < 0) {
621         HDF_LOGE("failed to get node path");
622         OsalMemFree(vnodeAdapter->vNodePath);
623         OsalMemFree(vnodeAdapter);
624         return NULL;
625     }
626     return HdfIoServiceAdapterRegCdev(vnodeAdapter, &fileOps, mode);
627 }
628 
HdfIoServiceAdapterRemove(struct HdfIoService * service)629 void HdfIoServiceAdapterRemove(struct HdfIoService *service)
630 {
631     if (service != NULL) {
632         struct HdfVNodeAdapter *vnodeAdapter = (struct HdfVNodeAdapter *)service;
633         if (vnodeAdapter->vNodePath != NULL) {
634             OsalUnregisterCdev(vnodeAdapter->cdev);
635             OsalFreeCdev(vnodeAdapter->cdev);
636             OsalMemFree(vnodeAdapter->vNodePath);
637         }
638         OsalMutexDestroy(&vnodeAdapter->mutex);
639         OsalMemFree(vnodeAdapter);
640     }
641 }
642 
HdfDeviceSendEvent(const struct HdfDeviceObject * deviceObject,uint32_t id,const struct HdfSBuf * data)643 int32_t HdfDeviceSendEvent(const struct HdfDeviceObject *deviceObject, uint32_t id, const struct HdfSBuf *data)
644 {
645     struct HdfDeviceNode *deviceNode = NULL;
646     struct HdfVNodeAdapter *adapter = NULL;
647 
648     if (deviceObject == NULL || data == NULL) {
649         return HDF_ERR_INVALID_PARAM;
650     }
651 
652     deviceNode = CONTAINER_OF(deviceObject, struct HdfDeviceNode, deviceObject);
653     if (deviceNode->policy != SERVICE_POLICY_CAPACITY) {
654         return HDF_ERR_NOT_SUPPORT;
655     }
656 
657     adapter = (struct HdfVNodeAdapter *)(((struct DeviceNodeExt*)deviceNode)->ioService);
658     return HdfVNodeAdapterSendDevEvent(adapter, NULL, id, data);
659 }
660 
HdfDeviceSendEventToClient(const struct HdfDeviceIoClient * client,uint32_t id,const struct HdfSBuf * data)661 int32_t HdfDeviceSendEventToClient(const struct HdfDeviceIoClient *client, uint32_t id, const struct HdfSBuf *data)
662 {
663     struct HdfVNodeAdapterClient *vnodeClient = NULL;
664     if (client == NULL || client->device == NULL) {
665         return HDF_ERR_INVALID_PARAM;
666     }
667 
668     vnodeClient = CONTAINER_OF(client, struct HdfVNodeAdapterClient, ioServiceClient);
669     if (vnodeClient->adapter == NULL) {
670         return HDF_ERR_INVALID_PARAM;
671     }
672 
673     return HdfVNodeAdapterSendDevEvent(vnodeClient->adapter, vnodeClient, id, data);
674 }
675