1 /*
2  * Copyright (c) 2020-2023 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 EVENT_RINGBUFFER_MAX 10
24 #define MAX_RW_SIZE          (1024 * 1204) // 1M
25 
26 enum HdfVNodeClientStatus {
27     VNODE_CLIENT_RUNNING,
28     VNODE_CLIENT_LISTENING,
29     VNODE_CLIENT_STOPPED,
30     VNODE_CLIENT_EXITED,
31 };
32 
33 struct HdfVNodeAdapterClient {
34     struct HdfVNodeAdapter *adapter;
35     struct HdfDeviceIoClient ioServiceClient;
36     wait_queue_head_t pollWait;
37     struct HdfIoService *serv;
38     struct OsalMutex mutex;
39     struct DListHead eventQueue;
40     struct DListHead listNode;
41     int32_t eventQueueSize;
42     int32_t wakeup;
43     uint32_t status;
44     struct HdfDevEvent *eventRingBuffer[EVENT_RINGBUFFER_MAX];
45     volatile uint32_t readCursor;
46     volatile uint32_t writeCursor;
47     volatile bool writeHeadEvent;
48 };
49 
50 struct HdfIoServiceKClient {
51     struct HdfIoService ioService;
52     struct HdfDeviceIoClient client;
53 };
54 
HdfKIoServiceDispatch(struct HdfObject * service,int cmdId,struct HdfSBuf * data,struct HdfSBuf * reply)55 int HdfKIoServiceDispatch(struct HdfObject *service, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
56 {
57     struct HdfIoService *ioService = (struct HdfIoService*)service;
58     struct HdfIoServiceKClient *kClient = NULL;
59 
60     if (ioService == NULL || ioService->dispatcher == NULL) {
61         return HDF_ERR_INVALID_PARAM;
62     }
63 
64     kClient = CONTAINER_OF(ioService, struct HdfIoServiceKClient, ioService);
65     if (kClient->client.device == NULL || kClient->client.device->service == NULL ||
66         kClient->client.device->service->Dispatch == NULL) {
67             return HDF_ERR_INVALID_OBJECT;
68     }
69 
70     return kClient->client.device->service->Dispatch(&kClient->client, cmdId, data, reply);
71 }
72 
HdfHdfIoServiceKClientInstance(struct HdfDeviceObject * deviceObject)73 static struct HdfIoServiceKClient *HdfHdfIoServiceKClientInstance(struct HdfDeviceObject *deviceObject)
74 {
75     static struct HdfIoDispatcher kDispatcher = {
76         .Dispatch = HdfKIoServiceDispatch,
77     };
78 
79     struct HdfIoServiceKClient *client = OsalMemCalloc(sizeof(struct HdfIoServiceKClient));
80     if (client == NULL) {
81         return NULL;
82     }
83 
84     client->client.device = deviceObject;
85     if (deviceObject->service != NULL && deviceObject->service->Open != NULL) {
86         if (deviceObject->service->Open(&client->client) != HDF_SUCCESS) {
87             OsalMemFree(client);
88             return NULL;
89         }
90     }
91 
92     client->ioService.dispatcher = &kDispatcher;
93     return client;
94 }
95 
HdfIoServiceAdapterObtain(const char * serviceName)96 struct HdfIoService *HdfIoServiceAdapterObtain(const char *serviceName)
97 {
98     struct DevSvcManagerClnt *svcMgr = NULL;
99     struct HdfDeviceObject *deviceObject = NULL;
100     struct HdfIoServiceKClient *kClient = NULL;
101 
102     if (serviceName == NULL) {
103         return NULL;
104     }
105 
106     svcMgr = DevSvcManagerClntGetInstance();
107     if (svcMgr == NULL || svcMgr->devSvcMgrIf == NULL) {
108         return NULL;
109     }
110     deviceObject = svcMgr->devSvcMgrIf->GetObject(svcMgr->devSvcMgrIf, serviceName);
111     if (deviceObject == NULL) {
112         return NULL;
113     }
114 
115     kClient = HdfHdfIoServiceKClientInstance(deviceObject);
116     if (kClient == NULL) {
117         return NULL;
118     }
119 
120     return &kClient->ioService;
121 }
122 
HdfIoServiceAdapterRecycle(struct HdfIoService * ioService)123 void HdfIoServiceAdapterRecycle(struct HdfIoService *ioService)
124 {
125     struct HdfIoServiceKClient *kClient = NULL;
126 
127     if (ioService == NULL) {
128         return;
129     }
130 
131     kClient = CONTAINER_OF(ioService, struct HdfIoServiceKClient, ioService);
132     if (kClient->client.device != NULL && kClient->client.device->service != NULL &&
133         kClient->client.device->service->Release != NULL) {
134         kClient->client.device->service->Release(&kClient->client);
135     }
136     OsalMemFree(kClient);
137 }
138 
HdfSbufCopyFromUser(uintptr_t data,size_t size)139 static struct HdfSBuf *HdfSbufCopyFromUser(uintptr_t data, size_t size)
140 {
141     uint8_t *kData = NULL;
142     struct HdfSBuf *sbuf = NULL;
143 
144     if (size == 0) {
145         return HdfSbufObtain(VOID_DATA_SIZE);
146     }
147 
148     kData = OsalMemAlloc(size);
149     if (kData == NULL) {
150         HDF_LOGE("%s:oom", __func__);
151         return NULL;
152     }
153     if (CopyFromUser((void*)kData, (void*)data, size) != 0) {
154         HDF_LOGE("%s:failed to copy from user", __func__);
155         OsalMemFree(kData);
156         return NULL;
157     }
158 
159     sbuf = HdfSbufBind((uintptr_t)kData, size);
160     if (sbuf == NULL) {
161         OsalMemFree(kData);
162     }
163     HdfSbufTransDataOwnership(sbuf);
164 
165     return sbuf;
166 }
167 
HdfSbufCopyToUser(const struct HdfSBuf * sbuf,void * dstUser,size_t dstUserSize)168 static int HdfSbufCopyToUser(const struct HdfSBuf *sbuf, void *dstUser, size_t dstUserSize)
169 {
170     size_t sbufSize = HdfSbufGetDataSize(sbuf);
171     if (sbufSize == 0) {
172         return HDF_SUCCESS;
173     }
174     if (dstUserSize < sbufSize) {
175         HDF_LOGE("%s: readBuffer too small %zu", __func__, sbufSize);
176         return HDF_DEV_ERR_NORANGE;
177     }
178 
179     if (CopyToUser(dstUser, HdfSbufGetData(sbuf), sbufSize) != 0) {
180         HDF_LOGE("%s: failed to copy buff data", __func__);
181         return HDF_ERR_IO;
182     }
183 
184     return HDF_SUCCESS;
185 }
186 
DevEventFree(struct HdfDevEvent * event)187 static void DevEventFree(struct HdfDevEvent *event)
188 {
189     if (event == NULL) {
190         return;
191     }
192     if (event->data != NULL) {
193         HdfSbufRecycle(event->data);
194         event->data = NULL;
195     }
196     OsalMemFree(event);
197 }
198 
HdfVNodeAdapterServCall(const struct HdfVNodeAdapterClient * client,unsigned long arg)199 static int HdfVNodeAdapterServCall(const struct HdfVNodeAdapterClient *client, unsigned long arg)
200 {
201     struct HdfWriteReadBuf bwr;
202     struct HdfWriteReadBuf *bwrUser = (struct HdfWriteReadBuf *)((uintptr_t)arg);
203     struct HdfSBuf *data = NULL;
204     struct HdfSBuf *reply = NULL;
205     int ret;
206 
207     if (client->serv == NULL || client->adapter == NULL ||
208         client->adapter->ioService.dispatcher == NULL ||
209         client->adapter->ioService.dispatcher->Dispatch == NULL) {
210         return HDF_ERR_INVALID_OBJECT;
211     }
212 
213     if (bwrUser == NULL) {
214         return HDF_ERR_INVALID_PARAM;
215     }
216     if (CopyFromUser(&bwr, (void*)bwrUser, sizeof(bwr)) != 0) {
217         HDF_LOGE("copy from user failed");
218         return HDF_FAILURE;
219     }
220     if (bwr.writeSize > MAX_RW_SIZE || bwr.readSize > MAX_RW_SIZE) {
221         return HDF_ERR_INVALID_PARAM;
222     }
223 
224     data = HdfSbufCopyFromUser(bwr.writeBuffer, bwr.writeSize);
225     if (data == NULL) {
226         HDF_LOGE("vnode adapter bind data is null");
227         return HDF_FAILURE;
228     }
229     reply = HdfSbufObtainDefaultSize();
230     if (reply == NULL) {
231         HDF_LOGE("%s: oom", __func__);
232         HdfSbufRecycle(data);
233         return HDF_FAILURE;
234     }
235     (void)HdfSbufWriteUint64(reply, (uintptr_t)&client->ioServiceClient);
236     ret = client->adapter->ioService.dispatcher->Dispatch(client->adapter->ioService.target,
237         bwr.cmdCode, data, reply);
238     if (bwr.readSize != 0 && HdfSbufCopyToUser(reply, (void*)(uintptr_t)bwr.readBuffer, bwr.readSize) != HDF_SUCCESS) {
239         HdfSbufRecycle(data);
240         HdfSbufRecycle(reply);
241         return HDF_ERR_IO;
242     }
243     bwr.readConsumed = HdfSbufGetDataSize(reply);
244     if (CopyToUser(bwrUser, &bwr, sizeof(struct HdfWriteReadBuf)) != 0) {
245         HDF_LOGE("%s: fail to copy bwr", __func__);
246         ret = HDF_FAILURE;
247     }
248 
249     HdfSbufRecycle(data);
250     HdfSbufRecycle(reply);
251     return ret;
252 }
253 
EventDataProcess(struct HdfDevEvent * event,struct HdfWriteReadBuf * bwr,struct HdfWriteReadBuf * bwrUser)254 static int EventDataProcess(struct HdfDevEvent *event, struct HdfWriteReadBuf *bwr, struct HdfWriteReadBuf *bwrUser)
255 {
256     int ret = HDF_SUCCESS;
257     size_t eventSize = HdfSbufGetDataSize(event->data);
258     if (eventSize > bwr->readSize) {
259         bwr->readSize = eventSize;
260         ret = HDF_DEV_ERR_NORANGE;
261     } else {
262         if (HdfSbufCopyToUser(event->data, (void *)(uintptr_t)bwr->readBuffer, bwr->readSize) != HDF_SUCCESS) {
263             return HDF_ERR_IO;
264         }
265         bwr->readConsumed = eventSize;
266         bwr->cmdCode = (int32_t)event->id;
267     }
268     if (CopyToUser(bwrUser, bwr, sizeof(struct HdfWriteReadBuf)) != 0) {
269         HDF_LOGE("%s: failed to copy bwr", __func__);
270         ret = HDF_ERR_IO;
271     }
272 
273     return ret;
274 }
275 
ReadDeviceEventInRingBuffer(struct HdfVNodeAdapterClient * client,struct HdfWriteReadBuf * bwr,struct HdfWriteReadBuf * bwrUser)276 static int ReadDeviceEventInRingBuffer(
277     struct HdfVNodeAdapterClient *client, struct HdfWriteReadBuf *bwr, struct HdfWriteReadBuf *bwrUser)
278 {
279     struct HdfDevEvent *event = NULL;
280     int ret = HDF_SUCCESS;
281     uint32_t cursor;
282 
283     do {
284         event = NULL;
285         if (client->readCursor == client->writeCursor) {
286             break;
287         }
288         if (client->writeHeadEvent == true) {
289             HDF_LOGE("%{public}s: client->writeHeadEvent == true", __func__);
290             break;
291         }
292         cursor = client->readCursor;
293         event = client->eventRingBuffer[cursor];
294     } while (!__sync_bool_compare_and_swap(&(client->readCursor), cursor, (cursor + 1) % EVENT_RINGBUFFER_MAX));
295 
296     if (event == NULL) {
297         HDF_LOGE("%{public}s: eventRingBuffer is empty", __func__);
298         return HDF_DEV_ERR_NODATA;
299     }
300 
301     ret = EventDataProcess(event, bwr, bwrUser);
302     if (ret != HDF_SUCCESS) {
303         if (!__sync_bool_compare_and_swap(&(client->readCursor), (cursor + 1) % EVENT_RINGBUFFER_MAX, cursor)) {
304             HDF_LOGE("%{public}s: EventDataProcess failed and cursor had been changed, drop the event", __func__);
305             DevEventFree(event);
306         }
307         return ret;
308     }
309     DevEventFree(event);
310 
311     return ret;
312 }
313 
ReadDeviceEventInEventQueue(struct HdfVNodeAdapterClient * client,struct HdfWriteReadBuf * bwr,struct HdfWriteReadBuf * bwrUser)314 static int ReadDeviceEventInEventQueue(
315     struct HdfVNodeAdapterClient *client, struct HdfWriteReadBuf *bwr, struct HdfWriteReadBuf *bwrUser)
316 {
317     struct HdfDevEvent *event = NULL;
318     int ret = HDF_SUCCESS;
319 
320     OsalMutexLock(&client->mutex);
321     if (DListIsEmpty(&client->eventQueue)) {
322         OsalMutexUnlock(&client->mutex);
323         HDF_LOGE("%{public}s: eventQueue is empty", __func__);
324         return HDF_DEV_ERR_NODATA;
325     }
326     event = CONTAINER_OF(client->eventQueue.next, struct HdfDevEvent, listNode);
327     ret = EventDataProcess(event, bwr, bwrUser);
328     if (ret != HDF_SUCCESS) {
329         OsalMutexUnlock(&client->mutex);
330         return ret;
331     }
332     DListRemove(&event->listNode);
333     client->eventQueueSize--;
334     OsalMutexUnlock(&client->mutex);
335     DevEventFree(event);
336 
337     return ret;
338 }
339 
HdfVNodeAdapterReadDevEvent(struct HdfVNodeAdapterClient * client,unsigned long arg)340 static int HdfVNodeAdapterReadDevEvent(struct HdfVNodeAdapterClient *client, unsigned long arg)
341 {
342     struct HdfWriteReadBuf bwr;
343     struct HdfWriteReadBuf *bwrUser = (struct HdfWriteReadBuf *)((uintptr_t)arg);
344     int ret = HDF_SUCCESS;
345 
346     if (bwrUser == NULL) {
347         return HDF_ERR_INVALID_PARAM;
348     }
349 
350     if (CopyFromUser(&bwr, (void *)bwrUser, sizeof(bwr)) != 0) {
351         HDF_LOGE("Copy from user failed");
352         return HDF_FAILURE;
353     }
354 
355     if (bwr.readSize > MAX_RW_SIZE) {
356         return HDF_ERR_INVALID_PARAM;
357     }
358 
359     if (!DListIsEmpty(&client->eventQueue)) {
360         ret = ReadDeviceEventInEventQueue(client, &bwr, bwrUser);
361     } else {
362         ret = ReadDeviceEventInRingBuffer(client, &bwr, bwrUser);
363     }
364 
365     return ret;
366 }
367 
HdfVnodeAdapterDropOldEventLocked(struct HdfVNodeAdapterClient * client)368 static void HdfVnodeAdapterDropOldEventLocked(struct HdfVNodeAdapterClient *client)
369 {
370     struct HdfDevEvent *dropEvent = CONTAINER_OF(client->eventQueue.next, struct HdfDevEvent, listNode);
371     if (client->adapter != NULL) {
372         const char *nodePath = client->adapter->vNodePath;
373         HDF_LOGE("dev(%{public}s) event queue full, drop old one", nodePath == NULL ? "unknown" : nodePath);
374     }
375 
376     DListRemove(&dropEvent->listNode);
377     DevEventFree(dropEvent);
378     client->eventQueueSize--;
379 }
380 
VNodeAdapterSendDevEventToClient(struct HdfVNodeAdapterClient * vnodeClient,uint32_t id,const struct HdfSBuf * data)381 static int VNodeAdapterSendDevEventToClient(struct HdfVNodeAdapterClient *vnodeClient,
382     uint32_t id, const struct HdfSBuf *data)
383 {
384     struct HdfDevEvent *event = NULL;
385 
386     OsalMutexLock(&vnodeClient->mutex);
387     if (vnodeClient->status != VNODE_CLIENT_LISTENING) {
388         OsalMutexUnlock(&vnodeClient->mutex);
389         return HDF_SUCCESS;
390     }
391     if (vnodeClient->eventQueueSize >= EVENT_QUEUE_MAX) {
392         HdfVnodeAdapterDropOldEventLocked(vnodeClient);
393     }
394     event = OsalMemAlloc(sizeof(struct HdfDevEvent));
395     if (event == NULL) {
396         OsalMutexUnlock(&vnodeClient->mutex);
397         return HDF_DEV_ERR_NO_MEMORY;
398     }
399     event->id = id;
400     event->data = HdfSbufCopy(data);
401     if (event->data == NULL) {
402         OsalMutexUnlock(&vnodeClient->mutex);
403         HDF_LOGE("%s: sbuf oom", __func__);
404         OsalMemFree(event);
405         return HDF_DEV_ERR_NO_MEMORY;
406     }
407     DListInsertTail(&event->listNode, &vnodeClient->eventQueue);
408     vnodeClient->eventQueueSize++;
409     wake_up_interruptible(&vnodeClient->pollWait);
410     OsalMutexUnlock(&vnodeClient->mutex);
411 
412     return HDF_SUCCESS;
413 }
414 
DropOldEventInRingBuffer(struct HdfVNodeAdapterClient * vnodeClient)415 static void DropOldEventInRingBuffer(struct HdfVNodeAdapterClient *vnodeClient)
416 {
417     struct HdfDevEvent *firstEvent = NULL;
418     uint32_t cursor;
419     char *nodePath = NULL;
420 
421     do {
422         cursor = vnodeClient->readCursor;
423         firstEvent = NULL;
424         if ((vnodeClient->writeCursor + 1) % EVENT_RINGBUFFER_MAX != vnodeClient->readCursor) {
425             break;
426         }
427         firstEvent = vnodeClient->eventRingBuffer[cursor];
428     } while (!__sync_bool_compare_and_swap(&(vnodeClient->readCursor), cursor, (cursor + 1) % EVENT_RINGBUFFER_MAX));
429 
430     if (firstEvent != NULL) {
431         if (vnodeClient->adapter != NULL) {
432             nodePath = vnodeClient->adapter->vNodePath;
433             HDF_LOGE("dev(%{public}s) event ringbuffer full, drop old one", nodePath == NULL ? "unknown" : nodePath);
434         }
435         DevEventFree(firstEvent);
436     }
437 }
438 
AddEventToRingBuffer(struct HdfVNodeAdapterClient * vnodeClient,struct HdfDevEvent * event)439 static void AddEventToRingBuffer(struct HdfVNodeAdapterClient *vnodeClient, struct HdfDevEvent *event)
440 {
441     uint32_t cursor;
442 
443     if (vnodeClient->writeCursor == vnodeClient->readCursor) {
444         vnodeClient->writeHeadEvent = true;
445     }
446     do {
447         cursor = vnodeClient->writeCursor;
448     } while (!__sync_bool_compare_and_swap(&(vnodeClient->writeCursor), cursor, (cursor + 1) % EVENT_RINGBUFFER_MAX));
449 
450     vnodeClient->eventRingBuffer[cursor] = event;
451     vnodeClient->writeHeadEvent = false;
452 }
453 
VNodeAdapterSendDevEventToClientNoLock(struct HdfVNodeAdapterClient * vnodeClient,uint32_t id,const struct HdfSBuf * data)454 static int VNodeAdapterSendDevEventToClientNoLock(
455     struct HdfVNodeAdapterClient *vnodeClient, uint32_t id, const struct HdfSBuf *data)
456 {
457     struct HdfDevEvent *event = NULL;
458 
459     if (vnodeClient->status != VNODE_CLIENT_LISTENING) {
460         return HDF_SUCCESS;
461     }
462     DropOldEventInRingBuffer(vnodeClient);
463 
464     event = OsalMemAlloc(sizeof(struct HdfDevEvent));
465     if (event == NULL) {
466         return HDF_DEV_ERR_NO_MEMORY;
467     }
468     event->id = id;
469     event->data = HdfSbufCopy(data);
470     if (event->data == NULL) {
471         HDF_LOGE("%s: sbuf oom", __func__);
472         OsalMemFree(event);
473         return HDF_DEV_ERR_NO_MEMORY;
474     }
475 
476     AddEventToRingBuffer(vnodeClient, event);
477     wake_up_interruptible(&vnodeClient->pollWait);
478 
479     return HDF_SUCCESS;
480 }
481 
HdfVNodeAdapterSendDevEvent(struct HdfVNodeAdapter * adapter,struct HdfVNodeAdapterClient * vnodeClient,uint32_t id,const struct HdfSBuf * data)482 static int HdfVNodeAdapterSendDevEvent(struct HdfVNodeAdapter *adapter, struct HdfVNodeAdapterClient *vnodeClient,
483     uint32_t id, const struct HdfSBuf *data)
484 {
485     struct HdfVNodeAdapterClient *client = NULL;
486     int ret = HDF_FAILURE;
487 
488     if (adapter == NULL || data == NULL || HdfSbufGetDataSize(data) == 0) {
489         return HDF_ERR_INVALID_PARAM;
490     }
491     OsalMutexLock(&adapter->mutex);
492     DLIST_FOR_EACH_ENTRY(client, &adapter->clientList, struct HdfVNodeAdapterClient, listNode) {
493         if (vnodeClient != NULL && client != vnodeClient) {
494             continue;
495         }
496         ret = VNodeAdapterSendDevEventToClient(client, id, data);
497         if (ret != HDF_SUCCESS) {
498             break;
499         }
500     }
501     OsalMutexUnlock(&adapter->mutex);
502     return ret;
503 }
504 
HdfVNodeAdapterSendDevEventNoLock(const struct HdfVNodeAdapter * adapter,struct HdfVNodeAdapterClient * vnodeClient,uint32_t id,const struct HdfSBuf * data)505 static int HdfVNodeAdapterSendDevEventNoLock(const struct HdfVNodeAdapter *adapter,
506     struct HdfVNodeAdapterClient *vnodeClient, uint32_t id, const struct HdfSBuf *data)
507 {
508     if (adapter == NULL || data == NULL || HdfSbufGetDataSize(data) == 0) {
509         return HDF_ERR_INVALID_PARAM;
510     }
511     if (vnodeClient != NULL) {
512         return VNodeAdapterSendDevEventToClientNoLock(vnodeClient, id, data);
513     }
514 
515     return HDF_FAILURE;
516 }
517 
HdfVNodeAdapterClientStartListening(struct HdfVNodeAdapterClient * client)518 static void HdfVNodeAdapterClientStartListening(struct HdfVNodeAdapterClient *client)
519 {
520     OsalMutexLock(&client->mutex);
521     client->status = VNODE_CLIENT_LISTENING;
522     OsalMutexUnlock(&client->mutex);
523 }
524 
HdfVnodeCleanEventQueue(struct HdfVNodeAdapterClient * client)525 static void HdfVnodeCleanEventQueue(struct HdfVNodeAdapterClient *client)
526 {
527     struct HdfDevEvent *event = NULL;
528     struct HdfDevEvent *eventTemp = NULL;
529     DLIST_FOR_EACH_ENTRY_SAFE(event, eventTemp, &client->eventQueue, struct HdfDevEvent, listNode) {
530         DListRemove(&event->listNode);
531         DevEventFree(event);
532     }
533 }
534 
HdfVNodeAdapterClientStopListening(struct HdfVNodeAdapterClient * client)535 static void HdfVNodeAdapterClientStopListening(struct HdfVNodeAdapterClient *client)
536 {
537     OsalMutexLock(&client->mutex);
538     client->status = VNODE_CLIENT_STOPPED;
539     HdfVnodeCleanEventQueue(client);
540     wake_up_interruptible(&client->pollWait);
541     OsalMutexUnlock(&client->mutex);
542 }
543 
HdfVNodeAdapterClientExitListening(struct HdfVNodeAdapterClient * client)544 static void HdfVNodeAdapterClientExitListening(struct HdfVNodeAdapterClient *client)
545 {
546     OsalMutexLock(&client->mutex);
547     client->status = VNODE_CLIENT_EXITED;
548     HdfVnodeCleanEventQueue(client);
549     wake_up_interruptible(&client->pollWait);
550     OsalMutexUnlock(&client->mutex);
551 }
552 
HdfVNodeAdapterClientWakeup(struct HdfVNodeAdapterClient * client)553 static void HdfVNodeAdapterClientWakeup(struct HdfVNodeAdapterClient *client)
554 {
555     OsalMutexLock(&client->mutex);
556     if (client->status != VNODE_CLIENT_LISTENING) {
557         OsalMutexUnlock(&client->mutex);
558         return;
559     }
560     client->wakeup++;
561     wake_up_interruptible(&client->pollWait);
562     OsalMutexUnlock(&client->mutex);
563 }
564 
HdfVNodeAdapterIoctl(struct file * filep,unsigned int cmd,unsigned long arg)565 static long HdfVNodeAdapterIoctl(struct file *filep,  unsigned int cmd, unsigned long arg)
566 {
567     struct HdfVNodeAdapterClient *client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
568     if (client == NULL) {
569         return HDF_DEV_ERR_NO_DEVICE;
570     }
571     switch (cmd) {
572         case HDF_WRITE_READ:
573             return HdfVNodeAdapterServCall(client, arg);
574         case HDF_READ_DEV_EVENT:
575             return HdfVNodeAdapterReadDevEvent(client, arg);
576         case HDF_LISTEN_EVENT_START:
577             HdfVNodeAdapterClientStartListening(client);
578             break;
579         case HDF_LISTEN_EVENT_STOP:
580             HdfVNodeAdapterClientStopListening(client);
581             break;
582         case HDF_LISTEN_EVENT_WAKEUP:
583             HdfVNodeAdapterClientWakeup(client);
584             break;
585         case HDF_LISTEN_EVENT_EXIT:
586             HdfVNodeAdapterClientExitListening(client);
587             break;
588         default:
589             return HDF_FAILURE;
590     }
591 
592     return HDF_SUCCESS;
593 }
594 
HdfNewVNodeAdapterClient(struct HdfVNodeAdapter * adapter)595 static struct HdfVNodeAdapterClient *HdfNewVNodeAdapterClient(struct HdfVNodeAdapter *adapter)
596 {
597     struct HdfVNodeAdapterClient *client = OsalMemCalloc(sizeof(struct HdfVNodeAdapterClient));
598     if (client == NULL) {
599         HDF_LOGE("%s: oom", __func__);
600         return NULL;
601     }
602     if (OsalMutexInit(&client->mutex) != HDF_SUCCESS) {
603         OsalMemFree(client);
604         HDF_LOGE("%s: no mutex", __func__);
605         return NULL;
606     }
607 
608     DListHeadInit(&client->eventQueue);
609     client->eventQueueSize = 0;
610     client->serv = &adapter->ioService;
611     client->status = VNODE_CLIENT_RUNNING;
612     client->adapter = adapter;
613     client->ioServiceClient.device = (struct HdfDeviceObject *)adapter->ioService.target;
614     client->ioServiceClient.priv = NULL;
615     client->wakeup = 0;
616     client->readCursor = 0;
617     client->writeCursor = 0;
618     client->writeHeadEvent = false;
619     init_waitqueue_head(&client->pollWait);
620     OsalMutexLock(&adapter->mutex);
621     DListInsertTail(&client->listNode, &adapter->clientList);
622     OsalMutexUnlock(&adapter->mutex);
623 
624     return client;
625 }
626 
HdfDestoryVNodeAdapterClient(struct HdfVNodeAdapterClient * client)627 static void HdfDestoryVNodeAdapterClient(struct HdfVNodeAdapterClient *client)
628 {
629     struct HdfDevEvent *event = NULL;
630     struct HdfDevEvent *eventTemp = NULL;
631 
632     client->status = VNODE_CLIENT_STOPPED;
633 
634     OsalMutexLock(&client->adapter->mutex);
635     DListRemove(&client->listNode);
636     OsalMutexUnlock(&client->adapter->mutex);
637 
638     OsalMutexLock(&client->mutex);
639     DLIST_FOR_EACH_ENTRY_SAFE(event, eventTemp, &client->eventQueue, struct HdfDevEvent, listNode) {
640         DListRemove(&event->listNode);
641         DevEventFree(event);
642     }
643     OsalMutexUnlock(&client->mutex);
644     OsalMutexDestroy(&client->mutex);
645     OsalMemFree(client);
646 }
647 
HdfVNodeAdapterOpen(struct OsalCdev * cdev,struct file * filep)648 int HdfVNodeAdapterOpen(struct OsalCdev *cdev, struct file *filep)
649 {
650     struct HdfVNodeAdapter *adapter = (struct HdfVNodeAdapter *)OsalGetCdevPriv(cdev);
651     struct HdfVNodeAdapterClient *client = NULL;
652     int32_t ret;
653 
654     if (adapter == NULL) {
655         HDF_LOGE("Vnode adapter dispatcher is null");
656         return HDF_FAILURE;
657     }
658     client = HdfNewVNodeAdapterClient(adapter);
659     if (client == NULL) {
660         return ETXTBSY;
661     }
662     OsalSetFilePriv(filep, client);
663     if (client->ioServiceClient.device != NULL && client->ioServiceClient.device->service != NULL &&
664         client->ioServiceClient.device->service->Open != NULL) {
665         ret = client->ioServiceClient.device->service->Open(&client->ioServiceClient);
666         if (ret != HDF_SUCCESS) {
667             HdfDestoryVNodeAdapterClient(client);
668             return ret;
669         }
670     }
671 
672     return HDF_SUCCESS;
673 }
674 
HdfVNodeAdapterPoll(struct file * filep,poll_table * wait)675 static unsigned int HdfVNodeAdapterPoll(struct file *filep, poll_table *wait)
676 {
677     unsigned int mask = 0;
678     struct HdfVNodeAdapterClient *client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
679     if (client == NULL) {
680         mask |= POLLERR;
681         return mask;
682     }
683     poll_wait(filep, &client->pollWait, wait);
684     OsalMutexLock(&client->mutex);
685     if (client->status == VNODE_CLIENT_EXITED) {
686         mask |= POLLHUP;
687     } else if (!DListIsEmpty(&client->eventQueue)) {
688         mask |= POLLIN;
689     } else if (client->readCursor != client->writeCursor) {
690         mask |= POLLIN;
691     } else if (client->wakeup > 0) {
692         mask |= POLLIN;
693         client->wakeup--;
694     }
695     OsalMutexUnlock(&client->mutex);
696 
697     return mask;
698 }
699 
HdfVNodeAdapterClose(struct OsalCdev * cdev,struct file * filep)700 static int HdfVNodeAdapterClose(struct OsalCdev *cdev, struct file *filep)
701 {
702     struct HdfVNodeAdapterClient *client = NULL;
703     (void)cdev;
704     client = (struct HdfVNodeAdapterClient *)OsalGetFilePriv(filep);
705     if (client->ioServiceClient.device != NULL && client->ioServiceClient.device->service != NULL &&
706         client->ioServiceClient.device->service->Release != NULL) {
707         client->ioServiceClient.device->service->Release(&client->ioServiceClient);
708     }
709     HdfDestoryVNodeAdapterClient(client);
710     OsalSetFilePriv(filep, NULL);
711     return HDF_SUCCESS;
712 }
713 
HdfIoServiceAdapterRegCdev(struct HdfVNodeAdapter * vnodeAdapter,const struct OsalCdevOps * fileOps,uint32_t mode)714 struct HdfIoService *HdfIoServiceAdapterRegCdev(struct HdfVNodeAdapter *vnodeAdapter,
715     const struct OsalCdevOps *fileOps, uint32_t mode)
716 {
717     int32_t ret;
718     DListHeadInit(&vnodeAdapter->clientList);
719     if (OsalMutexInit(&vnodeAdapter->mutex) != HDF_SUCCESS) {
720         HDF_LOGE("vnode adapter out of mutex");
721         goto ERROR;
722     }
723     vnodeAdapter->cdev = OsalAllocCdev(fileOps);
724     if (vnodeAdapter->cdev == NULL) {
725         HDF_LOGE("fail to alloc osalcdev");
726         OsalMutexDestroy(&vnodeAdapter->mutex);
727         goto ERROR;
728     }
729     ret = OsalRegisterCdev(vnodeAdapter->cdev, vnodeAdapter->vNodePath, mode, vnodeAdapter);
730     if (ret != 0) {
731         HDF_LOGE("failed to register dev node %s, ret is: %d", vnodeAdapter->vNodePath, ret);
732         OsalMutexDestroy(&vnodeAdapter->mutex);
733         goto ERROR;
734     }
735     return &vnodeAdapter->ioService;
736 ERROR:
737     OsalMemFree(vnodeAdapter->vNodePath);
738     OsalMemFree(vnodeAdapter);
739     return NULL;
740 }
741 
HdfIoServiceAdapterPublish(const char * serviceName,uint32_t mode)742 struct HdfIoService *HdfIoServiceAdapterPublish(const char *serviceName, uint32_t mode)
743 {
744     int nodePathLength;
745     struct HdfVNodeAdapter *vnodeAdapter = NULL;
746     static const struct OsalCdevOps fileOps = {
747         .open = HdfVNodeAdapterOpen,
748         .release = HdfVNodeAdapterClose,
749         .ioctl = HdfVNodeAdapterIoctl,
750         .poll = HdfVNodeAdapterPoll,
751     };
752 
753     if ((serviceName == NULL) || (mode > MAX_MODE_SIZE)) {
754         HDF_LOGE("input param is invalid, mode is %x", mode);
755         return NULL;
756     }
757 
758     vnodeAdapter = (struct HdfVNodeAdapter *)OsalMemCalloc(sizeof(struct HdfVNodeAdapter));
759     if (vnodeAdapter == NULL) {
760         HDF_LOGE("alloc remote service is null");
761         return NULL;
762     }
763 
764     nodePathLength = strlen(serviceName) + strlen(DEV_NODE_PATH) + 1;
765     vnodeAdapter->vNodePath = (char *)OsalMemCalloc(nodePathLength);
766     if (vnodeAdapter->vNodePath == NULL) {
767         HDF_LOGE("alloc vnode path is null");
768         OsalMemFree(vnodeAdapter);
769         return NULL;
770     }
771 
772     if (sprintf_s(vnodeAdapter->vNodePath, nodePathLength, "%s%s", DEV_NODE_PATH, serviceName) < 0) {
773         HDF_LOGE("failed to get node path");
774         OsalMemFree(vnodeAdapter->vNodePath);
775         OsalMemFree(vnodeAdapter);
776         return NULL;
777     }
778     return HdfIoServiceAdapterRegCdev(vnodeAdapter, &fileOps, mode);
779 }
780 
HdfIoServiceAdapterRemove(struct HdfIoService * service)781 void HdfIoServiceAdapterRemove(struct HdfIoService *service)
782 {
783     if (service != NULL) {
784         struct HdfVNodeAdapter *vnodeAdapter = (struct HdfVNodeAdapter *)service;
785         if (vnodeAdapter->vNodePath != NULL) {
786             OsalUnregisterCdev(vnodeAdapter->cdev);
787             OsalFreeCdev(vnodeAdapter->cdev);
788             OsalMemFree(vnodeAdapter->vNodePath);
789         }
790         OsalMutexDestroy(&vnodeAdapter->mutex);
791         OsalMemFree(vnodeAdapter);
792     }
793 }
794 
HdfDeviceSendEvent(const struct HdfDeviceObject * deviceObject,uint32_t id,const struct HdfSBuf * data)795 int32_t HdfDeviceSendEvent(const struct HdfDeviceObject *deviceObject, uint32_t id, const struct HdfSBuf *data)
796 {
797     struct HdfDeviceNode *deviceNode = NULL;
798     struct HdfVNodeAdapter *adapter = NULL;
799 
800     if (deviceObject == NULL || data == NULL) {
801         return HDF_ERR_INVALID_PARAM;
802     }
803 
804     deviceNode = CONTAINER_OF(deviceObject, struct HdfDeviceNode, deviceObject);
805     if (deviceNode->policy != SERVICE_POLICY_CAPACITY) {
806         return HDF_ERR_NOT_SUPPORT;
807     }
808 
809     adapter = (struct HdfVNodeAdapter *)(((struct DeviceNodeExt *)deviceNode)->ioService);
810     return HdfVNodeAdapterSendDevEvent(adapter, NULL, id, data);
811 }
812 
HdfDeviceSendEventToClient(const struct HdfDeviceIoClient * client,uint32_t id,const struct HdfSBuf * data)813 int32_t HdfDeviceSendEventToClient(const struct HdfDeviceIoClient *client, uint32_t id, const struct HdfSBuf *data)
814 {
815     struct HdfVNodeAdapterClient *vnodeClient = NULL;
816     if (client == NULL || client->device == NULL) {
817         return HDF_ERR_INVALID_PARAM;
818     }
819 
820     vnodeClient = CONTAINER_OF(client, struct HdfVNodeAdapterClient, ioServiceClient);
821     if (vnodeClient->adapter == NULL) {
822         return HDF_ERR_INVALID_PARAM;
823     }
824 
825     return HdfVNodeAdapterSendDevEventNoLock(vnodeClient->adapter, vnodeClient, id, data);
826 }
827