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 <errno.h>
10 #include <limits.h>
11 #include <osal_thread.h>
12 #include <osal_time.h>
13 #include <poll.h>
14 #include <securec.h>
15 #include <sys/ioctl.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18
19 #include "hdf_base.h"
20 #include "hdf_log.h"
21 #include "hdf_sbuf.h"
22 #include "osal_mem.h"
23
24 #include "hdf_syscall_adapter.h"
25
26 #define HDF_LOG_TAG hdf_syscall_adapter
27 #define EPOLL_MAX_EVENT_SIZE 4
28 #define HDF_DEFAULT_BWR_READ_SIZE 1024
29 #define EVENT_READ_BUFF_GROWTH_RATE 2
30 #define EVENT_READ_BUFF_MAX (20 * 1024) // 20k
31 #define SYSCALL_INVALID_FD (-1)
32 #define HDF_PFD_GROW_SIZE 4
33 #define TIMEOUT_US 100000 // 100ms
34 #define LOAD_IOSERVICE_WAIT_TIME 10 // ms
35 #define LOAD_IOSERVICE_WAIT_COUNT 20 // ms
36
HaveOnlyOneElement(const struct DListHead * head)37 static bool HaveOnlyOneElement(const struct DListHead *head)
38 {
39 if (head->next != head && head->next->next == head) {
40 return true;
41 }
42
43 return false;
44 }
45
HdfDevEventGrowReadBuffer(struct HdfWriteReadBuf * buffer)46 static int32_t HdfDevEventGrowReadBuffer(struct HdfWriteReadBuf *buffer)
47 {
48 size_t newSize = buffer->readSize;
49
50 if (newSize > EVENT_READ_BUFF_MAX) {
51 HDF_LOGE("%s: report event size out of max limit", __func__);
52 return HDF_DEV_ERR_NORANGE;
53 }
54
55 void *newBuff = OsalMemAlloc(newSize);
56 if (newBuff == NULL) {
57 HDF_LOGE("%s:oom,%d", __func__, (int)newSize);
58 return HDF_DEV_ERR_NO_MEMORY;
59 }
60
61 OsalMemFree((void *)(uintptr_t)buffer->readBuffer);
62 buffer->readBuffer = (uintptr_t)newBuff;
63 return HDF_SUCCESS;
64 }
65
HdfFdToAdapterLocked(const struct HdfDevListenerThread * thread,int32_t fd)66 static struct HdfSyscallAdapter *HdfFdToAdapterLocked(const struct HdfDevListenerThread *thread, int32_t fd)
67 {
68 if (thread->adapter != NULL && thread->adapter->fd == fd) {
69 return thread->adapter;
70 }
71
72 if (thread->adapterListPtr == NULL) {
73 return NULL;
74 }
75
76 struct HdfSyscallAdapter *adapter = NULL;
77 DLIST_FOR_EACH_ENTRY(adapter, thread->adapterListPtr, struct HdfSyscallAdapter, listNode) {
78 if (adapter->fd == fd) {
79 return adapter;
80 }
81 }
82
83 return NULL;
84 }
85
HdfDevEventDispatchLocked(const struct HdfDevListenerThread * thread,struct HdfSyscallAdapter * adapter,const struct HdfWriteReadBuf * bwr)86 static int32_t HdfDevEventDispatchLocked(
87 const struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter, const struct HdfWriteReadBuf *bwr)
88 {
89 struct HdfDevEventlistener *listener = NULL;
90 struct HdfSBuf *sbuf = NULL;
91
92 if (bwr->readConsumed > 0) {
93 sbuf = HdfSbufBind(bwr->readBuffer, bwr->readConsumed);
94 } else {
95 sbuf = HdfSbufObtain(sizeof(int));
96 }
97
98 if (sbuf == NULL) {
99 HDF_LOGE("%s:sbuf oom", __func__);
100 return HDF_DEV_ERR_NO_MEMORY;
101 }
102
103 /* Dispatch events to the service group listener */
104 if (thread->listenerListPtr != NULL) {
105 DLIST_FOR_EACH_ENTRY(listener, thread->listenerListPtr, struct HdfDevEventlistener, listNode) {
106 if (listener->onReceive != NULL) {
107 (void)listener->onReceive(listener, &adapter->super, bwr->cmdCode, sbuf);
108 } else if (listener->callBack != NULL) {
109 (void)listener->callBack(listener->priv, bwr->cmdCode, sbuf);
110 }
111 HdfSbufSetDataSize(sbuf, bwr->readConsumed);
112 }
113 }
114
115 OsalMutexLock(&adapter->mutex);
116 /* Dispatch events to the service (SyscallAdapter) listener */
117 DLIST_FOR_EACH_ENTRY(listener, &adapter->listenerList, struct HdfDevEventlistener, listNode) {
118 if (listener->onReceive != NULL) {
119 (void)listener->onReceive(listener, &adapter->super, bwr->cmdCode, sbuf);
120 } else if (listener->callBack != NULL) {
121 (void)listener->callBack(listener->priv, bwr->cmdCode, sbuf);
122 }
123 HdfSbufSetDataSize(sbuf, bwr->readConsumed);
124 }
125 OsalMutexUnlock(&adapter->mutex);
126
127 HdfSbufRecycle(sbuf);
128 return HDF_SUCCESS;
129 }
130
HdfDevEventReadAndDispatch(struct HdfDevListenerThread * thread,int32_t fd)131 static int32_t HdfDevEventReadAndDispatch(struct HdfDevListenerThread *thread, int32_t fd)
132 {
133 struct HdfWriteReadBuf bwr = {0};
134 int32_t ret = HDF_SUCCESS;
135
136 bwr.readBuffer = (uintptr_t)OsalMemAlloc(HDF_DEFAULT_BWR_READ_SIZE);
137 if (bwr.readBuffer == (uintptr_t)NULL) {
138 HDF_LOGE("%s: oom", __func__);
139 return HDF_DEV_ERR_NO_MEMORY;
140 }
141 bwr.cmdCode = -1;
142 bwr.readConsumed = 0;
143 bwr.readSize = HDF_DEFAULT_BWR_READ_SIZE;
144
145 OsalMutexLock(&thread->mutex);
146
147 struct HdfSyscallAdapter *adapter = HdfFdToAdapterLocked(thread, fd);
148 if (adapter == NULL) {
149 HDF_LOGI("%s: invalid adapter", __func__);
150 OsalMSleep(1); // yield to sync adapter list
151 goto FINISH;
152 }
153
154 while (true) {
155 ret = ioctl(adapter->fd, HDF_READ_DEV_EVENT, &bwr);
156 if (ret == 0) {
157 break;
158 }
159 ret = errno;
160 if (ret == -HDF_DEV_ERR_NORANGE) {
161 if (HdfDevEventGrowReadBuffer(&bwr) == HDF_SUCCESS) {
162 /* read buffer may not enough, grow read buffer and try again--The read buffere is insufficient.
163 Expand the buffer and try again. */
164 continue;
165 }
166 }
167 if (ret == -HDF_DEV_ERR_NODATA) {
168 ret = HDF_SUCCESS;
169 } else {
170 HDF_LOGE("%s:ioctl failed, errno=%d", __func__, ret);
171 }
172
173 goto FINISH;
174 }
175
176 ret = HdfDevEventDispatchLocked(thread, adapter, &bwr);
177
178 FINISH:
179 OsalMemFree((void *)(uintptr_t)bwr.readBuffer);
180 OsalMutexUnlock(&thread->mutex);
181 return ret;
182 }
183
AssignPfds(struct HdfDevListenerThread * thread,struct pollfd ** pfds,uint16_t * pfdSize)184 static int32_t AssignPfds(struct HdfDevListenerThread *thread, struct pollfd **pfds, uint16_t *pfdSize)
185 {
186 struct pollfd *pfdPtr = *pfds;
187 uint16_t pfdCount = 0;
188
189 OsalMutexLock(&thread->mutex);
190 if (*pfdSize < thread->pfdSize) {
191 pfdPtr = OsalMemAlloc(sizeof(struct pollfd) * thread->pfdSize);
192 if (pfdPtr == NULL) {
193 HDF_LOGE("%s: oom", __func__);
194 OsalMutexUnlock(&thread->mutex);
195 return HDF_ERR_MALLOC_FAIL;
196 }
197
198 *pfdSize = thread->pfdSize;
199 OsalMemFree(*pfds);
200 *pfds = pfdPtr;
201 }
202
203 for (uint32_t i = 0; i < thread->pfdSize; i++) {
204 if (thread->pfds[i].fd != SYSCALL_INVALID_FD) {
205 pfdPtr[pfdCount].fd = thread->pfds[i].fd;
206 pfdPtr[pfdCount].events = thread->pfds[i].events;
207 pfdPtr[pfdCount].revents = 0;
208 pfdCount++;
209 }
210 }
211
212 thread->pollChanged = false;
213 OsalMutexUnlock(&thread->mutex);
214 return pfdCount;
215 }
216
217 #define POLL_WAIT_TIME_MS 100
HdfDevEventListenTask(void * para)218 static int32_t HdfDevEventListenTask(void *para)
219 {
220 struct HdfDevListenerThread *thread = (struct HdfDevListenerThread *)para;
221 struct pollfd *pfds = NULL;
222 uint16_t pfdSize = 0;
223 int32_t pollCount = 0;
224
225 thread->status = LISTENER_RUNNING;
226 while (!thread->shouldStop) {
227 if (thread->pollChanged) {
228 pollCount = AssignPfds(thread, &pfds, &pfdSize);
229 }
230 if (pollCount <= 0) {
231 goto EXIT;
232 }
233 int32_t pollSize = poll(pfds, pollCount, -1);
234 if (pollSize <= 0) {
235 HDF_LOGE("%s: poll fail (%d)%s", __func__, errno, strerror(errno));
236 OsalMSleep(POLL_WAIT_TIME_MS);
237 continue;
238 }
239 for (uint32_t i = 0; i < (uint32_t)pollCount; i++) {
240 if (pfds[i].fd == SYSCALL_INVALID_FD) {
241 continue;
242 }
243 if ((((uint32_t)pfds[i].revents) & POLLIN) &&
244 HdfDevEventReadAndDispatch(thread, pfds[i].fd) != HDF_SUCCESS) {
245 goto EXIT;
246 } else if (((uint32_t)pfds[i].revents) & POLLHUP) {
247 HDF_LOGI("event listener task received exit event");
248 goto EXIT;
249 } else if (((uint32_t)pfds[i].revents) & POLLNVAL) {
250 OsalMSleep(1); // polled closed fd, yield to sync
251 }
252 }
253 }
254
255 EXIT:
256 HDF_LOGI("event listener task exit");
257
258 thread->status = LISTENER_EXITED;
259 OsalMemFree(pfds);
260
261 if (thread->shouldStop) {
262 /* Exit due to async call and free the thread struct. */
263 OsalMutexDestroy(&thread->mutex);
264 OsalThreadDestroy(&thread->thread);
265 OsalMemFree(thread->pfds);
266 OsalMemFree(thread);
267 }
268
269 return HDF_SUCCESS;
270 }
271
HdfAdapterStartListenIoctl(int fd)272 static int32_t HdfAdapterStartListenIoctl(int fd)
273 {
274 int32_t ret = ioctl(fd, HDF_LISTEN_EVENT_START, 0);
275 if (ret) {
276 HDF_LOGE("%s: failed to notify drv(%d) of start %d %{public}s", __func__, fd, errno, strerror(errno));
277 return HDF_ERR_IO;
278 }
279
280 return HDF_SUCCESS;
281 }
282
HdfAdapterStopListenIoctl(int fd)283 static int32_t HdfAdapterStopListenIoctl(int fd)
284 {
285 int32_t ret = ioctl(fd, HDF_LISTEN_EVENT_STOP, 0);
286 if (ret) {
287 HDF_LOGE("%s: failed to notify drv(%d) of stop %d %{public}s", __func__, fd, errno, strerror(errno));
288 return HDF_ERR_IO;
289 }
290
291 return HDF_SUCCESS;
292 }
293
HdfAdapterExitListenIoctl(int fd)294 static int32_t HdfAdapterExitListenIoctl(int fd)
295 {
296 int32_t ret = ioctl(fd, HDF_LISTEN_EVENT_EXIT, 0);
297 if (ret) {
298 HDF_LOGE("%s: failed to notify drv(%d) of exit %d %{public}s", __func__, fd, errno, strerror(errno));
299 return HDF_ERR_IO;
300 }
301 HDF_LOGD("ioctl send poll thread(%d) exit event, ret=%d", fd, ret);
302 return HDF_SUCCESS;
303 }
304
HdfDevListenerThreadDoInit(struct HdfDevListenerThread * thread)305 static int32_t HdfDevListenerThreadDoInit(struct HdfDevListenerThread *thread)
306 {
307 if (OsalMutexInit(&thread->mutex) != HDF_SUCCESS) {
308 HDF_LOGE("%s: failed to create thread lock", __func__);
309 return HDF_FAILURE;
310 }
311
312 int32_t ret = OsalThreadCreate(&thread->thread, HdfDevEventListenTask, thread);
313 if (ret != HDF_SUCCESS) {
314 HDF_LOGE("%s: failed to create thread", __func__);
315 thread->status = LISTENER_UNINITED;
316 OsalMutexDestroy(&thread->mutex);
317 return HDF_ERR_THREAD_CREATE_FAIL;
318 }
319
320 thread->status = LISTENER_INITED;
321 thread->shouldStop = false;
322 thread->pollChanged = true;
323
324 return HDF_SUCCESS;
325 }
326
HdfDevListenerThreadInit(struct HdfDevListenerThread * thread)327 static int32_t HdfDevListenerThreadInit(struct HdfDevListenerThread *thread)
328 {
329 switch (thread->status) {
330 case LISTENER_STARTED: // fall-through
331 case LISTENER_RUNNING: // fall-through
332 case LISTENER_INITED: // fall-through
333 case LISTENER_WAITING:
334 return HDF_SUCCESS;
335 case LISTENER_EXITED:
336 thread->status = LISTENER_INITED;
337 thread->shouldStop = false;
338 return HDF_SUCCESS;
339 case LISTENER_UNINITED:
340 return HdfDevListenerThreadDoInit(thread);
341 default:
342 break;
343 }
344
345 return HDF_FAILURE;
346 }
347
GetValidPfdIndexLocked(struct HdfDevListenerThread * thread,struct HdfSyscallAdapter * adapter)348 static int32_t GetValidPfdIndexLocked(struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter)
349 {
350 uint32_t index = 0;
351 struct pollfd *pfds = thread->pfds;
352 for (; index < thread->pfdSize; index++) {
353 if (pfds[index].fd == SYSCALL_INVALID_FD) {
354 break;
355 }
356
357 if (pfds[index].fd == adapter->fd) {
358 return index;
359 }
360 }
361
362 if (index >= thread->pfdSize) {
363 uint32_t newSize = thread->pfdSize + HDF_PFD_GROW_SIZE;
364 struct pollfd *newPfds = OsalMemCalloc(sizeof(struct pollfd) * newSize);
365 if (newPfds == NULL) {
366 return HDF_ERR_MALLOC_FAIL;
367 }
368 if (thread->pfdSize != 0) {
369 (void)memcpy_s(
370 newPfds, sizeof(struct pollfd) * newSize, thread->pfds, sizeof(struct pollfd) * thread->pfdSize);
371 }
372
373 for (uint32_t i = index; i < newSize; i++) {
374 newPfds[i].fd = SYSCALL_INVALID_FD;
375 }
376
377 OsalMemFree(thread->pfds);
378 thread->pfds = newPfds;
379 thread->pfdSize = newSize;
380 }
381
382 return index;
383 }
384
HdfAddAdapterToPfds(struct HdfDevListenerThread * thread,struct HdfSyscallAdapter * adapter)385 static int32_t HdfAddAdapterToPfds(struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter)
386 {
387 int32_t index = GetValidPfdIndexLocked(thread, adapter);
388 if (index < 0) {
389 return HDF_ERR_MALLOC_FAIL;
390 }
391
392 thread->pfds[index].fd = adapter->fd;
393 thread->pfds[index].events = POLLIN;
394 thread->pfds[index].revents = 0;
395
396 return HDF_SUCCESS;
397 }
398
HdfListenThreadInitPollFds(struct HdfDevListenerThread * thread)399 static int32_t HdfListenThreadInitPollFds(struct HdfDevListenerThread *thread)
400 {
401 struct HdfSyscallAdapter *adapter = NULL;
402 if (thread->adapterListPtr != NULL) {
403 DLIST_FOR_EACH_ENTRY(adapter, thread->adapterListPtr, struct HdfSyscallAdapter, listNode) {
404 if (HdfAddAdapterToPfds(thread, adapter) != HDF_SUCCESS) {
405 return HDF_ERR_MALLOC_FAIL;
406 }
407 }
408 }
409
410 if (thread->adapter != NULL) {
411 return HdfAddAdapterToPfds(thread, thread->adapter);
412 }
413
414 return HDF_SUCCESS;
415 }
416
HdfDevListenerThreadStart(struct HdfDevListenerThread * thread)417 static int32_t HdfDevListenerThreadStart(struct HdfDevListenerThread *thread)
418 {
419 if (thread->status >= LISTENER_STARTED) {
420 return HDF_SUCCESS;
421 }
422
423 if (thread->status != LISTENER_INITED) {
424 return HDF_ERR_INVALID_PARAM;
425 }
426
427 int32_t ret = HdfListenThreadInitPollFds(thread);
428 if (ret != HDF_SUCCESS || thread->pfdSize <= 0) {
429 HDF_LOGE("%s:invalid poll list", __func__);
430 return HDF_DEV_ERR_NO_DEVICE;
431 }
432
433 do {
434 for (uint16_t i = 0; i < thread->pfdSize; i++) {
435 if (thread->pfds[i].fd == SYSCALL_INVALID_FD) {
436 continue;
437 }
438 if (HdfAdapterStartListenIoctl(thread->pfds[i].fd)) {
439 return HDF_ERR_IO;
440 }
441 }
442
443 struct OsalThreadParam config = {
444 .name = "hdf_event_listener",
445 .priority = OSAL_THREAD_PRI_DEFAULT,
446 .stackSize = 0,
447 };
448
449 thread->status = LISTENER_STARTED;
450 if (OsalThreadStart(&thread->thread, &config) != HDF_SUCCESS) {
451 HDF_LOGE("%s:OsalThreadStart failed", __func__);
452 ret = HDF_FAILURE;
453 break;
454 }
455 return HDF_SUCCESS;
456 } while (0);
457
458 return ret;
459 }
460
HdfDevListenerThreadObtain(void)461 static struct HdfDevListenerThread *HdfDevListenerThreadObtain(void)
462 {
463 struct HdfDevListenerThread *thread = OsalMemCalloc(sizeof(struct HdfDevListenerThread));
464 if (thread == NULL) {
465 return NULL;
466 }
467 thread->status = LISTENER_UNINITED;
468 if (HdfDevListenerThreadInit(thread) != HDF_SUCCESS) {
469 OsalMemFree(thread);
470 return NULL;
471 }
472 return thread;
473 }
474
HdfIoServiceGroupThreadInit(struct HdfSyscallAdapterGroup * group)475 static int32_t HdfIoServiceGroupThreadInit(struct HdfSyscallAdapterGroup *group)
476 {
477 if (group->thread == NULL) {
478 struct HdfDevListenerThread *listenerThread = HdfDevListenerThreadObtain();
479 if (listenerThread == NULL) {
480 return HDF_ERR_THREAD_CREATE_FAIL;
481 }
482 group->thread = listenerThread;
483 }
484 group->thread->adapterListPtr = &group->adapterList;
485 group->thread->listenerListPtr = &group->listenerList;
486 return HdfDevListenerThreadInit(group->thread);
487 }
488
HdfIoServiceGroupThreadStart(struct HdfSyscallAdapterGroup * group)489 static int32_t HdfIoServiceGroupThreadStart(struct HdfSyscallAdapterGroup *group)
490 {
491 OsalMutexLock(&group->mutex);
492 if (HdfIoServiceGroupThreadInit(group) != HDF_SUCCESS) {
493 OsalMutexUnlock(&group->mutex);
494 return HDF_FAILURE;
495 }
496 int32_t ret = HdfDevListenerThreadStart(group->thread);
497 OsalMutexUnlock(&group->mutex);
498 return ret;
499 }
500
HdfListenThreadPollAdd(struct HdfDevListenerThread * thread,struct HdfSyscallAdapter * adapter)501 static int32_t HdfListenThreadPollAdd(struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter)
502 {
503 /* If thread is not bound to a service group, you do not need to add a poll. */
504 if (thread->adapterListPtr == NULL) {
505 return HDF_SUCCESS;
506 }
507
508 OsalMutexLock(&thread->mutex);
509 struct HdfSyscallAdapter *headAdapter = DListIsEmpty(thread->adapterListPtr) ?
510 NULL :
511 DLIST_FIRST_ENTRY(thread->adapterListPtr, struct HdfSyscallAdapter, listNode);
512
513 DListInsertTail(&adapter->listNode, thread->adapterListPtr);
514
515 if (thread->status < LISTENER_STARTED) {
516 OsalMutexUnlock(&thread->mutex);
517 return HDF_SUCCESS;
518 }
519
520 int32_t ret = HDF_SUCCESS;
521 do {
522 int32_t index = GetValidPfdIndexLocked(thread, adapter);
523 if (index < 0) {
524 ret = HDF_ERR_MALLOC_FAIL;
525 break;
526 }
527
528 thread->pfds[index].fd = adapter->fd;
529 thread->pfds[index].events = POLLIN;
530 thread->pfds[index].revents = 0;
531
532 if (headAdapter != NULL) {
533 if (ioctl(headAdapter->fd, HDF_LISTEN_EVENT_WAKEUP, 0) != 0) {
534 HDF_LOGE("%s: failed to wakeup drv to add poll %d %{public}s", __func__, errno, strerror(errno));
535 thread->pfds[index].fd = SYSCALL_INVALID_FD;
536 ret = HDF_ERR_IO;
537 break;
538 }
539 }
540
541 if (HdfAdapterStartListenIoctl(adapter->fd) != HDF_SUCCESS) {
542 thread->pfds[index].fd = SYSCALL_INVALID_FD;
543 ret = HDF_DEV_ERR_OP;
544 break;
545 }
546 thread->pollChanged = true;
547 OsalMutexUnlock(&thread->mutex);
548 return ret;
549 } while (false);
550
551 DListRemove(&adapter->listNode);
552 OsalMutexUnlock(&thread->mutex);
553 return ret;
554 }
555
HdfListenThreadPollDel(struct HdfDevListenerThread * thread,struct HdfSyscallAdapter * adapter)556 static void HdfListenThreadPollDel(struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter)
557 {
558 if (thread == NULL) {
559 DListRemove(&adapter->listNode);
560 adapter->group = NULL;
561 return;
562 }
563 OsalMutexLock(&thread->mutex);
564 struct pollfd *pfds = thread->pfds;
565 for (uint32_t index = 0; index < thread->pfdSize; index++) {
566 if (pfds[index].fd == adapter->fd) {
567 pfds[index].fd = SYSCALL_INVALID_FD;
568 break;
569 }
570 }
571
572 HdfAdapterStopListenIoctl(adapter->fd);
573 if (ioctl(adapter->fd, HDF_LISTEN_EVENT_WAKEUP, 0) != 0) {
574 HDF_LOGE("%s: failed to wakeup drv to del poll %d %s", __func__, errno, strerror(errno));
575 }
576 DListRemove(&adapter->listNode);
577 adapter->group = NULL;
578 thread->pollChanged = true;
579 OsalMutexUnlock(&thread->mutex);
580 }
581
HdfDevListenerThreadFree(struct HdfDevListenerThread * thread)582 static void HdfDevListenerThreadFree(struct HdfDevListenerThread *thread)
583 {
584 OsalMutexDestroy(&thread->mutex);
585 OsalMemFree(thread->pfds);
586 OsalThreadDestroy(&thread->thread);
587 OsalMemFree(thread);
588 }
589
HdfDevListenerThreadDestroy(struct HdfDevListenerThread * thread)590 static void HdfDevListenerThreadDestroy(struct HdfDevListenerThread *thread)
591 {
592 if (thread == NULL) {
593 return;
594 }
595
596 switch (thread->status) {
597 case LISTENER_RUNNING: {
598 int count = 0;
599 uint32_t stopCount = 0;
600 OsalMutexLock(&thread->mutex);
601 thread->adapter = NULL;
602 thread->adapterListPtr = NULL;
603 thread->listenerListPtr = NULL;
604 OsalMutexUnlock(&thread->mutex);
605 for (uint16_t i = 0; i < thread->pfdSize; i++) {
606 if (thread->pfds[i].fd != SYSCALL_INVALID_FD &&
607 HdfAdapterExitListenIoctl(thread->pfds[i].fd) == HDF_SUCCESS) {
608 stopCount++;
609 }
610 thread->pfds[i].fd = SYSCALL_INVALID_FD;
611 }
612
613 if (stopCount == 0) {
614 thread->shouldStop = true;
615 HDF_LOGE("%s:failed to exit listener thread with ioctl, will go async way", __func__);
616 return;
617 }
618 while (thread->status != LISTENER_EXITED && count <= TIMEOUT_US) {
619 OsalUSleep(1);
620 count++;
621 }
622 if (thread->status == LISTENER_EXITED) {
623 HDF_LOGI("poll thread exited");
624 HdfDevListenerThreadFree(thread);
625 } else {
626 thread->shouldStop = true;
627 HDF_LOGE("wait poll thread exit timeout, async exit");
628 }
629 return;
630 }
631 case LISTENER_STARTED:
632 thread->shouldStop = true;
633 break;
634 case LISTENER_EXITED: // fall-through
635 case LISTENER_INITED:
636 HdfDevListenerThreadFree(thread);
637 break;
638 default:
639 break;
640 }
641 }
642
HdfSyscallAdapterDispatch(struct HdfObject * object,int32_t code,struct HdfSBuf * data,struct HdfSBuf * reply)643 static int32_t HdfSyscallAdapterDispatch(
644 struct HdfObject *object, int32_t code, struct HdfSBuf *data, struct HdfSBuf *reply)
645 {
646 if (object == NULL) {
647 HDF_LOGE("Input object is null");
648 return HDF_FAILURE;
649 }
650 struct HdfSyscallAdapter *ioService = (struct HdfSyscallAdapter *)object;
651 struct HdfWriteReadBuf wrBuf;
652 if (reply != NULL) {
653 wrBuf.readBuffer = (uintptr_t)HdfSbufGetData(reply);
654 wrBuf.readSize = HdfSbufGetCapacity(reply);
655 } else {
656 wrBuf.readBuffer = 0;
657 wrBuf.readSize = 0;
658 }
659 if (data != NULL) {
660 wrBuf.writeBuffer = (uintptr_t)HdfSbufGetData(data);
661 wrBuf.writeSize = HdfSbufGetDataSize(data);
662 } else {
663 wrBuf.writeBuffer = 0;
664 wrBuf.writeSize = 0;
665 }
666
667 wrBuf.readConsumed = 0;
668 wrBuf.writeConsumed = 0;
669 wrBuf.cmdCode = code;
670 int32_t ret = ioctl(ioService->fd, HDF_WRITE_READ, &wrBuf);
671 if (ret < 0) {
672 HDF_LOGE("Failed to dispatch serv call ioctl %{public}d", -errno);
673 ret = -errno;
674 }
675 if (reply != NULL) {
676 HdfSbufSetDataSize(reply, wrBuf.readConsumed);
677 }
678 return ret;
679 }
680
TrytoLoadIoService(const char * serviceName,char * devNodePath,char * realPath)681 static int TrytoLoadIoService(const char *serviceName, char *devNodePath, char *realPath)
682 {
683 if (HdfLoadDriverByServiceName(serviceName) != HDF_SUCCESS) {
684 HDF_LOGE("%s: load %{public}s driver failed", __func__, serviceName);
685 return HDF_DEV_ERR_NO_DEVICE;
686 }
687
688 int waitCount = LOAD_IOSERVICE_WAIT_COUNT;
689 while (realpath(devNodePath, realPath) == NULL && waitCount-- > 0) {
690 OsalMSleep(LOAD_IOSERVICE_WAIT_TIME); // wait ueventd to crater dev
691 }
692 if (waitCount <= 0) {
693 HDF_LOGE("%s: char dev %{public}s is invalid", __func__, devNodePath);
694 return HDF_DEV_ERR_NO_DEVICE_SERVICE;
695 }
696
697 return HDF_SUCCESS;
698 }
699
HdfIoServiceAdapterObtain(const char * serviceName)700 struct HdfIoService *HdfIoServiceAdapterObtain(const char *serviceName)
701 {
702 struct HdfSyscallAdapter *adapter = NULL;
703 struct HdfIoService *ioService = NULL;
704 char *devNodePath = NULL;
705 char *realPath = NULL;
706
707 const char *devPath = DEV_NODE_PATH;
708 if (access(DEV_NODE_PATH, F_OK) != 0) {
709 devPath = DEV_PATH;
710 }
711
712 devNodePath = OsalMemCalloc(PATH_MAX);
713 realPath = OsalMemCalloc(PATH_MAX);
714 if (devNodePath == NULL || realPath == NULL) {
715 HDF_LOGE("%s: out of memory", __func__);
716 goto OUT;
717 }
718
719 if (sprintf_s(devNodePath, PATH_MAX - 1, "%s%s", devPath, serviceName) < 0) {
720 HDF_LOGE("Failed to get the node path");
721 goto OUT;
722 }
723
724 if (realpath(devNodePath, realPath) == NULL &&
725 TrytoLoadIoService(serviceName, devNodePath, realPath) != HDF_SUCCESS) {
726 goto OUT;
727 }
728
729 adapter = (struct HdfSyscallAdapter *)OsalMemCalloc(sizeof(struct HdfSyscallAdapter));
730 if (adapter == NULL) {
731 HDF_LOGE("Failed to allocate SyscallAdapter");
732 goto OUT;
733 }
734
735 DListHeadInit(&adapter->listenerList);
736 if (OsalMutexInit(&adapter->mutex)) {
737 HDF_LOGE("%s: Failed to create mutex", __func__);
738 OsalMemFree(adapter);
739 goto OUT;
740 }
741
742 adapter->fd = open(realPath, O_RDWR);
743 if (adapter->fd < 0) {
744 HDF_LOGE("Open file node %{public}s failed, (%d)%{public}s", realPath, errno, strerror(errno));
745 OsalMutexDestroy(&adapter->mutex);
746 OsalMemFree(adapter);
747 goto OUT;
748 }
749 ioService = &adapter->super;
750 static struct HdfIoDispatcher dispatch = {
751 .Dispatch = HdfSyscallAdapterDispatch,
752 };
753 ioService->dispatcher = &dispatch;
754 OUT:
755 OsalMemFree(devNodePath);
756 OsalMemFree(realPath);
757 return ioService;
758 }
759
HdfIoServiceAdapterRecycle(struct HdfIoService * service)760 void HdfIoServiceAdapterRecycle(struct HdfIoService *service)
761 {
762 struct HdfSyscallAdapter *adapter = (struct HdfSyscallAdapter *)service;
763 if (adapter != NULL) {
764 HdfDevListenerThreadDestroy(adapter->thread);
765 adapter->thread = NULL;
766 if (adapter->fd >= 0) {
767 close(adapter->fd);
768 adapter->fd = -1;
769 }
770 OsalMutexDestroy(&adapter->mutex);
771 OsalMemFree(adapter);
772 }
773 }
774
HdfIoServiceThreadBindLocked(struct HdfSyscallAdapter * adapter)775 static int32_t HdfIoServiceThreadBindLocked(struct HdfSyscallAdapter *adapter)
776 {
777 if (adapter->thread == NULL) {
778 struct HdfDevListenerThread *listenerthread = HdfDevListenerThreadObtain();
779 if (listenerthread == NULL) {
780 return HDF_ERR_THREAD_CREATE_FAIL;
781 }
782 adapter->thread = listenerthread;
783 }
784 adapter->thread->adapter = adapter;
785 return HdfDevListenerThreadInit(adapter->thread);
786 }
787
HdfIoServiceStartListen(struct HdfSyscallAdapter * adapter)788 static int32_t HdfIoServiceStartListen(struct HdfSyscallAdapter *adapter)
789 {
790 if (HdfIoServiceThreadBindLocked(adapter) != HDF_SUCCESS) {
791 HDF_LOGE("%s: Failed to bind a thread to SyscallAdapter", __func__);
792 return HDF_FAILURE;
793 }
794
795 return HdfDevListenerThreadStart(adapter->thread);
796 }
797
AddListenerToAdapterLocked(struct HdfSyscallAdapter * adapter,struct HdfDevEventlistener * listener)798 static bool AddListenerToAdapterLocked(struct HdfSyscallAdapter *adapter, struct HdfDevEventlistener *listener)
799 {
800 struct HdfDevEventlistener *it = NULL;
801 DLIST_FOR_EACH_ENTRY(it, &adapter->listenerList, struct HdfDevEventlistener, listNode) {
802 if (it == listener) {
803 HDF_LOGE("Add a listener for duplicate dev-event");
804 return false;
805 }
806 }
807 DListInsertTail(&listener->listNode, &adapter->listenerList);
808 return true;
809 }
810
HdfDeviceRegisterEventListener(struct HdfIoService * target,struct HdfDevEventlistener * listener)811 int32_t HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener)
812 {
813 if (target == NULL || listener == NULL) {
814 return HDF_ERR_INVALID_PARAM;
815 }
816
817 if (listener->callBack == NULL && listener->onReceive == NULL) {
818 HDF_LOGE("Listener onReceive func not implemented");
819 return HDF_ERR_INVALID_OBJECT;
820 }
821
822 struct HdfSyscallAdapter *adapter = CONTAINER_OF(target, struct HdfSyscallAdapter, super);
823 int32_t ret = HDF_SUCCESS;
824
825 OsalMutexLock(&adapter->mutex);
826 if (!AddListenerToAdapterLocked(adapter, listener)) {
827 OsalMutexUnlock(&adapter->mutex);
828 return HDF_ERR_INVALID_PARAM;
829 }
830
831 if (adapter->group != NULL) {
832 /* Do not bind any service in a service goup to its own thread or start the group thread. */
833 ret = HdfIoServiceGroupThreadStart(adapter->group);
834 OsalMutexUnlock(&adapter->mutex);
835 return ret;
836 }
837
838 if (HdfIoServiceStartListen(adapter) != HDF_SUCCESS) {
839 DListRemove(&listener->listNode);
840 ret = HDF_FAILURE;
841 }
842
843 OsalMutexUnlock(&adapter->mutex);
844 return ret;
845 }
846
HdfDeviceUnregisterEventListener(struct HdfIoService * target,struct HdfDevEventlistener * listener)847 int32_t HdfDeviceUnregisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener)
848 {
849 if (target == NULL || listener == NULL) {
850 return HDF_ERR_INVALID_PARAM;
851 }
852
853 if (listener->listNode.next == NULL || listener->listNode.prev == NULL) {
854 HDF_LOGE("%s: broken listener, may double unregister", __func__);
855 return HDF_ERR_INVALID_OBJECT;
856 }
857
858 struct HdfSyscallAdapter *adapter = (struct HdfSyscallAdapter *)target;
859 OsalMutexLock(&adapter->mutex);
860
861 DListRemove(&listener->listNode);
862
863 if (DListIsEmpty(&adapter->listenerList)) {
864 HdfDevListenerThreadDestroy(adapter->thread);
865 adapter->thread = NULL;
866 }
867 OsalMutexUnlock(&adapter->mutex);
868
869 return HDF_SUCCESS;
870 }
871
HdfIoServiceGroupObtain(void)872 struct HdfIoServiceGroup *HdfIoServiceGroupObtain(void)
873 {
874 struct HdfSyscallAdapterGroup *adapterGroup = OsalMemCalloc(sizeof(struct HdfSyscallAdapterGroup));
875 if (adapterGroup == NULL) {
876 return NULL;
877 }
878
879 if (OsalMutexInit(&adapterGroup->mutex)) {
880 OsalMemFree(adapterGroup);
881 return NULL;
882 }
883 DListHeadInit(&adapterGroup->adapterList);
884 DListHeadInit(&adapterGroup->listenerList);
885 return &adapterGroup->serviceGroup;
886 }
887
HdfIoServiceGroupRecycle(struct HdfIoServiceGroup * group)888 void HdfIoServiceGroupRecycle(struct HdfIoServiceGroup *group)
889 {
890 if (group == NULL) {
891 return;
892 }
893
894 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
895 OsalMutexLock(&adapterGroup->mutex);
896
897 HdfDevListenerThreadDestroy(adapterGroup->thread);
898 adapterGroup->thread = NULL;
899
900 struct HdfSyscallAdapter *adapter = NULL;
901 struct HdfSyscallAdapter *tmp = NULL;
902 DLIST_FOR_EACH_ENTRY_SAFE(adapter, tmp, &adapterGroup->adapterList, struct HdfSyscallAdapter, listNode) {
903 DListRemove(&adapter->listNode);
904 adapter->group = NULL;
905 }
906
907 OsalMutexUnlock(&adapterGroup->mutex);
908
909 OsalMutexDestroy(&adapterGroup->mutex);
910 OsalMemFree(adapterGroup);
911 }
912
HdfIoServiceGroupRegisterListener(struct HdfIoServiceGroup * group,struct HdfDevEventlistener * listener)913 int32_t HdfIoServiceGroupRegisterListener(struct HdfIoServiceGroup *group, struct HdfDevEventlistener *listener)
914 {
915 if (group == NULL || listener == NULL) {
916 return HDF_ERR_INVALID_PARAM;
917 }
918
919 if (listener->callBack == NULL && listener->onReceive == NULL) {
920 HDF_LOGE("Listener onReceive func not implemented");
921 return HDF_ERR_INVALID_OBJECT;
922 }
923 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
924
925 OsalMutexLock(&adapterGroup->mutex);
926 if (HdfIoServiceGroupThreadInit(adapterGroup) != HDF_SUCCESS) {
927 HDF_LOGE("%s:failed to bind listener thread for service group", __func__);
928 OsalMutexUnlock(&adapterGroup->mutex);
929 return HDF_FAILURE;
930 }
931
932 int32_t ret = HDF_SUCCESS;
933 struct HdfDevListenerThread *listenerThread = adapterGroup->thread;
934
935 OsalMutexLock(&listenerThread->mutex);
936 struct HdfDevEventlistener *it = NULL;
937 DLIST_FOR_EACH_ENTRY(it, &adapterGroup->listenerList, struct HdfDevEventlistener, listNode) {
938 if (it == listener) {
939 HDF_LOGE("Failed to add group listener, repeated registration");
940 ret = HDF_ERR_INVALID_PARAM;
941 goto FINISH;
942 }
943 }
944 DListInsertTail(&listener->listNode, &adapterGroup->listenerList);
945 if (!DListIsEmpty(&adapterGroup->adapterList) && listenerThread->status < LISTENER_STARTED) {
946 ret = HdfDevListenerThreadStart(listenerThread);
947 if (ret != HDF_SUCCESS) {
948 DListRemove(&listener->listNode);
949 }
950 }
951
952 FINISH:
953 OsalMutexUnlock(&listenerThread->mutex);
954 OsalMutexUnlock(&adapterGroup->mutex);
955 return ret;
956 }
957
GetListenerCount(struct HdfDevListenerThread * thread)958 static int32_t GetListenerCount(struct HdfDevListenerThread *thread)
959 {
960 struct HdfDevEventlistener *listener = NULL;
961 int32_t count = 0;
962
963 OsalMutexLock(&thread->mutex);
964 if (thread->listenerListPtr != NULL) {
965 DLIST_FOR_EACH_ENTRY(listener, thread->listenerListPtr, struct HdfDevEventlistener, listNode) {
966 count++;
967 }
968 }
969
970 struct HdfSyscallAdapter *adapter = NULL;
971 DLIST_FOR_EACH_ENTRY(adapter, thread->adapterListPtr, struct HdfSyscallAdapter, listNode) {
972 OsalMutexLock(&adapter->mutex);
973 DLIST_FOR_EACH_ENTRY(listener, &adapter->listenerList, struct HdfDevEventlistener, listNode) {
974 count++;
975 }
976 OsalMutexUnlock(&adapter->mutex);
977 }
978 OsalMutexUnlock(&thread->mutex);
979
980 return count;
981 }
982
HdfIoServiceGroupUnregisterListener(struct HdfIoServiceGroup * group,struct HdfDevEventlistener * listener)983 int32_t HdfIoServiceGroupUnregisterListener(struct HdfIoServiceGroup *group, struct HdfDevEventlistener *listener)
984 {
985 if (group == NULL || listener == NULL) {
986 return HDF_ERR_INVALID_PARAM;
987 }
988
989 if (listener->listNode.next == NULL || listener->listNode.prev == NULL) {
990 HDF_LOGE("%s:broken listener, may double unregister", __func__);
991 return HDF_ERR_INVALID_OBJECT;
992 }
993
994 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
995
996 OsalMutexLock(&adapterGroup->mutex);
997 struct HdfDevListenerThread *listenerThread = adapterGroup->thread;
998
999 DListRemove(&listener->listNode);
1000
1001 if (listenerThread != NULL && GetListenerCount(listenerThread) == 0) {
1002 HdfDevListenerThreadDestroy(listenerThread);
1003 adapterGroup->thread = NULL;
1004 }
1005 OsalMutexUnlock(&adapterGroup->mutex);
1006
1007 return HDF_SUCCESS;
1008 }
1009
HdfIoServiceGroupAddService(struct HdfIoServiceGroup * group,struct HdfIoService * service)1010 int32_t HdfIoServiceGroupAddService(struct HdfIoServiceGroup *group, struct HdfIoService *service)
1011 {
1012 if (group == NULL || service == NULL) {
1013 return HDF_ERR_INVALID_PARAM;
1014 }
1015 struct HdfSyscallAdapter *adapter = CONTAINER_OF(service, struct HdfSyscallAdapter, super);
1016 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
1017
1018 if (adapter->group != NULL) {
1019 HDF_LOGE("service already in group");
1020 return HDF_ERR_DEVICE_BUSY;
1021 }
1022
1023 if (adapter->thread != NULL) {
1024 HDF_LOGE("service already has independent thread");
1025 return HDF_ERR_DEVICE_BUSY;
1026 }
1027
1028 OsalMutexLock(&adapterGroup->mutex);
1029 if (HdfIoServiceGroupThreadInit(adapterGroup) != HDF_SUCCESS) {
1030 HDF_LOGE("%s:failed to bind listener thread for service group", __func__);
1031 OsalMutexUnlock(&adapterGroup->mutex);
1032 return HDF_FAILURE;
1033 }
1034
1035 struct HdfDevListenerThread *listenerThread = adapterGroup->thread;
1036 int32_t ret = HdfListenThreadPollAdd(listenerThread, adapter);
1037 if (ret != HDF_SUCCESS) {
1038 OsalMutexUnlock(&adapterGroup->mutex);
1039 return ret;
1040 }
1041
1042 adapter->group = adapterGroup;
1043
1044 OsalMutexLock(&listenerThread->mutex);
1045 if ((!DListIsEmpty(&adapterGroup->listenerList) || !DListIsEmpty(&adapter->listenerList)) &&
1046 listenerThread->status < LISTENER_STARTED) {
1047 ret = HdfDevListenerThreadStart(adapterGroup->thread);
1048 if (ret != HDF_SUCCESS) {
1049 HdfListenThreadPollDel(adapterGroup->thread, adapter);
1050 }
1051 }
1052 OsalMutexUnlock(&listenerThread->mutex);
1053 OsalMutexUnlock(&adapterGroup->mutex);
1054 return ret;
1055 }
1056
HdfIoServiceGroupRemoveService(struct HdfIoServiceGroup * group,struct HdfIoService * service)1057 void HdfIoServiceGroupRemoveService(struct HdfIoServiceGroup *group, struct HdfIoService *service)
1058 {
1059 if (group == NULL || service == NULL) {
1060 return;
1061 }
1062 struct HdfSyscallAdapter *adapter = CONTAINER_OF(service, struct HdfSyscallAdapter, super);
1063 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
1064 if (adapterGroup->thread == NULL || adapter->group == NULL) {
1065 return;
1066 }
1067
1068 OsalMutexLock(&adapterGroup->mutex);
1069 if (HaveOnlyOneElement(&adapterGroup->adapterList)) {
1070 HdfDevListenerThreadDestroy(adapterGroup->thread);
1071 adapterGroup->thread = NULL;
1072 DListRemove(&adapter->listNode);
1073 adapter->group = NULL;
1074 } else {
1075 HdfListenThreadPollDel(adapterGroup->thread, adapter);
1076 }
1077 OsalMutexUnlock(&adapterGroup->mutex);
1078 adapter->group = NULL;
1079 }
1080
HdfIoserviceGetListenerCount(const struct HdfIoService * service)1081 int HdfIoserviceGetListenerCount(const struct HdfIoService *service)
1082 {
1083 if (service == NULL) {
1084 return 0;
1085 }
1086
1087 struct HdfSyscallAdapter *adapter = CONTAINER_OF(service, struct HdfSyscallAdapter, super);
1088
1089 OsalMutexLock(&adapter->mutex);
1090 int count = DlistGetCount(&adapter->listenerList);
1091 OsalMutexUnlock(&adapter->mutex);
1092 return count;
1093 }
1094
HdfIoserviceGroupGetListenerCount(const struct HdfIoServiceGroup * group)1095 int HdfIoserviceGroupGetListenerCount(const struct HdfIoServiceGroup *group)
1096 {
1097 if (group == NULL) {
1098 return 0;
1099 }
1100
1101 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
1102 OsalMutexLock(&adapterGroup->mutex);
1103 if (adapterGroup->thread == NULL) {
1104 OsalMutexUnlock(&adapterGroup->mutex);
1105 return 0;
1106 }
1107 int count = GetListenerCount(adapterGroup->thread);
1108 OsalMutexUnlock(&adapterGroup->mutex);
1109 return count;
1110 }
1111
HdfIoserviceGroupGetServiceCount(const struct HdfIoServiceGroup * group)1112 int HdfIoserviceGroupGetServiceCount(const struct HdfIoServiceGroup *group)
1113 {
1114 if (group == NULL) {
1115 return 0;
1116 }
1117
1118 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
1119
1120 OsalMutexLock(&adapterGroup->mutex);
1121 if (adapterGroup->thread == NULL) {
1122 OsalMutexUnlock(&adapterGroup->mutex);
1123 return 0;
1124 }
1125
1126 OsalMutexLock(&adapterGroup->thread->mutex);
1127 int count = DlistGetCount(&adapterGroup->adapterList);
1128 OsalMutexUnlock(&adapterGroup->thread->mutex);
1129
1130 OsalMutexUnlock(&adapterGroup->mutex);
1131
1132 return count;
1133 }
1134