• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 <cstring>
20 #include <regex>
21 #include <unistd.h>
22 
23 #include <sys/epoll.h>
24 #include <sys/stat.h>
25 
26 #ifdef OHOS_BUILD_ENABLE_COORDINATION
27 #include "coordination_util.h"
28 #endif // OHOS_BUILD_ENABLE_COORDINATION
29 #include "device.h"
30 #include "devicestatus_define.h"
31 #include "fi_log.h"
32 #include "napi_constants.h"
33 
34 namespace OHOS {
35 namespace Msdp {
36 namespace DeviceStatus {
37 namespace {
38 constexpr OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "DeviceManager" };
39 constexpr size_t EXPECTED_N_SUBMATCHES { 2 };
40 constexpr size_t EXPECTED_SUBMATCH { 1 };
41 } // namespace
42 
HotplugHandler(DeviceManager & devMgr)43 DeviceManager::HotplugHandler::HotplugHandler(DeviceManager &devMgr)
44     : devMgr_(devMgr)
45 {}
46 
AddDevice(const std::string & devNode)47 void DeviceManager::HotplugHandler::AddDevice(const std::string &devNode)
48 {
49     devMgr_.AddDevice(devNode);
50 }
51 
RemoveDevice(const std::string & devNode)52 void DeviceManager::HotplugHandler::RemoveDevice(const std::string &devNode)
53 {
54     devMgr_.RemoveDevice(devNode);
55 }
56 
DeviceManager()57 DeviceManager::DeviceManager()
58     : hotplug_(*this)
59 {}
60 
Init(IContext * context)61 int32_t DeviceManager::Init(IContext *context)
62 {
63     CALL_INFO_TRACE;
64     CHKPR(context, RET_ERR);
65     int32_t ret = context->GetDelegateTasks().PostSyncTask(
66         std::bind(&DeviceManager::OnInit, this, context));
67     if (ret != RET_OK) {
68         FI_HILOGE("Post sync task failed");
69     }
70     return ret;
71 }
72 
OnInit(IContext * context)73 int32_t DeviceManager::OnInit(IContext *context)
74 {
75     CALL_INFO_TRACE;
76     CHKPR(context, RET_ERR);
77     context_ = context;
78     monitor_.SetDeviceMgr(&hotplug_);
79     enumerator_.SetDeviceMgr(&hotplug_);
80     return RET_OK;
81 }
82 
Enable()83 int32_t DeviceManager::Enable()
84 {
85     CALL_INFO_TRACE;
86     CHKPR(context_, RET_ERR);
87     int32_t ret = context_->GetDelegateTasks().PostSyncTask(
88         std::bind(&DeviceManager::OnEnable, this));
89     if (ret != RET_OK) {
90         FI_HILOGE("Post sync task failed");
91     }
92     return ret;
93 }
94 
OnEnable()95 int32_t DeviceManager::OnEnable()
96 {
97     CALL_DEBUG_ENTER;
98     epollMgr_ = std::make_shared<EpollManager>();
99     int32_t ret = epollMgr_->Open();
100     if (ret != RET_OK) {
101         return ret;
102     }
103     ret = monitor_.Enable();
104     if (ret != RET_OK) {
105         goto CLOSE_EPOLL;
106     }
107     ret = epollMgr_->Add(monitor_);
108     if (ret != RET_OK) {
109         goto DISABLE_MONITOR;
110     }
111     enumerator_.ScanDevices();
112     return RET_OK;
113 
114 DISABLE_MONITOR:
115     monitor_.Disable();
116 
117 CLOSE_EPOLL:
118     epollMgr_.reset();
119     return ret;
120 }
121 
Disable()122 int32_t DeviceManager::Disable()
123 {
124     CALL_INFO_TRACE;
125     CHKPR(context_, RET_ERR);
126     int32_t ret = context_->GetDelegateTasks().PostSyncTask(
127         std::bind(&DeviceManager::OnDisable, this));
128     if (ret != RET_OK) {
129         FI_HILOGE("PostSyncTask failed");
130     }
131     return ret;
132 }
133 
OnDisable()134 int32_t DeviceManager::OnDisable()
135 {
136     CHKPR(epollMgr_, RET_ERR);
137     epollMgr_->Remove(monitor_);
138     monitor_.Disable();
139     epollMgr_.reset();
140     return RET_OK;
141 }
142 
FindDevice(const std::string & devPath)143 std::shared_ptr<IDevice> DeviceManager::FindDevice(const std::string &devPath)
144 {
145     auto tIter = std::find_if(devices_.cbegin(), devices_.cend(),
146         [devPath](const auto &item) {
147             return ((item.second != nullptr) && (item.second->GetDevPath() == devPath));
148         });
149     return (tIter != devices_.cend() ? tIter->second : nullptr);
150 }
151 
ParseDeviceId(const std::string & devNode)152 int32_t DeviceManager::ParseDeviceId(const std::string &devNode)
153 {
154     CALL_DEBUG_ENTER;
155     std::regex pattern("^event(\\d+)$");
156     std::smatch mr;
157 
158     if (std::regex_match(devNode, mr, pattern)) {
159         if (mr.ready() && mr.size() == EXPECTED_N_SUBMATCHES) {
160             return std::stoi(mr[EXPECTED_SUBMATCH].str());
161         }
162     }
163     return RET_ERR;
164 }
165 
AddDevice(const std::string & devNode)166 std::shared_ptr<IDevice> DeviceManager::AddDevice(const std::string &devNode)
167 {
168     CALL_DEBUG_ENTER;
169     const std::string SYS_INPUT_PATH { "/sys/class/input/" };
170     const std::string devPath { DEV_INPUT_PATH + devNode };
171     struct stat statbuf;
172 
173     if (stat(devPath.c_str(), &statbuf) != 0) {
174         FI_HILOGD("Invalid device path:%{public}s", devPath.c_str());
175         return nullptr;
176     }
177     if (!S_ISCHR(statbuf.st_mode)) {
178         FI_HILOGD("Not character device:%{public}s", devPath.c_str());
179         return nullptr;
180     }
181 
182     int32_t deviceId = ParseDeviceId(devNode);
183     if (deviceId < 0) {
184         FI_HILOGE("Parsing device name failed:%{public}s", devNode.c_str());
185         return nullptr;
186     }
187 
188     std::shared_ptr<IDevice> dev = FindDevice(devPath);
189     if (dev != nullptr) {
190         FI_HILOGD("Already exists:%{public}s", devPath.c_str());
191         return dev;
192     }
193 
194     const std::string lSysPath { SYS_INPUT_PATH + devNode };
195     char rpath[PATH_MAX];
196     if (realpath(lSysPath.c_str(), rpath) == nullptr) {
197         FI_HILOGD("Invalid sysPath:%{public}s", lSysPath.c_str());
198         return nullptr;
199     }
200 
201     dev = std::make_shared<Device>(deviceId);
202     dev->SetDevPath(devPath);
203     dev->SetSysPath(std::string(rpath));
204     if (dev->Open() != RET_OK) {
205         FI_HILOGE("Unable to open \'%{public}s\'", devPath.c_str());
206         return nullptr;
207     }
208     auto ret = devices_.insert_or_assign(dev->GetId(), dev);
209     if (ret.second) {
210         FI_HILOGD("\'%{public}s\' added", dev->GetName().c_str());
211         OnDeviceAdded(dev);
212     }
213     return dev;
214 }
215 
RemoveDevice(const std::string & devNode)216 std::shared_ptr<IDevice> DeviceManager::RemoveDevice(const std::string &devNode)
217 {
218     CALL_INFO_TRACE;
219     const std::string devPath { DEV_INPUT_PATH + devNode };
220 
221     for (auto devIter = devices_.begin(); devIter != devices_.end(); ++devIter) {
222         std::shared_ptr<IDevice> dev = devIter->second;
223         CHKPC(dev);
224         if (dev->GetDevPath() == devPath) {
225             devices_.erase(devIter);
226             FI_HILOGD("\'%{public}s\' removed", dev->GetName().c_str());
227             dev->Close();
228             OnDeviceRemoved(dev);
229             return dev;
230         }
231     }
232     FI_HILOGD("\'%{public}s\' was not found", devNode.c_str());
233     return nullptr;
234 }
235 
OnDeviceAdded(std::shared_ptr<IDevice> dev)236 void DeviceManager::OnDeviceAdded(std::shared_ptr<IDevice> dev)
237 {
238     CHKPV(dev);
239     FI_HILOGI("Add device %{public}d:%{public}s", dev->GetId(), dev->GetDevPath().c_str());
240     FI_HILOGD("  sysPath:       \"%{public}s\"", dev->GetSysPath().c_str());
241     FI_HILOGD("  bus:           %{public}04x", dev->GetBus());
242     FI_HILOGD("  vendor:        %{public}04x", dev->GetVendor());
243     FI_HILOGD("  product:       %{public}04x", dev->GetProduct());
244     FI_HILOGD("  version:       %{public}04x", dev->GetVersion());
245     FI_HILOGI("  name:          \"%{public}s\"", dev->GetName().c_str());
246     FI_HILOGD("  location:      \"%{public}s\"", dev->GetPhys().c_str());
247     FI_HILOGD("  unique id:     \"%{public}s\"", dev->GetUniq().c_str());
248     FI_HILOGI("  is pointer:    %{public}s, is keyboard:%{public}s",
249         dev->IsPointerDevice() ? "True" : "False", dev->IsKeyboard() ? "True" : "False");
250 
251     for (const auto &observer : observers_) {
252         std::shared_ptr<IDeviceObserver> ptr = observer.lock();
253         CHKPC(ptr);
254         ptr->OnDeviceAdded(dev);
255     }
256 }
257 
OnDeviceRemoved(std::shared_ptr<IDevice> dev)258 void DeviceManager::OnDeviceRemoved(std::shared_ptr<IDevice> dev)
259 {
260     for (const auto &observer : observers_) {
261         std::shared_ptr<IDeviceObserver> ptr = observer.lock();
262         CHKPC(ptr);
263         ptr->OnDeviceRemoved(dev);
264     }
265 }
266 
Dispatch(const struct epoll_event & ev)267 void DeviceManager::Dispatch(const struct epoll_event &ev)
268 {
269     CALL_DEBUG_ENTER;
270     CHKPV(context_);
271     int32_t ret = context_->GetDelegateTasks().PostAsyncTask(
272         std::bind(&DeviceManager::OnEpollDispatch, this, ev.events));
273     if (ret != RET_OK) {
274         FI_HILOGE("PostAsyncTask failed");
275     }
276 }
277 
OnEpollDispatch(uint32_t events)278 int32_t DeviceManager::OnEpollDispatch(uint32_t events)
279 {
280     struct epoll_event ev {};
281     ev.events = events;
282     ev.data.ptr = epollMgr_.get();
283 
284     CHKPR(epollMgr_, RET_ERR);
285     epollMgr_->Dispatch(ev);
286     return RET_OK;
287 }
288 
GetDevice(int32_t id) const289 std::shared_ptr<IDevice> DeviceManager::GetDevice(int32_t id) const
290 {
291     CHKPP(context_);
292     std::packaged_task<std::shared_ptr<IDevice>(int32_t)> task {
293         std::bind(&DeviceManager::OnGetDevice, this, std::placeholders::_1) };
294     auto fu = task.get_future();
295 
296     int32_t ret = context_->GetDelegateTasks().PostSyncTask(
297         std::bind(&DeviceManager::RunGetDevice, this, std::ref(task), id));
298     if (ret != RET_OK) {
299         FI_HILOGE("Post task failed");
300         return nullptr;
301     }
302     return fu.get();
303 }
304 
OnGetDevice(int32_t id) const305 std::shared_ptr<IDevice> DeviceManager::OnGetDevice(int32_t id) const
306 {
307     if (auto devIter = devices_.find(id); devIter != devices_.cend()) {
308         return devIter->second;
309     }
310     FI_HILOGE("Device id not found");
311     return nullptr;
312 }
313 
RunGetDevice(std::packaged_task<std::shared_ptr<IDevice> (int32_t)> & task,int32_t id) const314 int32_t DeviceManager::RunGetDevice(std::packaged_task<std::shared_ptr<IDevice>(int32_t)> &task,
315                                     int32_t id) const
316 {
317     task(id);
318     return RET_OK;
319 }
320 
RetriggerHotplug(std::weak_ptr<IDeviceObserver> observer)321 void DeviceManager::RetriggerHotplug(std::weak_ptr<IDeviceObserver> observer)
322 {
323     CALL_INFO_TRACE;
324     CHKPV(context_);
325     int32_t ret = context_->GetDelegateTasks().PostAsyncTask(
326         std::bind(&DeviceManager::OnRetriggerHotplug, this, observer));
327     if (ret != RET_OK) {
328         FI_HILOGE("Post task failed");
329     }
330 }
331 
OnRetriggerHotplug(std::weak_ptr<IDeviceObserver> observer)332 int32_t DeviceManager::OnRetriggerHotplug(std::weak_ptr<IDeviceObserver> observer)
333 {
334     CALL_INFO_TRACE;
335     CHKPR(observer, RET_ERR);
336     std::shared_ptr<IDeviceObserver> ptr = observer.lock();
337     CHKPR(ptr, RET_ERR);
338     std::for_each(devices_.cbegin(), devices_.cend(),
339         [ptr] (const auto &item) {
340             if (item.second != nullptr) {
341                 ptr->OnDeviceAdded(item.second);
342             }
343         });
344     return RET_OK;
345 }
346 
AddDeviceObserver(std::weak_ptr<IDeviceObserver> observer)347 int32_t DeviceManager::AddDeviceObserver(std::weak_ptr<IDeviceObserver> observer)
348 {
349     CALL_DEBUG_ENTER;
350     CHKPR(context_, RET_ERR);
351     int32_t ret = context_->GetDelegateTasks().PostAsyncTask(
352         std::bind(&DeviceManager::OnAddDeviceObserver, this, observer));
353     if (ret != RET_OK) {
354         FI_HILOGE("Post task failed");
355     }
356     return ret;
357 }
358 
OnAddDeviceObserver(std::weak_ptr<IDeviceObserver> observer)359 int32_t DeviceManager::OnAddDeviceObserver(std::weak_ptr<IDeviceObserver> observer)
360 {
361     CALL_INFO_TRACE;
362     CHKPR(observer, RET_ERR);
363     auto ret = observers_.insert(observer);
364     if (!ret.second) {
365         FI_HILOGW("Observer is duplicated");
366     }
367     return RET_OK;
368 }
369 
RemoveDeviceObserver(std::weak_ptr<IDeviceObserver> observer)370 void DeviceManager::RemoveDeviceObserver(std::weak_ptr<IDeviceObserver> observer)
371 {
372     CALL_INFO_TRACE;
373     CHKPV(context_);
374     int32_t ret = context_->GetDelegateTasks().PostAsyncTask(
375         std::bind(&DeviceManager::OnRemoveDeviceObserver, this, observer));
376     if (ret != RET_OK) {
377         FI_HILOGE("Post task failed");
378     }
379 }
380 
OnRemoveDeviceObserver(std::weak_ptr<IDeviceObserver> observer)381 int32_t DeviceManager::OnRemoveDeviceObserver(std::weak_ptr<IDeviceObserver> observer)
382 {
383     CALL_INFO_TRACE;
384     CHKPR(observer, RET_ERR);
385     observers_.erase(observer);
386     return RET_OK;
387 }
388 } // namespace DeviceStatus
389 } // namespace Msdp
390 } // namespace OHOS