1 /*
2 * Copyright (c) 2021-2024 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 "virtual_device.h"
17
18 #include <getopt.h>
19 #include <sys/stat.h>
20
21 #include "virtual_finger.h"
22 #include "virtual_gamepad.h"
23 #include "virtual_joystick.h"
24 #include "virtual_keyboard.h"
25 #include "virtual_keyboard_sys_ctrl.h"
26 #include "virtual_keyboard_consumer_ctrl.h"
27 #include "virtual_keyboard_ext.h"
28 #include "virtual_knob.h"
29 #include "virtual_knob_sys_ctrl.h"
30 #include "virtual_knob_consumer_ctrl.h"
31 #include "virtual_knob_mouse.h"
32 #include "virtual_mouse.h"
33 #include "virtual_pen.h"
34 #include "virtual_pen_mouse.h"
35 #include "virtual_pen_keyboard.h"
36 #include "virtual_remote_control.h"
37 #include "virtual_single_finger.h"
38 #include "virtual_single_touchscreen.h"
39 #include "virtual_stylus.h"
40 #include "virtual_trackball.h"
41 #include "virtual_trackpad.h"
42 #include "virtual_trackpad_sys_ctrl.h"
43 #include "virtual_touchpad.h"
44 #include "virtual_pc_switch.h"
45 #include "virtual_pc_touchpad.h"
46 #include "virtual_touchscreen.h"
47 #include "virtual_trackpad_mouse.h"
48 #include "virtual_crown.h"
49
50 namespace OHOS {
51 namespace MMI {
52 namespace {
53 constexpr int32_t FILE_SIZE_MAX = 0x5000;
54 constexpr int32_t INVALID_FILE_SIZE = -1;
55 constexpr int32_t FILE_POWER = 0777;
56 constexpr int32_t SLEEP_TIME = 1500000;
57 const std::string PROC_PATH = "/proc";
58 const std::string VIRTUAL_DEVICE_NAME = "vuinput";
59 const std::string g_pid = std::to_string(getpid());
60
IsNum(const std::string & str)61 static inline bool IsNum(const std::string& str)
62 {
63 std::istringstream sin(str);
64 double num;
65 return (sin >> num) && sin.eof();
66 }
67
IsValidPath(const std::string & rootDir,const std::string & filePath)68 static inline bool IsValidPath(const std::string& rootDir, const std::string& filePath)
69 {
70 return (filePath.compare(0, rootDir.size(), rootDir) == 0);
71 }
72
IsValidUinputPath(const std::string & filePath)73 static inline bool IsValidUinputPath(const std::string& filePath)
74 {
75 return IsValidPath(PROC_PATH, filePath);
76 }
77
IsFileExists(const std::string & fileName)78 static inline bool IsFileExists(const std::string& fileName)
79 {
80 return (access(fileName.c_str(), F_OK) == 0);
81 }
82
CheckFileName(const std::string & fileName)83 static bool CheckFileName(const std::string& fileName)
84 {
85 std::string::size_type pos = fileName.find("_");
86 if (pos == std::string::npos) {
87 std::cout << "Failed to create file" << std::endl;
88 return false;
89 }
90 if (!IsNum(fileName.substr(0, pos))) {
91 std::cout << "File name check error" << std::endl;
92 return false;
93 }
94 std::vector<std::string> validFileNames = {
95 "mouse", "keyboard", "joystick", "trackball", "remotecontrol",
96 "trackpad", "knob", "gamepad", "touchpad", "touchscreen",
97 "pen", "pc", "all"
98 };
99 std::string deviceName = fileName.substr(pos + 1);
100 bool result = std::any_of(validFileNames.begin(), validFileNames.end(), [deviceName](const std::string& str) {
101 return str == deviceName;
102 });
103 if (!result) {
104 std::cout << "Check device file name:" << fileName << std::endl;
105 }
106 return result;
107 }
108
RemoveDir(const std::string & filePath)109 static void RemoveDir(const std::string& filePath)
110 {
111 if (filePath.empty()) {
112 std::cout << "File path is empty" << std::endl;
113 return;
114 }
115 DIR* dir = opendir(filePath.c_str());
116 if (dir == nullptr) {
117 std::cout << "Failed to open folder:" << filePath << std::endl;
118 return;
119 }
120 dirent* ptr = nullptr;
121 while ((ptr = readdir(dir)) != nullptr) {
122 std::string tmpDirName(ptr->d_name);
123 if ((tmpDirName == ".") || (tmpDirName == "..")) {
124 continue;
125 }
126 if (ptr->d_type == DT_REG) {
127 std::string rmFile = filePath + ptr->d_name;
128 if (remove(rmFile.c_str()) != 0) {
129 std::cout << "Remove file:" << rmFile << " failed" << std::endl;
130 }
131 } else if (ptr->d_type == DT_DIR) {
132 RemoveDir((filePath + ptr->d_name + "/"));
133 } else {
134 std::cout << "File name:" << ptr << " type is error" << std::endl;
135 }
136 }
137 if (closedir(dir) != 0) {
138 std::cout << "Close dir:" << filePath << " failed" << std::endl;
139 }
140 if (std::remove(filePath.c_str()) != 0) {
141 std::cout << "Remove dir:" << filePath <<" failed" << std::endl;
142 }
143 }
144
StartMouse()145 static void StartMouse()
146 {
147 static VirtualMouse virtualMouse;
148 virtualMouse.SetUp();
149 }
150
StartKeyboard()151 static void StartKeyboard()
152 {
153 static VirtualKeyboard virtualKey;
154 virtualKey.SetUp();
155 static VirtualKeyboardSysCtrl virtualKeyboardSysCtrl;
156 virtualKeyboardSysCtrl.SetUp();
157 static VirtualKeyboardConsumerCtrl virtualKeyboardConsumerCtrl;
158 virtualKeyboardConsumerCtrl.SetUp();
159 static VirtualKeyboardExt virtualKeyext;
160 virtualKeyext.SetUp();
161 }
162
StartJoystick()163 static void StartJoystick()
164 {
165 static VirtualJoystick virtualJoystick;
166 virtualJoystick.SetUp();
167 }
168
StartTrackball()169 static void StartTrackball()
170 {
171 static VirtualTrackball virtualTrackball;
172 virtualTrackball.SetUp();
173 }
174
StartRemoteControl()175 static void StartRemoteControl()
176 {
177 static VirtualRemoteControl virtualRemoteControl;
178 virtualRemoteControl.SetUp();
179 }
180
StartTrackpad()181 static void StartTrackpad()
182 {
183 static VirtualTrackpad virtualTrackpad;
184 virtualTrackpad.SetUp();
185 static VirtualTrackpadMouse virtualMousepadMouse;
186 virtualMousepadMouse.SetUp();
187 static VirtualTrackpadSysCtrl virtualTrackpadSysCtrl;
188 virtualTrackpadSysCtrl.SetUp();
189 }
190
StartPc()191 static void StartPc()
192 {
193 static VirtualPcTouchpad virtualPcTouchpad;
194 virtualPcTouchpad.SetUp();
195 static VirtualPcSwitch virtualPcSwitch;
196 virtualPcSwitch.SetUp();
197 }
198
StartKnob()199 static void StartKnob()
200 {
201 static VirtualKnob virtualKnob;
202 virtualKnob.SetUp();
203 static VirtualKnobConsumerCtrl virtualKnobConsumerCtrl;
204 virtualKnobConsumerCtrl.SetUp();
205 static VirtualKnobMouse virtualKnobMouse;
206 virtualKnobMouse.SetUp();
207 static VirtualKnobSysCtrl virtualKnobSysCtrl;
208 virtualKnobSysCtrl.SetUp();
209 }
210
StartGamePad()211 static void StartGamePad()
212 {
213 static VirtualGamePad virtualGamePad;
214 virtualGamePad.SetUp();
215 }
216
StartTouchPad()217 static void StartTouchPad()
218 {
219 static VirtualStylus virtualStylus;
220 virtualStylus.SetUp();
221 static VirtualTouchpad virtualTouchpad;
222 virtualTouchpad.SetUp();
223 static VirtualFinger virtualFinger;
224 virtualFinger.SetUp();
225 static VirtualSingleFinger virtualSingleFinger;
226 virtualSingleFinger.SetUp();
227 }
228
StartTouchScreen()229 static void StartTouchScreen()
230 {
231 static VirtualTouchScreen virtualTouchScreen;
232 virtualTouchScreen.SetUp();
233 static VirtualSingleTouchScreen virtualSingleTouchScreen;
234 virtualSingleTouchScreen.SetUp();
235 }
236
StartPen()237 static void StartPen()
238 {
239 static VirtualPen virtualPen;
240 virtualPen.SetUp();
241 static VirtualPenMouse virtualPenMouse;
242 virtualPenMouse.SetUp();
243 static VirtualPenKeyboard virtualPenKeyboard;
244 virtualPenKeyboard.SetUp();
245 }
246
StartCrown()247 static void StartCrown()
248 {
249 static VirtualCrown virtualCrown;
250 virtualCrown.SetUp();
251 }
252
253 using VirtualFun = void (*)();
254 std::map<std::string, VirtualFun> mapFun = {
255 {"mouse", &StartMouse},
256 {"keyboard", &StartKeyboard},
257 {"joystick", &StartJoystick},
258 {"trackball", &StartTrackball},
259 {"remotecontrol", &StartRemoteControl},
260 {"trackpad", &StartTrackpad},
261 {"knob", &StartKnob},
262 {"gamepad", &StartGamePad},
263 {"touchpad", &StartTouchPad},
264 {"pc", &StartPc},
265 {"touchscreen", &StartTouchScreen},
266 {"pen", &StartPen},
267 {"crown", &StartCrown}
268 };
269
StartAllDevices()270 static void StartAllDevices()
271 {
272 if (mapFun.empty()) {
273 std::cout << "mapFun is empty" << std::endl;
274 return;
275 }
276 for (const auto &item : mapFun) {
277 (*item.second)();
278 }
279 }
280 } // namespace
281
VirtualDevice(const std::string & deviceName,uint16_t busType,uint16_t vendorId,uint16_t productId)282 VirtualDevice::VirtualDevice(const std::string& deviceName, uint16_t busType,
283 uint16_t vendorId, uint16_t productId)
284 : deviceName_(deviceName),
285 busTtype_(busType),
286 vendorId_(vendorId),
287 productId_(productId),
288 version_(1) {}
289
~VirtualDevice()290 VirtualDevice::~VirtualDevice()
291 {
292 Close();
293 }
294
BrowseDirectory(const std::string & filePath)295 std::vector<std::string> VirtualDevice::BrowseDirectory(const std::string& filePath)
296 {
297 std::vector<std::string> fileList;
298 DIR* dir = opendir(filePath.c_str());
299 if (dir == nullptr) {
300 std::cout << "Failed to open folder" << std::endl;
301 return fileList;
302 }
303 dirent* ptr = nullptr;
304 while ((ptr = readdir(dir)) != nullptr) {
305 if (ptr->d_type == DT_REG) {
306 if (ClearFileResidues(ptr->d_name)) {
307 fileList.push_back(ptr->d_name);
308 }
309 }
310 }
311 if (closedir(dir) != 0) {
312 std::cout << "Close dir:" << filePath << " failed" << std::endl;
313 }
314 return fileList;
315 }
316
ClearFileResidues(const std::string & fileName)317 bool VirtualDevice::ClearFileResidues(const std::string& fileName)
318 {
319 const std::string::size_type pos = fileName.find("_");
320 const std::string processPath = "/proc/" + fileName.substr(0, pos) + "/";
321 const std::string filePath = processPath + "cmdline";
322 std::string temp;
323 std::string processName;
324 DIR *dir = nullptr;
325 if (!CheckFileName(fileName)) {
326 std::cout << "File name check error" << std::endl;
327 goto RELEASE_RES1;
328 }
329 if (pos == std::string::npos) {
330 std::cout << "Failed to create file" << std::endl;
331 goto RELEASE_RES1;
332 }
333 if (!IsFileExists(processPath)) {
334 std::cout << processPath << " folder does not exist" << std::endl;
335 goto RELEASE_RES1;
336 }
337 dir = opendir(processPath.c_str());
338 if (dir == nullptr) {
339 std::cout << "Useless flag file:" << processPath << std::endl;
340 goto RELEASE_RES1;
341 }
342 temp = ReadUinputToolFile(filePath);
343 if (temp.empty()) {
344 std::cout << "Temp is empty" << std::endl;
345 goto RELEASE_RES2;
346 }
347 processName.append(temp);
348 if (processName.find(VIRTUAL_DEVICE_NAME.c_str()) == std::string::npos) {
349 std::cout << "Process name is wrong" << std::endl;
350 goto RELEASE_RES2;
351 }
352 return true;
353 RELEASE_RES1:
354 if (remove((g_folderPath + fileName).c_str()) != 0) {
355 std::cout << "Remove file failed" << std::endl;
356 }
357 return false;
358 RELEASE_RES2:
359 if (closedir(dir) != 0) {
360 std::cout << "Close dir failed" << std::endl;
361 }
362 if (remove((g_folderPath + fileName).c_str()) != 0) {
363 std::cout << "Remove file failed" << std::endl;
364 }
365 return false;
366 }
367
CreateKey()368 bool VirtualDevice::CreateKey()
369 {
370 auto fun = [&](int32_t uiSet, const std::vector<uint32_t>& list) ->bool {
371 for (const auto &item : list) {
372 if (ioctl(fd_, uiSet, item) < 0) {
373 std::cout << __func__ << " not setting event type:" << item
374 << ", deviceName:" << deviceName_ << std::endl;
375 return false;
376 }
377 }
378 return true;
379 };
380 std::map<int32_t, std::vector<uint32_t>> uinputTypes;
381 uinputTypes[UI_SET_EVBIT] = GetEventTypes();
382 uinputTypes[UI_SET_KEYBIT] = GetKeys();
383 uinputTypes[UI_SET_PROPBIT] = GetProperties();
384 uinputTypes[UI_SET_ABSBIT] = GetAbs();
385 uinputTypes[UI_SET_RELBIT] = GetRelBits();
386 uinputTypes[UI_SET_MSCBIT] = GetMiscellaneous();
387 uinputTypes[UI_SET_LEDBIT] = GetLeds();
388 uinputTypes[UI_SET_SWBIT] = GetSwitches();
389 uinputTypes[UI_SET_FFBIT] = GetRepeats();
390
391 for (const auto &item : uinputTypes) {
392 if (!fun(item.first, item.second)) {
393 return false;
394 }
395 }
396 return true;
397 }
398
SetAbsResolution()399 bool VirtualDevice::SetAbsResolution()
400 {
401 for (const auto &item : absInit_) {
402 ioctl(fd_, UI_ABS_SETUP, &item);
403 }
404 return true;
405 }
406
SetPhys(const std::string & deviceName)407 bool VirtualDevice::SetPhys(const std::string& deviceName)
408 {
409 std::string phys;
410 std::map<std::string, std::string> typeDevice = {
411 {"Virtual Mouse", "mouse"},
412 {"Virtual Crown", "mouse"},
413 {"Virtual keyboard", "keyboard"},
414 {"Virtual KeyboardConsumerCtrl", "keyboard"},
415 {"Virtual keyboardExt", "keyboard"},
416 {"Virtual KeyboardSysCtrl", "keyboard"},
417 {"Virtual Knob", "knob"},
418 {"Virtual KnobConsumerCtrl", "knob"},
419 {"Virtual KnobMouse", "knob"},
420 {"Virtual KnobSysCtrl", "knob"},
421 {"Virtual Trackpad", "trackpad"},
422 {"Virtual TrackPadMouse", "trackpad"},
423 {"Virtual TrackpadSysCtrl", "trackpad"},
424 {"Virtual Finger", "touchpad"},
425 {"Virtual SingleFinger", "touchpad"},
426 {"Virtual Stylus", "touchpad"},
427 {"Virtual Touchpad", "touchpad"},
428 {"Virtual PcSwitch", "pc"},
429 {"Virtual PcTouchPad", "pc"},
430 {"Virtual RemoteControl", "remotecontrol"},
431 {"Virtual Joystick", "joystick"},
432 {"Virtual GamePad", "gamepad"},
433 {"Virtual Trackball", "trackball"},
434 {"Virtual TouchScreen", "touchscreen"},
435 {"Virtual SingleTouchScreen", "touchscreen"},
436 {"V-Pencil", "pen"},
437 {"V-Pencil-mouse", "pen"},
438 {"V-Pencil-keyboard", "pen"},
439 };
440 std::string deviceType = typeDevice.find(deviceName)->second;
441 phys.append(deviceType).append(g_pid).append("/").append(g_pid);
442
443 if (ioctl(fd_, UI_SET_PHYS, phys.c_str()) < 0) {
444 std::cout << "Failed to set uinput phys" << std::endl;
445 return false;
446 }
447 return true;
448 }
449
DoIoctl(int32_t fd,int32_t request,const uint32_t value)450 bool VirtualDevice::DoIoctl(int32_t fd, int32_t request, const uint32_t value)
451 {
452 int32_t rc = ioctl(fd, request, value);
453 if (rc < 0) {
454 std::cout << "Failed to ioctl" << std::endl;
455 return false;
456 }
457 return true;
458 }
459
SetDeviceId()460 void VirtualDevice::SetDeviceId()
461 {
462 uinputDev_.id.bustype = busTtype_;
463 uinputDev_.id.vendor = vendorId_;
464 uinputDev_.id.product = productId_;
465 uinputDev_.id.version = version_;
466 }
467
SetUp()468 bool VirtualDevice::SetUp()
469 {
470 fd_ = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
471 if (fd_ < 0) {
472 std::cout << "Failed to open uinput: " << fd_ << std::endl;
473 return false;
474 }
475
476 if (strncpy_s(uinputDev_.name, sizeof(uinputDev_.name), deviceName_.c_str(), deviceName_.size()) != 0) {
477 std::cout << "Failed to copied device name: " << uinputDev_.name << std::endl;
478 return false;
479 };
480 SetDeviceId();
481 if (!SetAbsResolution()) {
482 std::cout << "Failed to set uinput abs resolution" << std::endl;
483 return false;
484 }
485 if (!SetPhys(deviceName_)) {
486 std::cout << "Failed to set uinput phys" << std::endl;
487 return false;
488 }
489 if (!CreateKey()) {
490 std::cout << "Failed to create uinput KeyValue" << std::endl;
491 return false;
492 }
493 if (write(fd_, &uinputDev_, sizeof(uinputDev_)) < 0) {
494 std::cout << "Unable to write device info to target" << std::endl;
495 return false;
496 }
497 if (ioctl(fd_, UI_DEV_CREATE) < 0) {
498 std::cout << "Try to create uinput device filed in fd: " << fd_ << std::endl;
499 return false;
500 }
501 return true;
502 }
503
Close()504 void VirtualDevice::Close()
505 {
506 if (fd_ >= 0) {
507 ioctl(fd_, UI_DEV_DESTROY);
508 close(fd_);
509 fd_ = -1;
510 }
511 }
512
ReadFile(const std::string & filePath)513 std::string VirtualDevice::ReadFile(const std::string& filePath)
514 {
515 FILE* fp = fopen(filePath.c_str(), "r");
516 if (fp == nullptr) {
517 std::cout << "Failed to open file: " << filePath << std::endl;
518 return "";
519 }
520 std::string dataStr;
521 char buf[256] = {};
522 while (fgets(buf, sizeof(buf), fp) != nullptr) {
523 dataStr += buf;
524 }
525 if (fclose(fp) != 0) {
526 std::cout << "Failed to close file" << std::endl;
527 }
528 return dataStr;
529 }
530
GetFileSize(const std::string & filePath)531 int32_t VirtualDevice::GetFileSize(const std::string& filePath)
532 {
533 struct stat statbuf = { 0 };
534 if (stat(filePath.c_str(), &statbuf) != 0) {
535 std::cout << "Get file size error" << std::endl;
536 return INVALID_FILE_SIZE;
537 }
538 return statbuf.st_size;
539 }
540
ReadUinputToolFile(const std::string & filePath)541 std::string VirtualDevice::ReadUinputToolFile(const std::string& filePath)
542 {
543 if (filePath.empty()) {
544 std::cout << "FilePath is empty" << std::endl;
545 return "";
546 }
547 char realPath[PATH_MAX] = {};
548 if (realpath(filePath.c_str(), realPath) == nullptr) {
549 std::cout << "Path is error" << std::endl;
550 return "";
551 }
552 if (!IsValidUinputPath(realPath)) {
553 std::cout << "File path is error" << std::endl;
554 return "";
555 }
556 if (!IsFileExists(realPath)) {
557 std::cout << "File not exist" << std::endl;
558 return "";
559 }
560 int32_t fileSize = GetFileSize(realPath);
561 if ((fileSize < 0) || (fileSize > FILE_SIZE_MAX)) {
562 std::cout << "File size out of read range" << std::endl;
563 return "";
564 }
565 return ReadFile(filePath);
566 }
567
CreateHandle(const std::string & deviceArgv)568 bool VirtualDevice::CreateHandle(const std::string& deviceArgv)
569 {
570 if (deviceArgv == "all") {
571 StartAllDevices();
572 return true;
573 }
574 if (mapFun.find(deviceArgv) == mapFun.end()) {
575 std::cout << "Please enter the device type correctly" << std::endl;
576 return false;
577 }
578 (*mapFun[deviceArgv])();
579 return true;
580 }
581
AddDevice(const std::string & startDeviceName)582 bool VirtualDevice::AddDevice(const std::string& startDeviceName)
583 {
584 if (startDeviceName.empty()) {
585 std::cout << "StartDeviceName is empty" << std::endl;
586 return false;
587 }
588 if (!CreateHandle(startDeviceName)) {
589 std::cout << "Failed to start device: " << startDeviceName <<std::endl;
590 return false;
591 }
592 std::string symbolFile;
593 symbolFile.append(g_folderPath).append(g_pid).append("_").append(startDeviceName);
594 std::ofstream flagFile;
595 flagFile.open(symbolFile.c_str());
596 if (!flagFile.is_open()) {
597 std::cout << "Failed to create file" <<std::endl;
598 return false;
599 }
600 flagFile.close();
601 return true;
602 }
603
CloseDevice(const std::string & closeDeviceName,const std::vector<std::string> & deviceList)604 bool VirtualDevice::CloseDevice(const std::string& closeDeviceName, const std::vector<std::string>& deviceList)
605 {
606 if (deviceList.empty()) {
607 RemoveDir(g_folderPath);
608 std::cout << "No start device" <<std::endl;
609 return false;
610 }
611 if (closeDeviceName == "all") {
612 for (const auto &it : deviceList) {
613 kill(std::stoi(it), SIGKILL);
614 }
615 RemoveDir(g_folderPath);
616 return true;
617 }
618 for (const auto &it : deviceList) {
619 if (it.find(closeDeviceName) == 0) {
620 kill(std::stoi(it), SIGKILL);
621 remove((g_folderPath + it).c_str());
622 if (BrowseDirectory(g_folderPath).empty()) {
623 RemoveDir(g_folderPath);
624 }
625 return true;
626 }
627 }
628 std::cout << "Device shutdown failed! The PID format is incorrect" <<std::endl;
629 return false;
630 }
631
CheckCommand(int32_t argc,char ** argv)632 bool VirtualDevice::CheckCommand(int32_t argc, char **argv)
633 {
634 int32_t c = -1;
635 if (!SelectOptions(argc, argv, c)) {
636 std::cout << "Select option failed" << std::endl;
637 return false;
638 }
639 if (!IsFileExists(g_folderPath)) {
640 mkdir(g_folderPath.c_str(), FILE_POWER);
641 }
642 switch (c) {
643 case 'L': {
644 if (!ListOption(argc, argv)) {
645 std::cout << "Device query failed" << std::endl;
646 return false;
647 }
648 break;
649 }
650 case 'S': {
651 if (!StartOption(argc, argv)) {
652 std::cout << "Device start failed" << std::endl;
653 return false;
654 }
655 break;
656 }
657 case 'C': {
658 if (!CloseOption(argc, argv)) {
659 std::cout << "Device close failed" << std::endl;
660 return false;
661 }
662 break;
663 }
664 case '?': {
665 if (!HelpOption(argc, argv)) {
666 std::cout << "Failed to ask for help" << std::endl;
667 return false;
668 }
669 break;
670 }
671 default: {
672 std::cout << "The command line format is incorrect" << std::endl;
673 return false;
674 }
675 }
676 return true;
677 }
678
SelectOptions(int32_t argc,char ** argv,int32_t & opt)679 bool VirtualDevice::SelectOptions(int32_t argc, char **argv, int32_t &opt)
680 {
681 if (argc < PARAMETERS_QUERY_NUMBER) {
682 std::cout << "Please enter options or parameters" << std::endl;
683 return false;
684 }
685 struct option longOptions[] = {
686 {"list", no_argument, nullptr, 'L'},
687 {"start", no_argument, nullptr, 'S'},
688 {"close", no_argument, nullptr, 'C'},
689 {"help", no_argument, nullptr, '?'},
690 {nullptr, 0, nullptr, 0}
691 };
692 std::string inputOptions = argv[optind];
693 if (inputOptions.find('-') == inputOptions.npos) {
694 for (uint32_t i = 0; i < sizeof(longOptions) / sizeof(struct option) - 1; ++i) {
695 if (longOptions[i].name == inputOptions) {
696 opt = longOptions[i].val;
697 optind++;
698 break;
699 }
700 }
701 } else if ((inputOptions.length() != PARAMETERS_QUERY_NUMBER) &&
702 (inputOptions[inputOptions.find('-') + 1] != '-')) {
703 std::cout << "More than one short option is not supported" << std::endl;
704 return false;
705 } else {
706 int32_t optionIndex = 0;
707 opt = getopt_long(argc, argv, "LSC?", longOptions, &optionIndex);
708 }
709 if (opt == -1) {
710 std::cout << "Nonstandard input parameters" << std::endl;
711 return false;
712 }
713 return true;
714 }
715
ListOption(int32_t argc,char ** argv)716 bool VirtualDevice::ListOption(int32_t argc, char **argv)
717 {
718 if (argc != PARAMETERS_QUERY_NUMBER) {
719 std::cout << "Invalid Input Param, Please Check the validity of the para" << std::endl;
720 return false;
721 }
722 std::vector<std::string> deviceList = BrowseDirectory(g_folderPath);
723 if (deviceList.empty()) {
724 std::cout << "No device information to query" << std::endl;
725 return true;
726 }
727 std::string::size_type pos;
728 std::cout << "PID\tDEVICE" << std::endl;
729 for (const auto &item : deviceList) {
730 pos = item.find("_");
731 if (pos != std::string::npos) {
732 std::cout << item.substr(0, pos) << "\t" << item.substr(pos + 1, item.size() - pos - 1) << std::endl;
733 }
734 }
735 return true;
736 }
737
StartOption(int32_t argc,char ** argv)738 bool VirtualDevice::StartOption(int32_t argc, char **argv)
739 {
740 if (argc != PARAMETERS_NUMBER) {
741 std::cout << "Invalid Input Param, Please Check the validity of the para" << std::endl;
742 return false;
743 }
744 if (!AddDevice(argv[optind])) {
745 std::cout << "Failed to create device" << std::endl;
746 return false;
747 }
748 while (true) {
749 usleep(SLEEP_TIME);
750 }
751 return true;
752 }
753
CloseOption(int32_t argc,char ** argv)754 bool VirtualDevice::CloseOption(int32_t argc, char **argv)
755 {
756 std::vector<std::string> deviceList = BrowseDirectory(g_folderPath);
757 if (argc != PARAMETERS_NUMBER) {
758 std::cout << "Invalid Input Param, Please Check the validity of the para" << std::endl;
759 return false;
760 }
761 if (!CloseDevice(argv[optind], deviceList)) {
762 std::cout << "Failed to closed device" << std::endl;
763 return false;
764 }
765 std::cout << "device closed successfully" << std::endl;
766 return true;
767 }
768
HelpOption(int32_t argc,char ** argv)769 bool VirtualDevice::HelpOption(int32_t argc, char **argv)
770 {
771 if (argc != PARAMETERS_QUERY_NUMBER) {
772 std::cout << "Invalid Input Param, Please Check the validity of the para" << std::endl;
773 return false;
774 }
775 ShowUsage();
776 return true;
777 }
778
SetResolution(const ResolutionInfo & resolutionInfo)779 void VirtualDevice::SetResolution(const ResolutionInfo& resolutionInfo)
780 {
781 uinputAbs_.code = resolutionInfo.axisCode;
782 uinputAbs_.absinfo.resolution = resolutionInfo.absResolution;
783 absInit_.push_back(uinputAbs_);
784 }
785
SetAbsValue(const AbsInfo & absInfo)786 void VirtualDevice::SetAbsValue(const AbsInfo& absInfo)
787 {
788 uinputDev_.absmin[absInfo.code] = absInfo.minValue;
789 uinputDev_.absmax[absInfo.code] = absInfo.maxValue;
790 uinputDev_.absfuzz[absInfo.code] = absInfo.fuzz;
791 uinputDev_.absflat[absInfo.code] = absInfo.flat;
792 }
793
GetEventTypes() const794 const std::vector<uint32_t>& VirtualDevice::GetEventTypes() const
795 {
796 return eventTypes_;
797 }
798
GetKeys() const799 const std::vector<uint32_t>& VirtualDevice::GetKeys() const
800 {
801 return keys_;
802 }
803
GetProperties() const804 const std::vector<uint32_t>& VirtualDevice::GetProperties() const
805 {
806 return properties_;
807 }
808
GetAbs() const809 const std::vector<uint32_t>& VirtualDevice::GetAbs() const
810 {
811 return abs_;
812 }
813
GetRelBits() const814 const std::vector<uint32_t>& VirtualDevice::GetRelBits() const
815 {
816 return relBits_;
817 }
818
GetLeds() const819 const std::vector<uint32_t>& VirtualDevice::GetLeds() const
820 {
821 return leds_;
822 }
823
GetRepeats() const824 const std::vector<uint32_t>& VirtualDevice::GetRepeats() const
825 {
826 return repeats_;
827 }
828
GetMiscellaneous() const829 const std::vector<uint32_t>& VirtualDevice::GetMiscellaneous() const
830 {
831 return miscellaneous_;
832 }
833
GetSwitches() const834 const std::vector<uint32_t>& VirtualDevice::GetSwitches() const
835 {
836 return switches_;
837 }
838
ShowUsage()839 void VirtualDevice::ShowUsage()
840 {
841 std::cout << "Usage: vuinput <option> <command> <arg>..." << std::endl;
842 std::cout << "The option are: " << std::endl;
843 std::cout << "commands for list: " << std::endl;
844 std::cout << "-L --list list -display virtual devices and pid information" << std::endl;
845 std::cout << "commands for start: " << std::endl;
846 std::cout << "-S <device> & --start <device> & start <device> & -start a device" << std::endl;
847 std::cout << " -start supported <device>-" << std::endl;
848 std::cout << " mouse" << std::endl;
849 std::cout << " keyboard" << std::endl;
850 std::cout << " joystick" << std::endl;
851 std::cout << " trackball" << std::endl;
852 std::cout << " remotecontrol" << std::endl;
853 std::cout << " trackpad" << std::endl;
854 std::cout << " knob" << std::endl;
855 std::cout << " gamepad" << std::endl;
856 std::cout << " touchpad" << std::endl;
857 std::cout << " touchscreen" << std::endl;
858 std::cout << " pen" << std::endl;
859 std::cout << "-S all & --start all & start all & -start devices " << std::endl;
860 std::cout << "commands for close: " << std::endl;
861 std::cout << "-C <pid> --close <pid> close <pid> -close a pid " << std::endl;
862 std::cout << "-C all --close all close all -close pids " << std::endl;
863 std::cout << "-? --help help " << std::endl;
864 }
865 } // namespace MMI
866 } // namespace OHOS
867