From 99d506e8b56e1d516f897bd4e4b77b50f6235f36 Mon Sep 17 00:00:00 2001 From: yuanbo Date: Sat, 19 Feb 2022 11:34:22 +0800 Subject: [PATCH] feat: support dynamic load khdf driver module Signed-off-by: yuanbo --- .clang-format | 16 +++- .../adapter/syscall/src/hdf_syscall_adapter.c | 94 +++++++++++-------- core/manager/src/devmgr_service.c | 12 +-- core/manager/src/driver_manager.c | 47 +++++++--- .../unittest/common/hdf_lite_manager_test.cpp | 56 +++++------ include/utils/hdf_base.h | 1 + utils/include/osal_sysevent.h | 17 +++- 7 files changed, 149 insertions(+), 94 deletions(-) mode change 100755 => 100644 include/utils/hdf_base.h diff --git a/.clang-format b/.clang-format index 0983e957..9d8e1bde 100644 --- a/.clang-format +++ b/.clang-format @@ -4,12 +4,24 @@ PointerAlignment: Right AlignAfterOpenBracket: DontAlign AlignTrailingComments: true AlignConsecutiveMacros: Consecutive -AllowShortFunctionsOnASingleLine: None IndentCaseLabels: true BreakBeforeBinaryOperators: None -SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatementsExceptControlMacros SpacesInCStyleCastParentheses: false +AlignEscapedNewlines: Left +NamespaceIndentation: None +FixNamespaceComments: true +ConstructorInitializerAllOnOneLineOrOnePerLine: true +BreakConstructorInitializers: AfterColon +AlignArrayOfStructures: Left +AllowShortFunctionsOnASingleLine: Empty +AllowShortLambdasOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: true +SpaceInEmptyBlock: false +LambdaBodyIndentation: Signature +BreakBeforeTernaryOperators: false +Cpp11BracedListStyle: true +SpaceAroundPointerQualifiers: Both ForEachMacros: - 'DLIST_FOR_EACH_ENTRY' diff --git a/core/adapter/syscall/src/hdf_syscall_adapter.c b/core/adapter/syscall/src/hdf_syscall_adapter.c index a73c813c..095cb6a6 100644 --- a/core/adapter/syscall/src/hdf_syscall_adapter.c +++ b/core/adapter/syscall/src/hdf_syscall_adapter.c @@ -6,29 +6,33 @@ * See the LICENSE file in the root of this repository for complete details. */ -#include "hdf_syscall_adapter.h" #include #include +#include +#include #include #include #include #include #include -#include -#include + #include "hdf_base.h" #include "hdf_log.h" #include "hdf_sbuf.h" #include "osal_mem.h" -#define HDF_LOG_TAG hdf_syscall_adapter -#define EPOLL_MAX_EVENT_SIZE 4 -#define HDF_DEFAULT_BWR_READ_SIZE 1024 +#include "hdf_syscall_adapter.h" + +#define HDF_LOG_TAG hdf_syscall_adapter +#define EPOLL_MAX_EVENT_SIZE 4 +#define HDF_DEFAULT_BWR_READ_SIZE 1024 #define EVENT_READ_BUFF_GROWTH_RATE 2 -#define EVENT_READ_BUFF_MAX (20 * 1024) // 20k -#define SYSCALL_INVALID_FD (-1) -#define HDF_PFD_GROW_SIZE 4 -#define TIMEOUT_US 100000 // 100ms +#define EVENT_READ_BUFF_MAX (20 * 1024) // 20k +#define SYSCALL_INVALID_FD (-1) +#define HDF_PFD_GROW_SIZE 4 +#define TIMEOUT_US 100000 // 100ms +#define LOAD_IOSERVICE_WAIT_TIME 10 // ms +#define LOAD_IOSERVICE_WAIT_COUNT 20 // ms static bool HaveOnlyOneElement(const struct DListHead *head) { @@ -54,7 +58,7 @@ static int32_t HdfDevEventGrowReadBuffer(struct HdfWriteReadBuf *buffer) return HDF_DEV_ERR_NO_MEMORY; } - OsalMemFree((void*)(uintptr_t)buffer->readBuffer); + OsalMemFree((void *)(uintptr_t)buffer->readBuffer); buffer->readBuffer = (uintptr_t)newBuff; return HDF_SUCCESS; } @@ -79,8 +83,8 @@ static struct HdfSyscallAdapter *HdfFdToAdapterLocked(const struct HdfDevListene return NULL; } -static int32_t HdfDevEventDispatchLocked(const struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter, - const struct HdfWriteReadBuf *bwr) +static int32_t HdfDevEventDispatchLocked( + const struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter, const struct HdfWriteReadBuf *bwr) { struct HdfDevEventlistener *listener = NULL; struct HdfSBuf *sbuf = NULL; @@ -126,7 +130,7 @@ static int32_t HdfDevEventDispatchLocked(const struct HdfDevListenerThread *thre static int32_t HdfDevEventReadAndDispatch(struct HdfDevListenerThread *thread, int32_t fd) { - struct HdfWriteReadBuf bwr = { 0 }; + struct HdfWriteReadBuf bwr = {0}; int32_t ret = HDF_SUCCESS; bwr.readBuffer = (uintptr_t)OsalMemAlloc(HDF_DEFAULT_BWR_READ_SIZE); @@ -172,7 +176,7 @@ static int32_t HdfDevEventReadAndDispatch(struct HdfDevListenerThread *thread, i ret = HdfDevEventDispatchLocked(thread, adapter, &bwr); finish: - OsalMemFree((void*)(uintptr_t)bwr.readBuffer); + OsalMemFree((void *)(uintptr_t)bwr.readBuffer); OsalMutexUnlock(&thread->mutex); return ret; } @@ -325,7 +329,7 @@ static int32_t HdfDevListenerThreadInit(struct HdfDevListenerThread *thread) switch (thread->status) { case LISTENER_STARTED: // fall-through case LISTENER_RUNNING: // fall-through - case LISTENER_INITED: // fall-through + case LISTENER_INITED: // fall-through case LISTENER_WAITING: return HDF_SUCCESS; case LISTENER_EXITED: @@ -362,8 +366,8 @@ static int32_t GetValidPfdIndexLocked(struct HdfDevListenerThread *thread, struc return HDF_ERR_MALLOC_FAIL; } if (thread->pfdSize != 0) { - (void)memcpy_s(newPfds, sizeof(struct pollfd) * newSize, - thread->pfds, sizeof(struct pollfd) * thread->pfdSize); + (void)memcpy_s( + newPfds, sizeof(struct pollfd) * newSize, thread->pfds, sizeof(struct pollfd) * thread->pfdSize); } for (uint32_t i = index; i < newSize; i++) { @@ -503,7 +507,8 @@ static int32_t HdfListenThreadPollAdd(struct HdfDevListenerThread *thread, struc OsalMutexLock(&thread->mutex); struct HdfSyscallAdapter *headAdapter = DListIsEmpty(thread->adapterListPtr) ? - NULL : DLIST_FIRST_ENTRY(thread->adapterListPtr, struct HdfSyscallAdapter, listNode); + NULL : + DLIST_FIRST_ENTRY(thread->adapterListPtr, struct HdfSyscallAdapter, listNode); DListInsertTail(&adapter->listNode, thread->adapterListPtr); @@ -548,7 +553,7 @@ static int32_t HdfListenThreadPollAdd(struct HdfDevListenerThread *thread, struc return ret; } -static void HdfListenThreadPollDel(struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter) +static void HdfListenThreadPollDel(struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter) { if (thread == NULL) { DListRemove(&adapter->listNode); @@ -635,8 +640,8 @@ static void HdfDevListenerThreadDestroy(struct HdfDevListenerThread *thread) } } -static int32_t HdfSyscallAdapterDispatch(struct HdfObject *object, int32_t code, - struct HdfSBuf *data, struct HdfSBuf *reply) +static int32_t HdfSyscallAdapterDispatch( + struct HdfObject *object, int32_t code, struct HdfSBuf *data, struct HdfSBuf *reply) { if (object == NULL) { HDF_LOGE("Input object is null"); @@ -646,14 +651,14 @@ static int32_t HdfSyscallAdapterDispatch(struct HdfObject *object, int32_t code, struct HdfWriteReadBuf wrBuf; if (reply != NULL) { wrBuf.readBuffer = (uintptr_t)HdfSbufGetData(reply); - wrBuf.readSize = HdfSbufGetCapacity(reply); + wrBuf.readSize = HdfSbufGetCapacity(reply); } else { wrBuf.readBuffer = 0; wrBuf.readSize = 0; } if (data != NULL) { wrBuf.writeBuffer = (uintptr_t)HdfSbufGetData(data); - wrBuf.writeSize = HdfSbufGetDataSize(data); + wrBuf.writeSize = HdfSbufGetDataSize(data); } else { wrBuf.writeBuffer = 0; wrBuf.writeSize = 0; @@ -662,7 +667,7 @@ static int32_t HdfSyscallAdapterDispatch(struct HdfObject *object, int32_t code, wrBuf.readConsumed = 0; wrBuf.writeConsumed = 0; wrBuf.cmdCode = code; - int32_t ret = ioctl(ioService->fd, HDF_WRITE_READ, &wrBuf); + int32_t ret = ioctl(ioService->fd, HDF_WRITE_READ, &wrBuf); if (ret < 0) { HDF_LOGE("Failed to dispatch serv call ioctl %{public}d", errno); ret = errno; @@ -673,6 +678,25 @@ static int32_t HdfSyscallAdapterDispatch(struct HdfObject *object, int32_t code, return ret; } +static int TrytoLoadIoService(const char *serviceName, char *devNodePath, char *realPath) +{ + if (HdfLoadDriverByServiceName(serviceName) != HDF_SUCCESS) { + HDF_LOGE("%s: load %{public}s driver failed", __func__, serviceName); + return HDF_DEV_ERR_NO_DEVICE; + } + + int waitCount = LOAD_IOSERVICE_WAIT_COUNT; + while (realpath(devNodePath, realPath) == NULL && waitCount-- > 0) { + OsalMSleep(LOAD_IOSERVICE_WAIT_TIME); // wait ueventd to crater dev + } + if (waitCount <= 0) { + HDF_LOGE("%s: char dev %{public}s is invalid", __func__, devNodePath); + return HDF_DEV_ERR_NO_DEVICE_SERVICE; + } + + return HDF_SUCCESS; +} + struct HdfIoService *HdfIoServiceAdapterObtain(const char *serviceName) { struct HdfSyscallAdapter *adapter = NULL; @@ -697,15 +721,9 @@ struct HdfIoService *HdfIoServiceAdapterObtain(const char *serviceName) goto out; } - if (realpath(devNodePath, realPath) == NULL) { - if (HdfLoadDriverByServiceName(serviceName) != HDF_SUCCESS) { - HDF_LOGE("%s: load %{public}s driver failed", __func__, serviceName); - goto out; - } - if (realpath(devNodePath, realPath) == NULL) { - HDF_LOGE("%s: file name %{public}s is invalid", __func__, devNodePath); - goto out; - } + if (realpath(devNodePath, realPath) == NULL && + TrytoLoadIoService(serviceName, devNodePath, realPath) != HDF_SUCCESS) { + goto out; } adapter = (struct HdfSyscallAdapter *)OsalMemCalloc(sizeof(struct HdfSyscallAdapter)); @@ -843,8 +861,8 @@ int32_t HdfDeviceUnregisterEventListener(struct HdfIoService *target, struct Hdf DListRemove(&listener->listNode); if (DListIsEmpty(&adapter->listenerList)) { - HdfDevListenerThreadDestroy(adapter->thread); - adapter->thread = NULL; + HdfDevListenerThreadDestroy(adapter->thread); + adapter->thread = NULL; } OsalMutexUnlock(&adapter->mutex); @@ -950,9 +968,9 @@ static int32_t GetListenerCount(struct HdfDevListenerThread *thread) } struct HdfSyscallAdapter *adapter = NULL; - DLIST_FOR_EACH_ENTRY (adapter, thread->adapterListPtr, struct HdfSyscallAdapter, listNode) { + DLIST_FOR_EACH_ENTRY(adapter, thread->adapterListPtr, struct HdfSyscallAdapter, listNode) { OsalMutexLock(&adapter->mutex); - DLIST_FOR_EACH_ENTRY (listener, &adapter->listenerList, struct HdfDevEventlistener, listNode) { + DLIST_FOR_EACH_ENTRY(listener, &adapter->listenerList, struct HdfDevEventlistener, listNode) { count++; } OsalMutexUnlock(&adapter->mutex); diff --git a/core/manager/src/devmgr_service.c b/core/manager/src/devmgr_service.c index 115b279b..8be3458b 100644 --- a/core/manager/src/devmgr_service.c +++ b/core/manager/src/devmgr_service.c @@ -20,8 +20,8 @@ #define HDF_LOG_TAG devmgr_service -static bool DevmgrServiceDynamicDevInfoFound(const char *svcName, struct DevHostServiceClnt **targetHostClnt, - struct HdfDeviceInfo **targetDeviceInfo) +static bool DevmgrServiceDynamicDevInfoFound( + const char *svcName, struct DevHostServiceClnt **targetHostClnt, struct HdfDeviceInfo **targetDeviceInfo) { struct HdfSListIterator itDeviceInfo; struct HdfDeviceInfo *deviceInfo = NULL; @@ -59,8 +59,8 @@ static int DevmgrServiceStartHostProcess(struct DevHostServiceClnt *hostClnt, bo hostClnt->hostPid = installer->StartDeviceHost(hostClnt->hostId, hostClnt->hostName); if (hostClnt->hostPid == HDF_FAILURE) { - HDF_LOGW("failed to start device host(%s, %u)", hostClnt->hostName, hostClnt->hostId); - return HDF_FAILURE; + HDF_LOGW("failed to start device host(%s, %u)", hostClnt->hostName, hostClnt->hostId); + return HDF_FAILURE; } hostClnt->stopFlag = false; if (!sync) { @@ -310,8 +310,8 @@ static int DevmgrServiceStartDeviceHosts(struct DevmgrService *inst) hostAttr = (struct HdfHostInfo *)HdfSListIteratorNext(&it); ret = DevmgrServiceStartDeviceHost(inst, hostAttr); if (ret != HDF_SUCCESS) { - HDF_LOGW("%s failed to start device host, host id is %u, host name is '%s'", - __func__, hostAttr->hostId, hostAttr->hostName); + HDF_LOGW("%s failed to start device host, host id is %u, host name is '%s'", __func__, hostAttr->hostId, + hostAttr->hostName); } } HdfSListFlush(&hostList, HdfHostInfoDelete); diff --git a/core/manager/src/driver_manager.c b/core/manager/src/driver_manager.c index 54809559..3972a0e1 100644 --- a/core/manager/src/driver_manager.c +++ b/core/manager/src/driver_manager.c @@ -10,10 +10,11 @@ #include "hdf_driver.h" #include "hdf_log.h" #include "osal_mem.h" +#include "osal_sysevent.h" static struct DListHead *HdfDriverHead() { - static struct DListHead driverHead = { 0 }; + static struct DListHead driverHead = {0}; if (driverHead.next == NULL) { DListHeadInit(&driverHead); } @@ -52,8 +53,7 @@ int32_t HdfUnregisterDriverEntry(const struct HdfDriverEntry *entry) } driverHead = HdfDriverHead(); - DLIST_FOR_EACH_ENTRY_SAFE(driver, tmp, driverHead, struct HdfDriver, node) - { + DLIST_FOR_EACH_ENTRY_SAFE(driver, tmp, driverHead, struct HdfDriver, node) { if (driver->entry == entry) { DListRemove(&driver->node); OsalMemFree(driver); @@ -85,8 +85,7 @@ int32_t HdfUnregisterDriver(struct HdfDriver *driver) } driverHead = HdfDriverHead(); - DLIST_FOR_EACH_ENTRY_SAFE(it, tmp, driverHead, struct HdfDriver, node) - { + DLIST_FOR_EACH_ENTRY_SAFE(it, tmp, driverHead, struct HdfDriver, node) { if (it == driver) { DListRemove(&it->node); break; @@ -96,26 +95,46 @@ int32_t HdfUnregisterDriver(struct HdfDriver *driver) return HDF_SUCCESS; } -struct HdfDriver *HdfDriverManagerGetDriver(const char *driverName) +static struct HdfDriver *HdfDriverManagerFoundDriver(const char *driverName) { struct DListHead *driverHead = NULL; struct HdfDriver *driver = NULL; - - if (driverName == NULL) { - return NULL; - } - driverHead = HdfDriverHead(); DLIST_FOR_EACH_ENTRY(driver, driverHead, struct HdfDriver, node) { if (driver->entry != NULL && driver->entry->moduleName != NULL && !strcmp(driver->entry->moduleName, driverName)) { - return driver; - } + return driver; + } } - HDF_LOGE("%s:driver %s not found", __func__, driverName); + return NULL; } +struct HdfDriver *HdfDriverManagerGetDriver(const char *driverName) +{ + struct HdfDriver *driver = NULL; + if (driverName == NULL) { + return NULL; + } + driver = HdfDriverManagerFoundDriver(driverName); + if (driver != NULL) { + return driver; + } + + if (HdfSysEventSend != NULL) { + HDF_LOGI("%s:try to dynamic load driver %s", __func__, driverName); + if (HdfSysEventSend(HDF_SYSEVENT_CLASS_MODULE, KEVENT_MODULE_INSTALL, driverName, true) != HDF_SUCCESS) { + return NULL; + } + + driver = HdfDriverManagerFoundDriver(driverName); + } + if (driver == NULL) { + HDF_LOGE("%s:driver %s not found", __func__, driverName); + } + return driver; +} + struct DListHead *HdfDriverManagerGetDriverList() { return HdfDriverHead(); diff --git a/core/manager/test/unittest/common/hdf_lite_manager_test.cpp b/core/manager/test/unittest/common/hdf_lite_manager_test.cpp index 24462961..161d1ed4 100644 --- a/core/manager/test/unittest/common/hdf_lite_manager_test.cpp +++ b/core/manager/test/unittest/common/hdf_lite_manager_test.cpp @@ -10,11 +10,12 @@ #include #include #include +#include #include #include -#include -#include "hdf_uhdf_test.h" + #include "hdf_io_service.h" +#include "hdf_uhdf_test.h" #include "osal_time.h" #include "sample_driver_test.h" @@ -38,20 +39,16 @@ void HdfManagerTest::TearDownTestCase() HdfTestCloseService(); } -void HdfManagerTest::SetUp() -{ -} +void HdfManagerTest::SetUp() {} -void HdfManagerTest::TearDown() -{ -} +void HdfManagerTest::TearDown() {} /** - * @tc.name: HdfIoServiceBind001 - * @tc.desc: service bind test - * @tc.type: FUNC - * @tc.require: AR000F8698 AR000F8699 AR000F869A AR000F869B AR000F869C - */ + * @tc.name: HdfIoServiceBind001 + * @tc.desc: service bind test + * @tc.type: FUNC + * @tc.require: AR000F8698 AR000F8699 AR000F869A AR000F869B AR000F869C + */ HWTEST_F(HdfManagerTest, HdfIoServiceBind001, TestSize.Level0) { const char *svcName = "HDF_TEST"; @@ -61,11 +58,11 @@ HWTEST_F(HdfManagerTest, HdfIoServiceBind001, TestSize.Level0) } /** - * @tc.name: HdfIoServiceBind002 - * @tc.desc: service bind test - * @tc.type: FUNC - * @tc.require: AR000F8698 AR000F8699 AR000F869A AR000F869B AR000F869C - */ + * @tc.name: HdfIoServiceBind002 + * @tc.desc: service bind test + * @tc.type: FUNC + * @tc.require: AR000F8698 AR000F8699 AR000F869A AR000F869B AR000F869C + */ HWTEST_F(HdfManagerTest, HdfIoServiceBind002, TestSize.Level0) { struct HdfIoService *hdfSvc = HdfIoServiceBind(DEV_MGR_NODE); @@ -74,11 +71,11 @@ HWTEST_F(HdfManagerTest, HdfIoServiceBind002, TestSize.Level0) } /** - * @tc.name: HdfRegisterDevice001 - * @tc.desc: register device - * @tc.type: FUNC - * @tc.require: SR000F8697 - */ + * @tc.name: HdfRegisterDevice001 + * @tc.desc: register device + * @tc.type: FUNC + * @tc.require: SR000F8697 + */ HWTEST_F(HdfManagerTest, HdfRegisterDevice001, TestSize.Level0) { int32_t ret = HDF_FAILURE; @@ -110,11 +107,11 @@ HWTEST_F(HdfManagerTest, HdfRegisterDevice001, TestSize.Level0) } /** - * @tc.name: HdfGetServiceNameByDeviceClass001 - * @tc.desc: get service test - * @tc.type: FUNC - * @tc.require: AR000F8698 AR000F8699 AR000F869A AR000F869B AR000F869C - */ + * @tc.name: HdfGetServiceNameByDeviceClass001 + * @tc.desc: get service test + * @tc.type: FUNC + * @tc.require: AR000F8698 AR000F8699 AR000F869A AR000F869B AR000F869C + */ HWTEST_F(HdfManagerTest, HdfGetServiceNameByDeviceClass001, TestSize.Level0) { struct HdfSBuf *data = HdfSbufObtain(2000); @@ -126,7 +123,7 @@ HWTEST_F(HdfManagerTest, HdfGetServiceNameByDeviceClass001, TestSize.Level0) std::cout << "clasee " << i << " device list:" << std::endl; EXPECT_TRUE(ret == HDF_SUCCESS); const char *svcName = NULL; - while(true) { + while (true) { svcName = HdfSbufReadString(data); if (svcName == NULL) { break; @@ -141,4 +138,3 @@ HWTEST_F(HdfManagerTest, HdfGetServiceNameByDeviceClass001, TestSize.Level0) HdfSbufRecycle(data); EXPECT_TRUE(flag); } - diff --git a/include/utils/hdf_base.h b/include/utils/hdf_base.h old mode 100755 new mode 100644 index 03458669..1b3a471f --- a/include/utils/hdf_base.h +++ b/include/utils/hdf_base.h @@ -98,6 +98,7 @@ typedef enum { #define HDF_LIBRARY_DIR "/vendor/lib" #define HDF_ETC_DIR "/vendor/etc" #define HDF_CONFIG_DIR "/vendor/etc/hdfconfig" +#define HDF_MODULE_DIR "/vendor/modules/" #endif #ifdef __cplusplus diff --git a/utils/include/osal_sysevent.h b/utils/include/osal_sysevent.h index b10a74c4..7200b20f 100644 --- a/utils/include/osal_sysevent.h +++ b/utils/include/osal_sysevent.h @@ -13,7 +13,8 @@ #define HDF_SYSEVENT 0xFADE /* hdf sys event class definition */ -#define HDF_SYSEVENT_CLASS_POWER 0x00000001 +#define HDF_SYSEVENT_CLASS_POWER 0x00000001 +#define HDF_SYSEVENT_CLASS_MODULE 0x00000002 /* hdf power event definition */ enum PowerKeventId { @@ -24,6 +25,13 @@ enum PowerKeventId { KEVENT_POWER_EVENT_MAX, }; +/* hdf power event definition */ +enum DriverModuleKeventId { + KEVENT_MODULE_INSTALL, + KEVENT_MODULE_REMOVE, + KEVENT_MODULE_EVENT_MAX, +}; + struct HdfSysEvent { uint64_t eventClass; uint32_t eventid; @@ -33,7 +41,7 @@ struct HdfSysEvent { struct HdfSysEventNotifyNode; -typedef int (*HdfSysEventNotifierFn)( +typedef int32_t (*HdfSysEventNotifierFn)( struct HdfSysEventNotifyNode *self, uint64_t eventClass, uint32_t event, const char *content); struct HdfSysEventNotifyNode { @@ -42,8 +50,9 @@ struct HdfSysEventNotifyNode { uint64_t classFilter; }; -int HdfSysEventNotifyRegister(struct HdfSysEventNotifyNode *notifierNode, uint64_t classSet); +int32_t HdfSysEventNotifyRegister(struct HdfSysEventNotifyNode *notifierNode, uint64_t classSet); void HdfSysEventNotifyUnregister(struct HdfSysEventNotifyNode *notifierNode); -int HdfSysEventSend(uint64_t eventClass, uint32_t event, const char *content, bool sync); + +__attribute__((weak)) int32_t HdfSysEventSend(uint64_t eventClass, uint32_t event, const char *content, bool sync); #endif // #ifndef OSAL_SYSEVENT_H \ No newline at end of file