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