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