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