• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "osal_sysevent.h"
17 #include "hdf_io_service_if.h"
18 #include "hdf_log.h"
19 #include "osal_mem.h"
20 #include "osal_mutex.h"
21 
22 #define HDF_LOG_TAG usysevent
23 
24 #define KEVENT_IOSERVICE_NAME "hdf_kevent"
25 
26 #define KEVENT_COMPLETE_EVENT 1
27 
28 struct HdfSysEventNotifier {
29     struct OsalMutex mutex;
30     struct DListHead notifyNodeList;
31     struct DListHead waitList;
32     struct HdfDevEventlistener ioServiceListener;
33     struct HdfIoService *keventIoService;
34 };
35 
36 struct HdfSysEventNotifier *g_hdfSysEventNotifier;
37 
HdfSysEventNotifierGetInstance(void)38 static struct HdfSysEventNotifier *HdfSysEventNotifierGetInstance(void)
39 {
40     if (g_hdfSysEventNotifier != NULL) {
41         return g_hdfSysEventNotifier;
42     }
43 
44     struct HdfSysEventNotifier *notifier = OsalMemCalloc(sizeof(struct HdfSysEventNotifier));
45     if (notifier == NULL) {
46         return NULL;
47     }
48 
49     int ret = OsalMutexInit(&notifier->mutex);
50     if (ret != HDF_SUCCESS) {
51         OsalMemFree(notifier);
52         return NULL;
53     }
54 
55     DListHeadInit(&notifier->notifyNodeList);
56 
57     g_hdfSysEventNotifier = notifier;
58 
59     return notifier;
60 }
61 
FinishEvent(struct HdfIoService * service,const struct HdfSysEvent * event)62 static int FinishEvent(struct HdfIoService *service, const struct HdfSysEvent *event)
63 {
64     struct HdfSBuf *sbuf = HdfSbufObtain(sizeof(uint64_t));
65 
66     if (sbuf == NULL) {
67         return HDF_ERR_MALLOC_FAIL;
68     }
69 
70     if (!HdfSbufWriteUint64(sbuf, event->syncToken)) {
71         HdfSbufRecycle(sbuf);
72         return HDF_FAILURE;
73     }
74 
75     int ret = service->dispatcher->Dispatch(&service->object, KEVENT_COMPLETE_EVENT, sbuf, NULL);
76     if (ret != HDF_SUCCESS) {
77         HDF_LOGE("failed to finish sysevent, %{public}d", ret);
78     }
79 
80     HdfSbufRecycle(sbuf);
81     return ret;
82 }
83 
OnKEventReceived(struct HdfDevEventlistener * listener,struct HdfIoService * service,uint32_t id,struct HdfSBuf * data)84 static int OnKEventReceived(
85     struct HdfDevEventlistener *listener, struct HdfIoService *service, uint32_t id, struct HdfSBuf *data)
86 {
87     struct HdfSysEventNotifier *notifier = (struct HdfSysEventNotifier *)listener->priv;
88     if (notifier == NULL) {
89         return HDF_ERR_INVALID_PARAM;
90     }
91 
92     if (id != HDF_SYSEVENT) {
93         return HDF_ERR_INVALID_OBJECT;
94     }
95 
96     struct HdfSysEvent *receivedEvent = NULL;
97     uint32_t receivedEventLen = 0;
98 
99     if (!HdfSbufReadBuffer(data, (const void **)&receivedEvent, &receivedEventLen) ||
100         receivedEventLen != sizeof(struct HdfSysEvent)) {
101         HDF_LOGE("failed to read kevent object");
102         return HDF_FAILURE;
103     }
104 
105     receivedEvent->content = HdfSbufReadString(data);
106 
107     OsalMutexLock(&notifier->mutex);
108 
109     struct HdfSysEventNotifyNode *notifyNode = NULL;
110     DLIST_FOR_EACH_ENTRY(notifyNode, &notifier->notifyNodeList, struct HdfSysEventNotifyNode, listNode) {
111         if (receivedEvent->eventClass & notifyNode->classFilter) {
112             (void)notifyNode->callback(
113                 notifyNode, receivedEvent->eventClass, receivedEvent->eventid, receivedEvent->content);
114         }
115     }
116 
117     if (receivedEvent->syncToken != 0) {
118         FinishEvent(service, receivedEvent);
119     }
120 
121     OsalMutexUnlock(&notifier->mutex);
122 
123     return HDF_SUCCESS;
124 }
125 
InitKeventIoServiceListenerLocked(struct HdfSysEventNotifier * notifier)126 static int InitKeventIoServiceListenerLocked(struct HdfSysEventNotifier *notifier)
127 {
128     if (notifier->keventIoService == NULL) {
129         notifier->keventIoService = HdfIoServiceBind(KEVENT_IOSERVICE_NAME);
130     }
131     if (notifier->keventIoService == NULL) {
132         HDF_LOGE(" ioservice %{public}s is invalid", KEVENT_IOSERVICE_NAME);
133         return HDF_DEV_ERR_NO_DEVICE;
134     }
135 
136     notifier->ioServiceListener.onReceive = OnKEventReceived;
137     notifier->ioServiceListener.priv = notifier;
138     int ret = HdfDeviceRegisterEventListener(notifier->keventIoService, &notifier->ioServiceListener);
139     if (ret != HDF_SUCCESS) {
140         HDF_LOGE(" ioservice %{public}s is invalid", KEVENT_IOSERVICE_NAME);
141         HdfIoServiceRecycle(notifier->keventIoService);
142         notifier->keventIoService = NULL;
143     }
144 
145     return ret;
146 }
147 
DeInitKeventIoServiceListenerLocked(struct HdfSysEventNotifier * notifier)148 static void DeInitKeventIoServiceListenerLocked(struct HdfSysEventNotifier *notifier)
149 {
150     if (notifier->keventIoService == NULL) {
151         return;
152     }
153 
154     (void)HdfDeviceUnregisterEventListener(notifier->keventIoService, &notifier->ioServiceListener);
155     HdfIoServiceRecycle(notifier->keventIoService);
156     notifier->keventIoService = NULL;
157 }
158 
HdfSysEventNotifyRegister(struct HdfSysEventNotifyNode * notifierNode,uint64_t classSet)159 int32_t HdfSysEventNotifyRegister(struct HdfSysEventNotifyNode *notifierNode, uint64_t classSet)
160 {
161     if (notifierNode == NULL) {
162         return HDF_ERR_INVALID_PARAM;
163     }
164 
165     struct HdfSysEventNotifier *notifier = HdfSysEventNotifierGetInstance();
166 
167     if (notifier == NULL) {
168         return HDF_DEV_ERR_NO_MEMORY;
169     }
170 
171     OsalMutexLock(&notifier->mutex);
172     DListInsertTail(&notifierNode->listNode, &notifier->notifyNodeList);
173     notifierNode->classFilter = classSet;
174     int32_t ret = InitKeventIoServiceListenerLocked(notifier);
175     if (ret != HDF_SUCCESS) {
176         DListRemove(&notifierNode->listNode);
177     }
178     OsalMutexUnlock(&notifier->mutex);
179 
180     return ret;
181 }
182 
HdfSysEventNotifyUnregister(struct HdfSysEventNotifyNode * notifierNode)183 void HdfSysEventNotifyUnregister(struct HdfSysEventNotifyNode *notifierNode)
184 {
185     if (notifierNode == NULL) {
186         return;
187     }
188 
189     struct HdfSysEventNotifier *notifier = HdfSysEventNotifierGetInstance();
190 
191     if (notifier == NULL) {
192         return;
193     }
194     OsalMutexLock(&notifier->mutex);
195 
196     DListRemove(&notifierNode->listNode);
197     if (DListIsEmpty(&notifier->notifyNodeList)) {
198         DeInitKeventIoServiceListenerLocked(notifier);
199     }
200     OsalMutexUnlock(&notifier->mutex);
201 }
202