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 char *base = NULL;
49 int32_t deviceType;
50
51 while ((svrName = HdfSbufReadString(reply))) {
52 const size_t svrNameLen = strlen(svrName) + 1;
53 base = (char *)OsalMemCalloc(sizeof(*node) + svrNameLen);
54 if (base == NULL) {
55 DevmgrFreeQueryDeviceListImpl(list);
56 return HDF_FAILURE;
57 }
58 node = (struct DeviceInfoNode *)base;
59 node->svcName = base + sizeof(*node);
60 if (strcpy_s(node->svcName, svrNameLen, svrName) != EOK) {
61 HDF_LOGE("strcpy service name %{public}s failed", svrName);
62 OsalMemFree(base);
63 continue;
64 }
65 HDF_LOGD("%{public}s %{public}s", __func__, svrName);
66 HdfSbufReadInt32(reply, &deviceType);
67 if (deviceType != HDF_LOCAL_SERVICE && deviceType != HDF_REMOTE_SERVICE) {
68 HDF_LOGE("device type error %{public}d ", deviceType);
69 OsalMemFree(base);
70 continue;
71 }
72 node->deviceType = deviceType;
73 DListInsertTail(&node->node, &list->list);
74 list->deviceCnt++;
75 }
76
77 return HDF_SUCCESS;
78 }
79
DevmgrQueryDeviceInfo(struct HDIDeviceManager * iDevMgr,struct DeviceInfoList * list,int32_t type)80 static int32_t DevmgrQueryDeviceInfo(struct HDIDeviceManager *iDevMgr, struct DeviceInfoList *list, int32_t type)
81 {
82 struct HdfSBuf *reply = NULL;
83 struct HdfSBuf *data = NULL;
84 int32_t ret;
85
86 reply = HdfSbufTypedObtain(SBUF_IPC);
87 if (reply == NULL) {
88 return HDF_ERR_MALLOC_FAIL;
89 }
90
91 data = HdfSbufTypedObtain(SBUF_IPC);
92 if (data == NULL) {
93 HdfSbufRecycle(reply);
94 return HDF_ERR_MALLOC_FAIL;
95 }
96 do {
97 if (!HdfRemoteServiceWriteInterfaceToken(iDevMgr->remote, data)) {
98 ret = HDF_FAILURE;
99 break;
100 }
101 list->deviceCnt = 0;
102 DListHeadInit(&list->list);
103
104 HdfSbufWriteInt32(data, type);
105 ret = DeviceManagerHdiCall(iDevMgr, DEVMGR_SERVICE_QUERY_DEVICE, data, reply);
106 if (ret != HDF_SUCCESS) {
107 HDF_LOGE("DevmgrProxyQueryDevice failed");
108 break;
109 }
110
111 ret = HdfObtainDeviceInfo(list, reply);
112 } while (0);
113
114 HdfSbufRecycle(reply);
115 HdfSbufRecycle(data);
116 return ret;
117 }
118
DevmgrQueryUsableDeviceInfo(struct HDIDeviceManager * self,struct DeviceInfoList * list)119 static int32_t DevmgrQueryUsableDeviceInfo(struct HDIDeviceManager *self, struct DeviceInfoList *list)
120 {
121 if (self == NULL || list == NULL) {
122 return HDF_ERR_INVALID_PARAM;
123 }
124 return DevmgrQueryDeviceInfo(self, list, HDF_SERVICE_USABLE);
125 }
126
DevmgrQueryUnusableDeviceInfo(struct HDIDeviceManager * self,struct DeviceInfoList * list)127 static int32_t DevmgrQueryUnusableDeviceInfo(struct HDIDeviceManager *self, struct DeviceInfoList *list)
128 {
129 if (self == NULL || list == NULL) {
130 return HDF_ERR_INVALID_PARAM;
131 }
132
133 return DevmgrQueryDeviceInfo(self, list, HDF_SERVICE_UNUSABLE);
134 }
135
DevmgrFreeQueryDeviceListImpl(struct DeviceInfoList * list)136 static void DevmgrFreeQueryDeviceListImpl(struct DeviceInfoList *list)
137 {
138 if (list == NULL) {
139 return;
140 }
141
142 struct DeviceInfoNode *devNode = NULL;
143 struct DeviceInfoNode *tmp = NULL;
144 DLIST_FOR_EACH_ENTRY_SAFE(devNode, tmp, &list->list, struct DeviceInfoNode, node) {
145 DListRemove(&devNode->node);
146 OsalMemFree(devNode);
147 }
148 list->deviceCnt = 0;
149 }
150
DevmgrFreeQueryDeviceList(struct HDIDeviceManager * self,struct DeviceInfoList * list)151 static void DevmgrFreeQueryDeviceList(struct HDIDeviceManager *self, struct DeviceInfoList *list)
152 {
153 (void)self;
154 DevmgrFreeQueryDeviceListImpl(list);
155 }
156
DevmgrProcessLoad(struct HDIDeviceManager * iDevMgr,const char * serviceName,int32_t id)157 static int32_t DevmgrProcessLoad(struct HDIDeviceManager *iDevMgr, const char *serviceName, int32_t id)
158 {
159 int32_t status = HDF_FAILURE;
160 struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
161 do {
162 if (data == NULL) {
163 status = HDF_ERR_MALLOC_FAIL;
164 break;
165 }
166 if (!HdfRemoteServiceWriteInterfaceToken(iDevMgr->remote, data)) {
167 status = HDF_FAILURE;
168 break;
169 }
170 if (!HdfSbufWriteString(data, serviceName)) {
171 HDF_LOGE("%{public}s: writing service name failed!", __func__);
172 break;
173 }
174 status = DeviceManagerHdiCall(iDevMgr, id, data, NULL);
175 if (status != HDF_SUCCESS) {
176 HDF_LOGE("failed to process load/unload device %{public}s code:%{public}d", serviceName, id);
177 }
178 } while (0);
179
180 HdfSbufRecycle(data);
181 return status;
182 }
183
DevmgrLoadDevice(struct HDIDeviceManager * iDevMgr,const char * serviceName)184 int32_t DevmgrLoadDevice(struct HDIDeviceManager *iDevMgr, const char *serviceName)
185 {
186 if (iDevMgr == NULL || serviceName == NULL) {
187 return HDF_ERR_INVALID_PARAM;
188 }
189
190 HDF_LOGI("load device: %{public}s", serviceName);
191
192 return DevmgrProcessLoad(iDevMgr, serviceName, DEVMGR_SERVICE_LOAD_DEVICE);
193 }
194
DevmgrUnloadDevice(struct HDIDeviceManager * iDevMgr,const char * serviceName)195 int32_t DevmgrUnloadDevice(struct HDIDeviceManager *iDevMgr, const char *serviceName)
196 {
197 if (iDevMgr == NULL || serviceName == NULL) {
198 return HDF_ERR_INVALID_PARAM;
199 }
200
201 HDF_LOGI("unload device: %{public}s", serviceName);
202
203 return DevmgrProcessLoad(iDevMgr, serviceName, DEVMGR_SERVICE_UNLOAD_DEVICE);
204 }
205
HDIDeviceManagerConstruct(struct HDIDeviceManager * inst)206 static void HDIDeviceManagerConstruct(struct HDIDeviceManager *inst)
207 {
208 inst->FreeQueryDeviceList = DevmgrFreeQueryDeviceList;
209 inst->QueryUsableDeviceInfo = DevmgrQueryUsableDeviceInfo;
210 inst->QueryUnusableDeviceInfo = DevmgrQueryUnusableDeviceInfo;
211 inst->LoadDevice = DevmgrLoadDevice;
212 inst->UnloadDevice = DevmgrUnloadDevice;
213 }
214
HDIDeviceManagerGet(void)215 struct HDIDeviceManager *HDIDeviceManagerGet(void)
216 {
217 struct HDIServiceManager *serviceMgr = HDIServiceManagerGet();
218 if (serviceMgr == NULL) {
219 return NULL;
220 }
221 struct HdfRemoteService *remote = serviceMgr->GetService(serviceMgr, DEVICE_MANAGER_SERVICE);
222 HDIServiceManagerRelease(serviceMgr);
223 if (remote == NULL) {
224 HDF_LOGE("%{public}s: hdi service %{public}s not found", __func__, DEVICE_MANAGER_SERVICE);
225 return NULL;
226 }
227
228 struct HDIDeviceManager *iDevMgr = OsalMemAlloc(sizeof(struct HDIDeviceManager));
229 if (iDevMgr == NULL) {
230 HDF_LOGE("%{public}s: OOM", __func__);
231 HdfRemoteServiceRecycle(remote);
232 return NULL;
233 }
234 if (!HdfRemoteServiceSetInterfaceDesc(remote, "HDI.IDeviceManager.V1_0")) {
235 HDF_LOGE("%{public}s: failed to init interface desc", __func__);
236 HdfRemoteServiceRecycle(remote);
237 HDIDeviceManagerRelease(iDevMgr);
238 return NULL;
239 }
240 iDevMgr->remote = remote;
241 HDIDeviceManagerConstruct(iDevMgr);
242 return iDevMgr;
243 }
244
HDIDeviceManagerRelease(struct HDIDeviceManager * devmgr)245 void HDIDeviceManagerRelease(struct HDIDeviceManager *devmgr)
246 {
247 if (devmgr == NULL) {
248 return;
249 }
250
251 HdfRemoteServiceRecycle(devmgr->remote);
252 OsalMemFree(devmgr);
253 }