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 <securec.h>
17 /*
18 * The "devmgr_service_stub.h" header file should be used. Actually, only the interface ID definition and service name
19 * are required here. This dependency can be removed when interface proxy impl is automatically generated from IDL.
20 */
21 #include <devmgr_service_stub.h>
22 #include <hdf_base.h>
23 #include <hdf_log.h>
24 #include <hdf_remote_service.h>
25 #include <osal_mem.h>
26 #include <servmgr_hdi.h>
27 #include "devmgr_hdi.h"
28
29 #define HDF_LOG_TAG devmgr_interface
30
31 static void DevmgrFreeQueryDeviceListImpl(struct DeviceInfoList *list);
32
DeviceManagerHdiCall(struct HDIDeviceManager * iDevMgr,int32_t id,struct HdfSBuf * data,struct HdfSBuf * reply)33 static int32_t DeviceManagerHdiCall(struct HDIDeviceManager *iDevMgr, int32_t id,
34 struct HdfSBuf *data, struct HdfSBuf *reply)
35 {
36 if (iDevMgr->remote == NULL || iDevMgr->remote->dispatcher == NULL ||
37 iDevMgr->remote->dispatcher->Dispatch == NULL) {
38 return HDF_ERR_INVALID_OBJECT;
39 }
40
41 return iDevMgr->remote->dispatcher->Dispatch(iDevMgr->remote, id, data, reply);
42 }
43
HdfObtainDeviceInfo(struct DeviceInfoList * list,struct HdfSBuf * reply)44 static int32_t HdfObtainDeviceInfo(struct DeviceInfoList *list, struct HdfSBuf *reply)
45 {
46 struct DeviceInfoNode *node = NULL;
47 const char *svrName = NULL;
48 int32_t svrNameLen;
49 char *base = NULL;
50 int32_t deviceType;
51
52 while ((svrName = HdfSbufReadString(reply))) {
53 svrNameLen = strlen(svrName) + 1;
54 base = (char *)OsalMemCalloc(sizeof(*node) + svrNameLen);
55 if (base == NULL) {
56 DevmgrFreeQueryDeviceListImpl(list);
57 return HDF_FAILURE;
58 }
59 node = (struct DeviceInfoNode *)base;
60 node->svcName = base + sizeof(*node);
61 if (strcpy_s(node->svcName, svrNameLen, svrName) != EOK) {
62 HDF_LOGE("strcpy service name %{public}s failed", svrName);
63 OsalMemFree(base);
64 continue;
65 }
66 HDF_LOGD("%{public}s %{public}s", __func__, svrName);
67 HdfSbufReadInt32(reply, &deviceType);
68 if (deviceType != HDF_LOCAL_SERVICE && deviceType != HDF_REMOTE_SERVICE) {
69 HDF_LOGE("device type error %{public}d ", deviceType);
70 OsalMemFree(base);
71 continue;
72 }
73 node->deviceType = deviceType;
74 DListInsertTail(&node->node, &list->list);
75 list->deviceCnt++;
76 }
77
78 return HDF_SUCCESS;
79 }
80
DevmgrQueryDeviceInfo(struct HDIDeviceManager * iDevMgr,struct DeviceInfoList * list,int32_t type)81 static int32_t DevmgrQueryDeviceInfo(struct HDIDeviceManager *iDevMgr, struct DeviceInfoList *list, int32_t type)
82 {
83 struct HdfSBuf *reply = NULL;
84 struct HdfSBuf *data = NULL;
85 int32_t ret;
86
87 reply = HdfSbufTypedObtain(SBUF_IPC);
88 if (reply == NULL) {
89 return HDF_ERR_MALLOC_FAIL;
90 }
91
92 data = HdfSbufTypedObtain(SBUF_IPC);
93 if (data == NULL) {
94 HdfSbufRecycle(reply);
95 return HDF_ERR_MALLOC_FAIL;
96 }
97 do {
98 if (!HdfRemoteServiceWriteInterfaceToken(iDevMgr->remote, data)) {
99 ret = HDF_FAILURE;
100 break;
101 }
102 list->deviceCnt = 0;
103 DListHeadInit(&list->list);
104
105 HdfSbufWriteInt32(data, type);
106 ret = DeviceManagerHdiCall(iDevMgr, DEVMGR_SERVICE_QUERY_DEVICE, data, reply);
107 if (ret != HDF_SUCCESS) {
108 HDF_LOGE("DevmgrProxyQueryDevice failed");
109 break;
110 }
111
112 ret = HdfObtainDeviceInfo(list, reply);
113 } while (0);
114
115 HdfSbufRecycle(reply);
116 HdfSbufRecycle(data);
117 return ret;
118 }
119
DevmgrQueryUsableDeviceInfo(struct HDIDeviceManager * self,struct DeviceInfoList * list)120 static int32_t DevmgrQueryUsableDeviceInfo(struct HDIDeviceManager *self, struct DeviceInfoList *list)
121 {
122 if (self == NULL || list == NULL) {
123 return HDF_ERR_INVALID_PARAM;
124 }
125 return DevmgrQueryDeviceInfo(self, list, HDF_SERVICE_USABLE);
126 }
127
DevmgrQueryUnusableDeviceInfo(struct HDIDeviceManager * self,struct DeviceInfoList * list)128 static int32_t DevmgrQueryUnusableDeviceInfo(struct HDIDeviceManager *self, struct DeviceInfoList *list)
129 {
130 if (self == NULL || list == NULL) {
131 return HDF_ERR_INVALID_PARAM;
132 }
133
134 return DevmgrQueryDeviceInfo(self, list, HDF_SERVICE_UNUSABLE);
135 }
136
DevmgrFreeQueryDeviceListImpl(struct DeviceInfoList * list)137 static void DevmgrFreeQueryDeviceListImpl(struct DeviceInfoList *list)
138 {
139 if (list == NULL) {
140 return;
141 }
142
143 struct DeviceInfoNode *devNode = NULL;
144 struct DeviceInfoNode *tmp = NULL;
145 DLIST_FOR_EACH_ENTRY_SAFE(devNode, tmp, &list->list, struct DeviceInfoNode, node) {
146 DListRemove(&devNode->node);
147 OsalMemFree(devNode);
148 }
149 list->deviceCnt = 0;
150 }
151
DevmgrFreeQueryDeviceList(struct HDIDeviceManager * self,struct DeviceInfoList * list)152 static void DevmgrFreeQueryDeviceList(struct HDIDeviceManager *self, struct DeviceInfoList *list)
153 {
154 (void)self;
155 DevmgrFreeQueryDeviceListImpl(list);
156 }
157
DevmgrLoadDevice(struct HDIDeviceManager * iDevMgr,const char * serviceName)158 int32_t DevmgrLoadDevice(struct HDIDeviceManager *iDevMgr, const char *serviceName)
159 {
160 int32_t status = HDF_FAILURE;
161 if (iDevMgr == NULL || serviceName == NULL) {
162 return HDF_ERR_INVALID_PARAM;
163 }
164 HDF_LOGI("load device: %{public}s", serviceName);
165 struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
166 do {
167 if (data == NULL) {
168 status = HDF_ERR_MALLOC_FAIL;
169 break;
170 }
171 if (!HdfRemoteServiceWriteInterfaceToken(iDevMgr->remote, data)) {
172 status = HDF_FAILURE;
173 break;
174 }
175 if (!HdfSbufWriteString(data, serviceName)) {
176 HDF_LOGE("%{public}s: writing service name failed!", __func__);
177 break;
178 }
179 status = DeviceManagerHdiCall(iDevMgr, DEVMGR_SERVICE_LOAD_DEVICE, data, NULL);
180 if (status != HDF_SUCCESS) {
181 HDF_LOGE("failed to load device %{public}s", serviceName);
182 }
183 } while (0);
184
185 HdfSbufRecycle(data);
186 return status;
187 }
188
DevmgrUnloadDevice(struct HDIDeviceManager * iDevMgr,const char * serviceName)189 int32_t DevmgrUnloadDevice(struct HDIDeviceManager *iDevMgr, const char *serviceName)
190 {
191 int32_t status = HDF_FAILURE;
192 if (iDevMgr == NULL || serviceName == NULL) {
193 return HDF_ERR_INVALID_PARAM;
194 }
195 HDF_LOGI("unload device: %{public}s", serviceName);
196
197 struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
198 do {
199 if (data == NULL) {
200 status = HDF_ERR_MALLOC_FAIL;
201 break;
202 }
203 if (!HdfRemoteServiceWriteInterfaceToken(iDevMgr->remote, data)) {
204 status = HDF_FAILURE;
205 break;
206 }
207 if (!HdfSbufWriteString(data, serviceName)) {
208 HDF_LOGE("%{public}s: writing service name failed!", __func__);
209 break;
210 }
211 status = DeviceManagerHdiCall(iDevMgr, DEVMGR_SERVICE_UNLOAD_DEVICE, data, NULL);
212 if (status != HDF_SUCCESS) {
213 HDF_LOGE("failed to unload device %{public}s", serviceName);
214 }
215 } while (0);
216
217 HdfSbufRecycle(data);
218 return status;
219 }
220
HDIDeviceManagerConstruct(struct HDIDeviceManager * inst)221 static void HDIDeviceManagerConstruct(struct HDIDeviceManager *inst)
222 {
223 inst->FreeQueryDeviceList = DevmgrFreeQueryDeviceList;
224 inst->QueryUsableDeviceInfo = DevmgrQueryUsableDeviceInfo;
225 inst->QueryUnusableDeviceInfo = DevmgrQueryUnusableDeviceInfo;
226 inst->LoadDevice = DevmgrLoadDevice;
227 inst->UnloadDevice = DevmgrUnloadDevice;
228 }
229
HDIDeviceManagerGet(void)230 struct HDIDeviceManager *HDIDeviceManagerGet(void)
231 {
232 struct HDIServiceManager *serviceMgr = HDIServiceManagerGet();
233 if (serviceMgr == NULL) {
234 return NULL;
235 }
236 struct HdfRemoteService *remote = serviceMgr->GetService(serviceMgr, DEVICE_MANAGER_SERVICE);
237 HDIServiceManagerRelease(serviceMgr);
238 if (remote == NULL) {
239 HDF_LOGE("%{public}s: hdi service %{public}s not found", __func__, DEVICE_MANAGER_SERVICE);
240 return NULL;
241 }
242
243 struct HDIDeviceManager *iDevMgr = OsalMemAlloc(sizeof(struct HDIDeviceManager));
244 if (iDevMgr == NULL) {
245 HDF_LOGE("%{public}s: OOM", __func__);
246 HdfRemoteServiceRecycle(remote);
247 return NULL;
248 }
249 if (!HdfRemoteServiceSetInterfaceDesc(remote, "HDI.IDeviceManager.V1_0")) {
250 HDF_LOGE("%{public}s: failed to init interface desc", __func__);
251 HdfRemoteServiceRecycle(remote);
252 return NULL;
253 }
254 iDevMgr->remote = remote;
255 HDIDeviceManagerConstruct(iDevMgr);
256 return iDevMgr;
257 }
258
HDIDeviceManagerRelease(struct HDIDeviceManager * devmgr)259 void HDIDeviceManagerRelease(struct HDIDeviceManager *devmgr)
260 {
261 if (devmgr == NULL) {
262 return;
263 }
264
265 HdfRemoteServiceRecycle(devmgr->remote);
266 OsalMemFree(devmgr);
267 }