1 /*
2 * Copyright (c) 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 "devsvc_listener_holder.h"
10 #include "devsvc_manager.h"
11 #include "hdf_base.h"
12 #include "hdf_device_node.h"
13 #include "hdf_io_service.h"
14 #include "hdf_log.h"
15 #include "hdf_object_manager.h"
16 #include "osal_mem.h"
17 #include "svcmgr_ioservice.h"
18 #include "osal_mutex.h"
19
20 #define HDF_LOG_TAG devsvc_mger
21 #define SVC_MGR_NODE_PERM 0660
22
23 struct DevSvcManagerExt {
24 struct DevSvcManager super;
25 struct IDeviceIoService ioService;
26 struct HdfIoService *serv;
27 struct OsalMutex mutex;
28 bool started;
29 };
30
DeviceSvcMgrOpen(struct HdfDeviceIoClient * client)31 int32_t DeviceSvcMgrOpen(struct HdfDeviceIoClient *client)
32 {
33 (void)client;
34 return HDF_SUCCESS;
35 }
36
DevSvcManagerExtRegisterListener(struct HdfDeviceIoClient * client,struct HdfSBuf * data)37 static int32_t DevSvcManagerExtRegisterListener(struct HdfDeviceIoClient *client, struct HdfSBuf *data)
38 {
39 struct ServStatListenerHolder *holder = NULL;
40 uint16_t devClass = DEVICE_CLASS_MAX;
41 struct DevSvcManagerExt *svcmgrInst = NULL;
42 if (client->device == NULL || client->device->priv == NULL) {
43 return HDF_ERR_INVALID_PARAM;
44 }
45 svcmgrInst = (struct DevSvcManagerExt *)DevSvcManagerGetInstance();
46
47 if (!HdfSbufReadUint16(data, &devClass)) {
48 return HDF_ERR_INVALID_PARAM;
49 }
50
51 holder = ServStatListenerHolderGet((uintptr_t)client);
52 if (holder != NULL) {
53 HDF_LOGE("%s:register listener exist, update and return", __func__);
54 holder->listenClass = devClass;
55 return HDF_SUCCESS;
56 }
57
58 holder = ServStatListenerHolderCreate((uintptr_t)client, devClass);
59 if (holder == NULL) {
60 return HDF_ERR_MALLOC_FAIL;
61 }
62
63 return svcmgrInst->super.super.RegsterServListener(&svcmgrInst->super.super, holder);
64 }
65
DevSvcManagerExtUnRegisterListener(struct HdfDeviceIoClient * client)66 static int32_t DevSvcManagerExtUnRegisterListener(struct HdfDeviceIoClient *client)
67 {
68 struct ServStatListenerHolder *holder = NULL;
69 struct DevSvcManagerExt *svcmgrInst = NULL;
70
71 if (client->device == NULL || client->device->priv == NULL) {
72 return HDF_ERR_INVALID_PARAM;
73 }
74
75 svcmgrInst = (struct DevSvcManagerExt *)client->device->priv;
76 OsalMutexLock(&svcmgrInst->mutex);
77 holder = ServStatListenerHolderGet((uintptr_t)client);
78 if (holder == NULL) {
79 OsalMutexUnlock(&svcmgrInst->mutex);
80 return HDF_DEV_ERR_NO_DEVICE_SERVICE;
81 }
82 if (holder->node.next != NULL) {
83 svcmgrInst->super.super.UnregsterServListener(&svcmgrInst->super.super, holder);
84 }
85 ServStatListenerHolderRelease(holder);
86 OsalMutexUnlock(&svcmgrInst->mutex);
87
88 return HDF_SUCCESS;
89 }
90
DeviceSvcMgrDispatch(struct HdfObject * service,int cmdId,struct HdfSBuf * data,struct HdfSBuf * reply)91 int32_t DeviceSvcMgrDispatch(struct HdfObject *service, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
92 {
93 uint64_t ioClientPtr = 0;
94 struct HdfDeviceIoClient *client = NULL;
95 if (service == NULL || data == NULL || reply == NULL) {
96 return HDF_ERR_INVALID_PARAM;
97 }
98
99 if (!HdfSbufReadUint64(reply, &ioClientPtr) || ioClientPtr == 0) {
100 HDF_LOGE("device svc dispatch: ioClient is null");
101 return HDF_FAILURE;
102 }
103 HdfSbufFlush(reply);
104 client = (struct HdfDeviceIoClient *)(uintptr_t)ioClientPtr;
105 switch (cmdId) {
106 case SVCMGR_REGISTER_LISTENER:
107 return DevSvcManagerExtRegisterListener(client, data);
108 case SVCMGR_UNREGISTER_LISTENER:
109 return DevSvcManagerExtUnRegisterListener(client);
110 default:
111 break;
112 }
113
114 return HDF_ERR_NOT_SUPPORT;
115 }
116
DeviceSvcMgrRelease(struct HdfDeviceIoClient * client)117 void DeviceSvcMgrRelease(struct HdfDeviceIoClient *client)
118 {
119 if (client == NULL) {
120 return;
121 }
122 DevSvcManagerExtUnRegisterListener(client);
123 }
124
DevSvcManagerExtStart(struct IDevSvcManager * svcmgr)125 int DevSvcManagerExtStart(struct IDevSvcManager *svcmgr)
126 {
127 struct DevSvcManagerExt *inst = (struct DevSvcManagerExt *)svcmgr;
128 static struct HdfDeviceObject svcmgrDevObj = { 0 };
129 static struct IDeviceIoService svcmgrIoService = {
130 .Open = DeviceSvcMgrOpen,
131 .Dispatch = NULL,
132 .Release = DeviceSvcMgrRelease,
133 };
134 if (inst == NULL) {
135 return HDF_ERR_INVALID_PARAM;
136 }
137
138 if (inst->started) {
139 return HDF_SUCCESS;
140 }
141
142 svcmgrDevObj.service = &svcmgrIoService;
143 svcmgrDevObj.property = NULL;
144 svcmgrDevObj.deviceClass = DEVICE_CLASS_DEFAULT;
145 svcmgrDevObj.priv = (void *)svcmgr;
146
147 inst->serv = HdfIoServicePublish(DEV_SVCMGR_NODE, SVC_MGR_NODE_PERM);
148 if (inst->serv == NULL) {
149 HDF_LOGE("failed to pushlish svcmgr ioservice");
150 } else {
151 static struct HdfIoDispatcher dispatcher = {
152 .Dispatch = DeviceSvcMgrDispatch,
153 };
154 inst->serv->dispatcher = &dispatcher;
155 inst->serv->target = (struct HdfObject *)&svcmgrDevObj;
156 }
157
158 ServStatListenerHolderinit();
159 inst->started = true;
160 return HDF_SUCCESS;
161 }
162
DevSvcManagerExtConstruct(struct DevSvcManagerExt * inst)163 static bool DevSvcManagerExtConstruct(struct DevSvcManagerExt *inst)
164 {
165 if (inst == NULL) {
166 return false;
167 }
168 if (!DevSvcManagerConstruct(&inst->super)) {
169 HDF_LOGE("failed to construct device service manager");
170 return false;
171 }
172 if (OsalMutexInit(&inst->mutex) != HDF_SUCCESS) {
173 HDF_LOGE("failed to create devsvcmgrext mutex");
174 return false;
175 }
176 inst->super.super.StartService = DevSvcManagerExtStart;
177
178 return true;
179 }
180
DevSvcManagerExtCreate(void)181 struct HdfObject *DevSvcManagerExtCreate(void)
182 {
183 static struct DevSvcManagerExt *instance;
184 if (instance != NULL) {
185 return (struct HdfObject *)instance;
186 }
187
188 instance = OsalMemCalloc(sizeof(struct DevSvcManagerExt));
189 if (!DevSvcManagerExtConstruct(instance)) {
190 OsalMemFree(instance);
191 instance = NULL;
192 }
193
194 return (struct HdfObject *)instance;
195 }
196
DevSvcManagerExtRelease(struct IDevSvcManager * inst)197 void DevSvcManagerExtRelease(struct IDevSvcManager *inst)
198 {
199 struct DevSvcManagerExt *instance = (struct DevSvcManagerExt *)inst;
200 if (instance == NULL) {
201 return;
202 }
203 if (instance->serv != NULL) {
204 HdfIoServiceRemove(instance->serv);
205 instance->serv = NULL;
206 }
207 DevSvcManagerRelease(inst);
208 instance->started = false;
209 }
210