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