• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "device_manager.h"
17 
18 #include <algorithm>
19 #include <charconv>
20 #include <cstring>
21 #include <iostream>
22 #include <iomanip>
23 #include <map>
24 
25 #include <dirent.h>
26 
27 namespace OHOS {
28 namespace MMI {
29 namespace {
30 constexpr size_t EVENT_PREFIX_LENGTH = 5;
31 constexpr const char* EVENT_PREFIX = "event";
32 constexpr int32_t ID_WIDTH = 5;
33 constexpr int32_t PATH_WIDTH = 20;
34 constexpr int32_t TOTAL_WIDTH = 80;
35 constexpr int32_t INVALID_DEVICE_ID = -1;
36 constexpr const char* INPUT_DEVICE_DIR = "/dev/input";
37 }
38 
ExtractEventNumber(const std::string & fileName)39 int32_t DeviceManager::ExtractEventNumber(const std::string& fileName)
40 {
41     if (fileName.length() < EVENT_PREFIX_LENGTH || fileName.substr(0, EVENT_PREFIX_LENGTH) != EVENT_PREFIX) {
42         return INVALID_DEVICE_ID;
43     }
44     std::string numberPart = fileName.substr(EVENT_PREFIX_LENGTH);
45     if (!std::all_of(numberPart.begin(), numberPart.end(), ::isdigit)) {
46         return INVALID_DEVICE_ID;
47     }
48     int32_t eventNum;
49     auto [ptr, ec] = std::from_chars(numberPart.data(), numberPart.data() + numberPart.size(), eventNum);
50     if (ec == std::errc() &&
51         ptr == numberPart.data() + numberPart.size() &&
52         eventNum >= 0) {
53         return eventNum;
54     }
55     return INVALID_DEVICE_ID;
56 }
57 
BuildDevicePath(const std::string & fileName) const58 std::string DeviceManager::BuildDevicePath(const std::string& fileName) const
59 {
60     return std::string(INPUT_DEVICE_DIR) + "/" + fileName;
61 }
62 
DiscoverDevices()63 std::vector<InputDevice> DeviceManager::DiscoverDevices()
64 {
65     std::vector<InputDevice> devices;
66     DIR* dir = opendir(INPUT_DEVICE_DIR);
67     if (!dir) {
68         PrintError("Cannot open /dev/input directory: %s", strerror(errno));
69         return devices;
70     }
71     struct dirent* entry;
72     while ((entry = readdir(dir)) != nullptr) {
73         std::string fileName(entry->d_name);
74         std::string path = BuildDevicePath(entry->d_name);
75         int32_t eventNum = ExtractEventNumber(fileName);
76         if (eventNum >= 0) {
77             InputDevice device(path, static_cast<uint32_t>(eventNum));
78             if (device.IsOpen()) {
79                 devices.push_back(std::move(device));
80             }
81         }
82     }
83     closedir(dir);
84     std::sort(devices.begin(), devices.end(),
85         [](const InputDevice& a, const InputDevice& b) {
86             return a.GetId() < b.GetId();
87         });
88     return devices;
89 }
90 
PrintDeviceList()91 void DeviceManager::PrintDeviceList()
92 {
93     auto devices = DiscoverDevices();
94     if (devices.empty()) {
95         std::cout << "No input devices found." << std::endl;
96         return;
97     }
98     std::cout << "Available input devices:" << std::endl;
99     std::cout << std::setw(ID_WIDTH) << "ID" << " | "
100               << std::setw(PATH_WIDTH) << "Path" << " | "
101               << "Name" << std::endl;
102     std::cout << std::string(TOTAL_WIDTH, '-') << std::endl;
103     for (const auto& device : devices) {
104         std::cout << std::setw(ID_WIDTH) << device.GetId() << " | "
105                   << std::setw(PATH_WIDTH) << device.GetPath() << " | "
106                   << device.GetName() << std::endl;
107     }
108 }
109 } // namespace MMI
110 } // namespace OHOS