1 /*
2 * Copyright (c) 2023 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 <unistd.h>
17 #include "devhost_dump.h"
18 #include "devhost_dump_reg.h"
19 #include "hdf_base.h"
20 #include "hdf_cstring.h"
21 #include "hdf_dlist.h"
22 #include "hdf_core_log.h"
23 #include "osal_mem.h"
24 #include "osal_mutex.h"
25 #include "hdf_dump_reg.h"
26
27 #define HDF_LOG_TAG devhost_dump
28
29 struct DumpServiceNode {
30 DevHostDumpFunc dumpService;
31 char *servName;
32 struct DListHead node;
33 };
34
35 struct DumpHostNode {
36 struct DListHead list;
37 struct OsalMutex mutex;
38 DevHostDumpFunc dumpHost;
39 };
40
41 static struct DumpHostNode g_dumpHostNode;
42
DevHostDumpInit(void)43 void DevHostDumpInit(void)
44 {
45 OsalMutexInit(&g_dumpHostNode.mutex);
46 DListHeadInit(&g_dumpHostNode.list);
47 g_dumpHostNode.dumpHost = NULL;
48 }
49
DevHostDumpDeInit(void)50 void DevHostDumpDeInit(void)
51 {
52 struct DumpServiceNode *pos = NULL;
53 struct DumpServiceNode *tmp = NULL;
54
55 OsalMutexLock(&g_dumpHostNode.mutex);
56 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &g_dumpHostNode.list, struct DumpServiceNode, node) {
57 DListRemove(&pos->node);
58 OsalMemFree(pos->servName);
59 OsalMemFree(pos);
60 }
61 OsalMutexUnlock(&g_dumpHostNode.mutex);
62
63 OsalMutexDestroy(&g_dumpHostNode.mutex);
64 DListHeadInit(&g_dumpHostNode.list);
65 g_dumpHostNode.dumpHost = NULL;
66 }
67
DevHostCheckDumpExist(const char * servName)68 static bool DevHostCheckDumpExist(const char *servName)
69 {
70 struct DumpServiceNode *pos = NULL;
71 bool findFlag = false;
72 OsalMutexLock(&g_dumpHostNode.mutex);
73 DLIST_FOR_EACH_ENTRY(pos, &g_dumpHostNode.list, struct DumpServiceNode, node) {
74 if (strcmp(pos->servName, servName) == 0) {
75 findFlag = true;
76 break;
77 }
78 }
79 OsalMutexUnlock(&g_dumpHostNode.mutex);
80 return findFlag;
81 }
82
DevHostRegisterDumpService(const char * servName,DevHostDumpFunc dump)83 int32_t DevHostRegisterDumpService(const char *servName, DevHostDumpFunc dump)
84 {
85 if (dump == NULL || servName == NULL) {
86 return HDF_FAILURE;
87 }
88
89 if (DevHostCheckDumpExist(servName)) {
90 HDF_LOGE("%{public}s service %{public}s dump function exist", __func__, servName);
91 return HDF_FAILURE;
92 }
93
94 struct DumpServiceNode *node = (struct DumpServiceNode *)OsalMemCalloc(sizeof(*node));
95 if (node == NULL) {
96 return HDF_FAILURE;
97 }
98
99 HDF_LOGI("%{public}s enter", __func__);
100 node->dumpService = dump;
101 node->servName = HdfStringCopy(servName);
102 if (node->servName == NULL) {
103 OsalMemFree(node);
104 return HDF_FAILURE;
105 }
106 OsalMutexLock(&g_dumpHostNode.mutex);
107 DListInsertTail(&node->node, &g_dumpHostNode.list);
108 OsalMutexUnlock(&g_dumpHostNode.mutex);
109
110 return HDF_SUCCESS;
111 }
112
DevHostRegisterDumpHost(DevHostDumpFunc dump)113 int32_t DevHostRegisterDumpHost(DevHostDumpFunc dump)
114 {
115 if (dump == NULL) {
116 return HDF_FAILURE;
117 }
118
119 g_dumpHostNode.dumpHost = dump;
120
121 return HDF_SUCCESS;
122 }
123
DevHostDumpIpc(struct HdfSBuf * data)124 static void DevHostDumpIpc(struct HdfSBuf *data)
125 {
126 int fd = HdfSbufReadFileDescriptor(data);
127 if (fd < 0) {
128 HDF_LOGE("invalid fd %{public}d", fd);
129 return;
130 }
131 HDF_LOGI("%{public}s %{public}d", __func__, fd);
132
133 const char *dumpCmd = HdfSbufReadString(data);
134 if (dumpCmd == NULL) {
135 HDF_LOGE("ipc dumpCmd is NULL");
136 close(fd);
137 fd = -1;
138 return;
139 }
140
141 HdfDumpIpcStat(fd, dumpCmd);
142 close(fd);
143 fd = -1;
144 return;
145 }
146
DevHostDump(struct HdfSBuf * data,struct HdfSBuf * reply)147 void DevHostDump(struct HdfSBuf *data, struct HdfSBuf *reply)
148 {
149 if (data == NULL || reply == NULL) {
150 return;
151 }
152
153 const char *option = HdfSbufReadString(data);
154 if (option == NULL) {
155 return;
156 }
157
158 if (strcmp(option, "dumpHost") == 0) {
159 if (g_dumpHostNode.dumpHost == NULL) {
160 HDF_LOGE("%{public}s no dumpHost function", __func__);
161 (void)HdfSbufWriteString(reply, "The host does not register dump function\n");
162 return;
163 }
164 g_dumpHostNode.dumpHost(data, reply);
165 } else if (strcmp(option, "dumpService") == 0) {
166 const char *servName = HdfSbufReadString(data);
167 struct DumpServiceNode *pos = NULL;
168 bool dumpFlag = false;
169 OsalMutexLock(&g_dumpHostNode.mutex);
170 DLIST_FOR_EACH_ENTRY(pos, &g_dumpHostNode.list, struct DumpServiceNode, node) {
171 if (strcmp(pos->servName, servName) != 0) {
172 continue;
173 }
174 if (pos->dumpService) {
175 pos->dumpService(data, reply);
176 dumpFlag = true;
177 break;
178 }
179 }
180 OsalMutexUnlock(&g_dumpHostNode.mutex);
181 if (!dumpFlag) {
182 (void)HdfSbufWriteString(reply, "The service does not register dump function\n");
183 }
184 } else if (strcmp(option, "--ipc") == 0) {
185 DevHostDumpIpc(data);
186 } else {
187 HDF_LOGE("%{public}s invalid parameter %{public}s", __func__, option);
188 }
189
190 return;
191 }
192