1 /*
2 * Copyright (c) 2022-2023 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 <algorithm>
10 #include <hdf_io_service.h>
11 #include <idevmgr_hdi.h>
12 #include <iostream>
13 #include <iservmgr_hdi.h>
14 #include <osal_time.h>
15 #include <string>
16 #include <string_ex.h>
17 #include <vector>
18
19 #define HDF_LOG_TAG hdf_dbg
20
21 static constexpr uint32_t DATA_SIZE = 5000;
22 static constexpr uint32_t FUNC_IDX = 1;
23 static constexpr uint32_t SERVER_NAME_IDX = 3;
24 static constexpr uint32_t INTERFACE_DESC_IDX = 4;
25 static constexpr uint32_t CMD_ID_IDX = 5;
26 static constexpr uint32_t PARA_CNT_IDX = 6;
27 static constexpr uint32_t PARA_MULTIPLE = 2;
28 static constexpr uint32_t WAIT_TIME = 100;
29 static constexpr uint32_t HELP_INFO_PARA_CNT = 2;
30 static constexpr uint32_t GET_INFO_FUNC_NUMS = 5;
31 static constexpr int32_t DBG_HDI_PARA_MIN_LEN = 7;
32 static constexpr int32_t DBG_HDI_SERVICE_LOAD_IDX = 2;
33 static constexpr int32_t QUERY_INFO_PARA_CNT = 3;
34 static constexpr int32_t ALIGN_SIZE = 30;
35 static constexpr int32_t PARAM_IN_OUT_SIZE = 2;
36 static constexpr int32_t PARAM_IN_SIZE = 1;
37 static constexpr int32_t PARAM_IN_IDX = 0;
38 static constexpr int32_t PARAM_OUT_IDX = 1;
39 static constexpr const char *HELP_COMMENT =
40 " hdf_dbg menu: \n"
41 " hdf_dbg -h :display help information\n"
42 " hdf_dbg -q :query all service and device information\n"
43 " hdf_dbg -q 0 :query service information of kernel space\n"
44 " hdf_dbg -q 1 :query service information of user space\n"
45 " hdf_dbg -q 2 :query device information of kernel space\n"
46 " hdf_dbg -q 3 :query device information use space\n"
47 " hdf_dbg -d :debug hdi interface\n"
48 " detailed usage:\n"
49 " debug hdi interface, parameterType can be int or string now, for example:\n"
50 " hdf_dbg -d loadFlag serviceName interfaceToken cmd parameterInCount parameterInType parameterInValue\n"
51 " hdf_dbg -d loadFlag serviceName interfaceToken cmd parameterInCount,parameterOutCount parameterInType "
52 "parameterInValue parameterOutType\n"
53 " detailed examples:\n"
54 " hdf_dbg -d 1 sample_driver_service hdf.test.sampele_service 1 2 int 100 int 200\n"
55 " hdf_dbg -d 1 sample_driver_service hdf.test.sampele_service 1 2,1 int 100 int 200 int\n"
56 " hdf_dbg -d 0 sample_driver_service hdf.test.sampele_service 7 1 string foo\n";
57
58 using GetInfoFunc = void (*)();
59 static void GetAllServiceUserSpace();
60 static void GetAllServiceKernelSpace();
61 static void GetAllDeviceUserSpace();
62 static void GetAllDeviceKernelSpace();
63 static void GetAllInformation();
64
65 GetInfoFunc g_getInfoFuncs[GET_INFO_FUNC_NUMS] = {
66 GetAllServiceKernelSpace,
67 GetAllServiceUserSpace,
68 GetAllDeviceKernelSpace,
69 GetAllDeviceUserSpace,
70 GetAllInformation,
71 };
72
73 using OHOS::MessageOption;
74 using OHOS::MessageParcel;
75 using OHOS::HDI::DeviceManager::V1_0::HdiDevHostInfo;
76 using OHOS::HDI::DeviceManager::V1_0::IDeviceManager;
77 using OHOS::HDI::ServiceManager::V1_0::HdiServiceInfo;
78 using OHOS::HDI::ServiceManager::V1_0::IServiceManager;
79 using std::cout;
80 using std::endl;
81
82 class HdfDbg {
83 public:
84 bool loadDevice;
85 std::string serviceName;
86 std::u16string descriptor;
87 int32_t cmd;
88 int32_t inParam;
89 int32_t outParam;
90 std::vector<std::vector<std::string>> inParamVec;
91 std::vector<std::string> outParamVec;
92 };
93
PrintHelp()94 static void PrintHelp()
95 {
96 cout << HELP_COMMENT;
97 }
98
StrToInt(std::string tempstr)99 static int StrToInt(std::string tempstr)
100 {
101 int32_t num = GET_INFO_FUNC_NUMS;
102 if (std::all_of(tempstr.begin(), tempstr.end(), ::isdigit)) {
103 num = std::stoi(tempstr);
104 }
105 return num;
106 }
107
SetPadAlign(std::string & name,char padChar,int32_t size)108 static void SetPadAlign(std::string &name, char padChar, int32_t size)
109 {
110 int32_t padCnt = size - static_cast<int32_t>(name.length());
111
112 padCnt = (padCnt <= 0) ? 0 : padCnt;
113 name.append(padCnt, padChar);
114 }
115
PrintAllServiceInfoUser(std::vector<HdiServiceInfo> & serviceInfos)116 static void PrintAllServiceInfoUser(std::vector<HdiServiceInfo> &serviceInfos)
117 {
118 uint32_t cnt = 0;
119 std::string titleName = "serviceName";
120 SetPadAlign(titleName, ' ', ALIGN_SIZE);
121
122 cout << "display service info in user space, format:" << endl;
123 cout << titleName << ":devClass" << "\t:devId" << endl;
124
125 for (auto &info : serviceInfos) {
126 SetPadAlign(info.serviceName, ' ', ALIGN_SIZE);
127 cout << info.serviceName << ":0x" << std::hex << info.devClass << "\t:0x" << info.devId << endl;
128 cnt++;
129 }
130
131 cout << "total " << std::dec << cnt << " services in user space" << endl;
132 }
133
PrintAllServiceInfoKernel(struct HdfSBuf * data,bool flag)134 static void PrintAllServiceInfoKernel(struct HdfSBuf *data, bool flag)
135 {
136 uint32_t cnt = 0;
137 std::string titleName = "serviceName";
138
139 SetPadAlign(titleName, ' ', ALIGN_SIZE);
140 cout << "display service info in kernel space, format:" << endl;
141 cout << titleName << ":devClass" << "\t:devId" << endl;
142
143 while (flag) {
144 const char *servName = HdfSbufReadString(data);
145 if (servName == nullptr) {
146 break;
147 }
148
149 uint16_t devClass;
150 if (!HdfSbufReadUint16(data, &devClass)) {
151 return;
152 }
153
154 uint32_t devId;
155 if (!HdfSbufReadUint32(data, &devId)) {
156 return;
157 }
158
159 std::string serviceName = servName;
160 SetPadAlign(serviceName, ' ', ALIGN_SIZE);
161 cout << serviceName << ":0x" << std::hex << devClass << "\t:0x" << devId << endl;
162 cnt++;
163 }
164
165 cout << "total " << std::dec << cnt << " services in kernel space" << endl;
166 }
167
PrintALLDeviceInfoUser(std::vector<HdiDevHostInfo> & deviceInfos)168 static void PrintALLDeviceInfoUser(std::vector<HdiDevHostInfo> &deviceInfos)
169 {
170 cout << "display device info in user space, format:" << endl;
171 std::string titleHostName = "hostName";
172 SetPadAlign(titleHostName, ' ', ALIGN_SIZE);
173
174 cout << titleHostName << ":hostId" << endl;
175
176 std::string titleDevName = "deviceName";
177 std::string titleSrvName = ":serviceName";
178 SetPadAlign(titleDevName, ' ', ALIGN_SIZE);
179 SetPadAlign(titleSrvName, ' ', ALIGN_SIZE);
180
181 cout << "\t" << titleDevName << ":deviceId \t" << titleSrvName << endl;
182 uint32_t hostCnt = 0;
183 uint32_t devNodeCnt = 0;
184
185 for (auto &info : deviceInfos) {
186 SetPadAlign(info.hostName, ' ', ALIGN_SIZE);
187 cout << info.hostName << ":0x" << std::hex << info.hostId << endl;
188 for (auto &dev : info.devInfo) {
189 SetPadAlign(dev.deviceName, ' ', ALIGN_SIZE);
190 SetPadAlign(dev.servName, ' ', ALIGN_SIZE);
191 cout << "\t" << dev.deviceName << ":0x" << std::hex << dev.devId << "\t:" << dev.servName << endl;
192 devNodeCnt++;
193 }
194 hostCnt++;
195 }
196
197 cout << "total " << std::dec << hostCnt << " hosts, " << devNodeCnt << " devNodes in user space" << endl;
198 }
199
PrintOneHostInfoKernel(struct HdfSBuf * data,uint32_t & devNodeCnt)200 static int32_t PrintOneHostInfoKernel(struct HdfSBuf *data, uint32_t &devNodeCnt)
201 {
202 const char *hostName = HdfSbufReadString(data);
203 if (hostName == nullptr) {
204 return HDF_FAILURE;
205 }
206
207 uint32_t hostId;
208 if (!HdfSbufReadUint32(data, &hostId)) {
209 cout << "PrintOneHostInfoKernel HdfSbufReadUint32 hostId failed" << endl;
210 return HDF_FAILURE;
211 }
212
213 std::string hostNameStr = hostName;
214 SetPadAlign(hostNameStr, ' ', ALIGN_SIZE);
215 cout << hostNameStr << ":0x" << std::hex << hostId << endl;
216
217 uint32_t devCnt;
218 if (!HdfSbufReadUint32(data, &devCnt)) {
219 cout << "PrintOneHostInfoKernel HdfSbufReadUint32 devCnt failed" << endl;
220 return HDF_FAILURE;
221 }
222
223 for (uint32_t i = 0; i < devCnt; i++) {
224 const char *str = HdfSbufReadString(data);
225 std::string deviceName = (str == nullptr) ? "" : str;
226 SetPadAlign(deviceName, ' ', ALIGN_SIZE);
227
228 uint32_t devId;
229 if (!HdfSbufReadUint32(data, &devId)) {
230 cout << "PrintOneHostInfoKernel HdfSbufReadUint32 devId failed" << endl;
231 return HDF_FAILURE;
232 }
233
234 str = HdfSbufReadString(data);
235 std::string servName = (str == nullptr) ? "" : str;
236 SetPadAlign(servName, ' ', ALIGN_SIZE);
237 cout << "\t" << deviceName << ":0x" << std::hex << devId << "\t:" << servName << endl;
238 }
239 devNodeCnt += devCnt;
240
241 return HDF_SUCCESS;
242 }
PrintAllDeviceInfoKernel(struct HdfSBuf * data,bool flag)243 static void PrintAllDeviceInfoKernel(struct HdfSBuf *data, bool flag)
244 {
245 uint32_t hostCnt = 0;
246 uint32_t devNodeCnt = 0;
247
248 std::string titleHostName = "hostName";
249 SetPadAlign(titleHostName, ' ', ALIGN_SIZE);
250 cout << "display device info in kernel space, format:" << endl;
251 cout << titleHostName << ":hostId" << endl;
252
253 std::string titleDevName = "deviceName";
254 std::string titleSrvName = "serviceName";
255 SetPadAlign(titleDevName, ' ', ALIGN_SIZE);
256 SetPadAlign(titleSrvName, ' ', ALIGN_SIZE);
257 cout << "\t" << titleDevName << ":deviceId \t:" << titleSrvName << endl;
258
259 while (flag) {
260 if (PrintOneHostInfoKernel(data, devNodeCnt) == HDF_FAILURE) {
261 break;
262 }
263 hostCnt++;
264 }
265
266 cout << "total " << std::dec << hostCnt << " hosts, " << devNodeCnt << " devNodes in kernel space" << endl;
267 }
268
ParseParameterCount(int argc,char ** argv,HdfDbg & info)269 static bool ParseParameterCount(int argc, char **argv, HdfDbg &info)
270 {
271 std::string paramCount = argv[PARA_CNT_IDX];
272 std::vector<std::string> result;
273 OHOS::SplitStr(paramCount, ",", result);
274 info.inParam = 0;
275 info.outParam = 0;
276 if (result.size() == PARAM_IN_SIZE) {
277 info.inParam = StrToInt(result[PARAM_IN_IDX]);
278 } else if (result.size() == PARAM_IN_OUT_SIZE) {
279 info.inParam = StrToInt(result[PARAM_IN_IDX]);
280 info.outParam = StrToInt(result[PARAM_OUT_IDX]);
281 } else {
282 cout << "parameter count parse failed, input: " << paramCount <<
283 " it should be paramIn,paramOut or paramIn" << endl;
284 return false;
285 }
286 if ((info.inParam * PARA_MULTIPLE + info.outParam) != (argc - PARA_CNT_IDX - 1)) {
287 cout << "parameter count error, please check your input and output parameters" << endl;
288 return false;
289 }
290 return true;
291 }
292
ParseParameterIn(int argc,char ** argv,HdfDbg & info)293 static bool ParseParameterIn(int argc, char **argv, HdfDbg &info)
294 {
295 int32_t paraTypeIdx = PARA_CNT_IDX + 1;
296 for (int32_t i = 0; i < info.inParam; i++) {
297 int32_t paraValueIdx = paraTypeIdx + 1;
298 if (strcmp(argv[paraTypeIdx], "string") != 0 && strcmp(argv[paraTypeIdx], "int") != 0) {
299 cout << "parameterType not support:" << argv[paraTypeIdx] << endl;
300 return false;
301 }
302 info.inParamVec.push_back(std::vector<std::string>());
303 info.inParamVec[i].push_back(argv[paraTypeIdx]);
304 info.inParamVec[i].push_back(argv[paraValueIdx]);
305 paraTypeIdx += PARA_MULTIPLE;
306 }
307 return true;
308 }
309
ParseParameterOut(int argc,char ** argv,HdfDbg & info)310 static bool ParseParameterOut(int argc, char **argv, HdfDbg &info)
311 {
312 int32_t paraTypeIdx = PARA_CNT_IDX + 1 + info.inParam * PARA_MULTIPLE;
313 for (int32_t i = 0; i < info.outParam; i++) {
314 if (strcmp(argv[paraTypeIdx], "string") != 0 && strcmp(argv[paraTypeIdx], "int") != 0) {
315 cout << "parameterType not support:" << argv[paraTypeIdx] << endl;
316 return false;
317 }
318 info.outParamVec.push_back(argv[paraTypeIdx]);
319 paraTypeIdx++;
320 }
321 return true;
322 }
323
ParseHdfDbg(int argc,char ** argv,HdfDbg & info)324 static bool ParseHdfDbg(int argc, char **argv, HdfDbg &info)
325 {
326 if (argc < DBG_HDI_PARA_MIN_LEN) {
327 return false;
328 }
329 info.loadDevice = strcmp(argv[DBG_HDI_SERVICE_LOAD_IDX], "1") == 0 ? true : false;
330 info.serviceName = argv[SERVER_NAME_IDX];
331 info.descriptor = OHOS::Str8ToStr16(argv[INTERFACE_DESC_IDX]);
332 info.cmd = StrToInt(argv[CMD_ID_IDX]);
333 if (!ParseParameterCount(argc, argv, info) || !ParseParameterIn(argc, argv, info) ||
334 !ParseParameterOut(argc, argv, info)) {
335 return false;
336 }
337 return true;
338 }
339
InjectDebugHdi(int argc,char ** argv)340 static int32_t InjectDebugHdi(int argc, char **argv)
341 {
342 HdfDbg info;
343 if (!ParseHdfDbg(argc, argv, info)) {
344 PrintHelp();
345 return HDF_FAILURE;
346 }
347 auto servmgr = IServiceManager::Get();
348 auto devmgr = IDeviceManager::Get();
349 if (info.loadDevice) {
350 devmgr->LoadDevice(info.serviceName);
351 OsalMSleep(WAIT_TIME);
352 }
353 MessageParcel data;
354 data.WriteInterfaceToken(info.descriptor);
355 for (int32_t i = 0; i < info.inParam; i++) {
356 if (info.inParamVec[i][0] == "string") {
357 data.WriteCString(info.inParamVec[i][1].c_str());
358 } else {
359 data.WriteInt32(StrToInt(info.inParamVec[i][1]));
360 }
361 }
362 MessageParcel reply;
363 MessageOption option;
364 int32_t ret = HDF_FAILURE;
365 auto service = servmgr->GetService(info.serviceName.c_str());
366 if (service == nullptr) {
367 cout << "getService " << info.serviceName << " failed" << endl;
368 goto END;
369 }
370 ret = service->SendRequest(info.cmd, data, reply, option);
371 cout << "call service " << info.serviceName << " hdi cmd:" << info.cmd << " return:" << ret << endl;
372 for (int32_t i = 0; i < info.outParam; i++) {
373 if (info.outParamVec[i] == "string") {
374 cout << "output parameter" << i << ": parameterType is string, parameterValue is " <<
375 reply.ReadCString() << endl;
376 } else {
377 int32_t replyInt;
378 reply.ReadInt32(replyInt);
379 cout << "output parameter" << i << ": parameterType is int, parameterValue is " << replyInt << endl;
380 }
381 }
382 END:
383 if (info.loadDevice) {
384 devmgr->UnloadDevice(info.serviceName);
385 }
386 return ret;
387 }
388
GetAllServiceUserSpace()389 static void GetAllServiceUserSpace()
390 {
391 auto servmgr = IServiceManager::Get();
392 if (servmgr == nullptr) {
393 cout << "GetAllServiceUserSpace get ServiceManager failed" << endl;
394 return;
395 }
396
397 std::vector<HdiServiceInfo> serviceInfos;
398 (void)servmgr->ListAllService(serviceInfos);
399
400 PrintAllServiceInfoUser(serviceInfos);
401 }
402
GetAllServiceKernelSpace()403 static void GetAllServiceKernelSpace()
404 {
405 struct HdfSBuf *data = HdfSbufObtain(DATA_SIZE);
406 if (data == nullptr) {
407 cout << "GetAllServiceKernelSpace HdfSbufObtain failed" << endl;
408 return;
409 }
410
411 int32_t ret = HdfListAllService(data);
412 OsalMSleep(WAIT_TIME);
413 if (ret == HDF_SUCCESS) {
414 PrintAllServiceInfoKernel(data, true);
415 } else {
416 PrintAllServiceInfoKernel(data, false);
417 }
418
419 HdfSbufRecycle(data);
420 }
421
GetAllDeviceUserSpace()422 static void GetAllDeviceUserSpace()
423 {
424 auto devmgr = IDeviceManager::Get();
425 if (devmgr == nullptr) {
426 cout << "GetAllDeviceUserSpace get DeviceManager failed" << endl;
427 return;
428 }
429
430 std::vector<HdiDevHostInfo> deviceInfos;
431 (void)devmgr->ListAllDevice(deviceInfos);
432 PrintALLDeviceInfoUser(deviceInfos);
433 }
434
GetAllDeviceKernelSpace()435 static void GetAllDeviceKernelSpace()
436 {
437 struct HdfSBuf *data = HdfSbufObtain(DATA_SIZE);
438 if (data == nullptr) {
439 cout << "GetAllDeviceKernelSpace HdfSbufObtain failed" << endl;
440 return;
441 }
442
443 int32_t ret = HdfListAllDevice(data);
444 OsalMSleep(WAIT_TIME);
445 if (ret == HDF_SUCCESS) {
446 PrintAllDeviceInfoKernel(data, true);
447 } else {
448 PrintAllDeviceInfoKernel(data, false);
449 }
450
451 HdfSbufRecycle(data);
452 }
453
GetAllInformation()454 static void GetAllInformation()
455 {
456 GetAllServiceUserSpace();
457 cout << endl;
458 GetAllServiceKernelSpace();
459 cout << endl;
460 GetAllDeviceUserSpace();
461 cout << endl;
462 GetAllDeviceKernelSpace();
463 }
464
main(int argc,char ** argv)465 int main(int argc, char **argv)
466 {
467 if (argc == 1 || (argc == HELP_INFO_PARA_CNT && strcmp(argv[FUNC_IDX], "-h") == 0)) {
468 PrintHelp();
469 } else if (argc == QUERY_INFO_PARA_CNT || argc == QUERY_INFO_PARA_CNT - 1) {
470 if (strcmp(argv[FUNC_IDX], "-q") != 0) {
471 PrintHelp();
472 return HDF_FAILURE;
473 }
474
475 if (argc == QUERY_INFO_PARA_CNT - 1) {
476 g_getInfoFuncs[GET_INFO_FUNC_NUMS - 1]();
477 return HDF_SUCCESS;
478 }
479 std::string argvStr = argv[QUERY_INFO_PARA_CNT - 1];
480 uint32_t queryIdx = static_cast<uint32_t>(StrToInt(argvStr));
481 if (queryIdx < GET_INFO_FUNC_NUMS - 1) {
482 g_getInfoFuncs[queryIdx]();
483 } else {
484 PrintHelp();
485 return HDF_FAILURE;
486 }
487 } else if (argc > QUERY_INFO_PARA_CNT) {
488 if (strcmp(argv[FUNC_IDX], "-d") == 0) {
489 return InjectDebugHdi(argc, argv);
490 } else {
491 PrintHelp();
492 return HDF_FAILURE;
493 }
494 }
495
496 return HDF_SUCCESS;
497 }
498