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