1c29fa5a6Sopenharmony_ci/* 2c29fa5a6Sopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License. 5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at 6c29fa5a6Sopenharmony_ci * 7c29fa5a6Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8c29fa5a6Sopenharmony_ci * 9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and 13c29fa5a6Sopenharmony_ci * limitations under the License. 14c29fa5a6Sopenharmony_ci */ 15c29fa5a6Sopenharmony_ci 16c29fa5a6Sopenharmony_ci#include "monitor.h" 17c29fa5a6Sopenharmony_ci 18c29fa5a6Sopenharmony_ci#include <cstring> 19c29fa5a6Sopenharmony_ci#include <string_view> 20c29fa5a6Sopenharmony_ci 21c29fa5a6Sopenharmony_ci#include <sys/epoll.h> 22c29fa5a6Sopenharmony_ci#include <unistd.h> 23c29fa5a6Sopenharmony_ci 24c29fa5a6Sopenharmony_ci#include "devicestatus_define.h" 25c29fa5a6Sopenharmony_ci#include "fi_log.h" 26c29fa5a6Sopenharmony_ci#include "napi_constants.h" 27c29fa5a6Sopenharmony_ci#include "utility.h" 28c29fa5a6Sopenharmony_ci 29c29fa5a6Sopenharmony_ci#undef LOG_TAG 30c29fa5a6Sopenharmony_ci#define LOG_TAG "Monitor" 31c29fa5a6Sopenharmony_ci 32c29fa5a6Sopenharmony_cinamespace OHOS { 33c29fa5a6Sopenharmony_cinamespace Msdp { 34c29fa5a6Sopenharmony_cinamespace DeviceStatus { 35c29fa5a6Sopenharmony_ci 36c29fa5a6Sopenharmony_ciMonitor::~Monitor() 37c29fa5a6Sopenharmony_ci{ 38c29fa5a6Sopenharmony_ci Disable(); 39c29fa5a6Sopenharmony_ci} 40c29fa5a6Sopenharmony_ci 41c29fa5a6Sopenharmony_civoid Monitor::Dispatch(const struct epoll_event &ev) 42c29fa5a6Sopenharmony_ci{ 43c29fa5a6Sopenharmony_ci if ((ev.events & EPOLLIN) == EPOLLIN) { 44c29fa5a6Sopenharmony_ci ReceiveDevice(); 45c29fa5a6Sopenharmony_ci } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) { 46c29fa5a6Sopenharmony_ci FI_HILOGE("Epoll hangup, errno:%{public}s", strerror(errno)); 47c29fa5a6Sopenharmony_ci } 48c29fa5a6Sopenharmony_ci} 49c29fa5a6Sopenharmony_ci 50c29fa5a6Sopenharmony_civoid Monitor::SetDeviceMgr(IDeviceMgr *devMgr) 51c29fa5a6Sopenharmony_ci{ 52c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 53c29fa5a6Sopenharmony_ci CHKPV(devMgr); 54c29fa5a6Sopenharmony_ci devMgr_ = devMgr; 55c29fa5a6Sopenharmony_ci} 56c29fa5a6Sopenharmony_ci 57c29fa5a6Sopenharmony_ciint32_t Monitor::Enable() 58c29fa5a6Sopenharmony_ci{ 59c29fa5a6Sopenharmony_ci CALL_INFO_TRACE; 60c29fa5a6Sopenharmony_ci int32_t ret = OpenConnection(); 61c29fa5a6Sopenharmony_ci if (ret == RET_OK) { 62c29fa5a6Sopenharmony_ci ret = EnableReceiving(); 63c29fa5a6Sopenharmony_ci if (ret != RET_OK) { 64c29fa5a6Sopenharmony_ci FI_HILOGE("Enable receive failed"); 65c29fa5a6Sopenharmony_ci Disable(); 66c29fa5a6Sopenharmony_ci } 67c29fa5a6Sopenharmony_ci } 68c29fa5a6Sopenharmony_ci return ret; 69c29fa5a6Sopenharmony_ci} 70c29fa5a6Sopenharmony_ci 71c29fa5a6Sopenharmony_civoid Monitor::Disable() 72c29fa5a6Sopenharmony_ci{ 73c29fa5a6Sopenharmony_ci CALL_INFO_TRACE; 74c29fa5a6Sopenharmony_ci if (devWd_ >= 0) { 75c29fa5a6Sopenharmony_ci int32_t ret = inotify_rm_watch(inotifyFd_, devWd_); 76c29fa5a6Sopenharmony_ci if (ret != 0) { 77c29fa5a6Sopenharmony_ci FI_HILOGE("inotify_rm_watch failed"); 78c29fa5a6Sopenharmony_ci } 79c29fa5a6Sopenharmony_ci devWd_ = -1; 80c29fa5a6Sopenharmony_ci } 81c29fa5a6Sopenharmony_ci if (inotifyFd_ >= 0) { 82c29fa5a6Sopenharmony_ci if (close(inotifyFd_) < 0) { 83c29fa5a6Sopenharmony_ci FI_HILOGE("close inotify fd failed, error:%{public}s, inotifyFd_:%{public}d", strerror(errno), inotifyFd_); 84c29fa5a6Sopenharmony_ci } 85c29fa5a6Sopenharmony_ci inotifyFd_ = -1; 86c29fa5a6Sopenharmony_ci } 87c29fa5a6Sopenharmony_ci} 88c29fa5a6Sopenharmony_ci 89c29fa5a6Sopenharmony_ciint32_t Monitor::OpenConnection() 90c29fa5a6Sopenharmony_ci{ 91c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 92c29fa5a6Sopenharmony_ci inotifyFd_ = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); 93c29fa5a6Sopenharmony_ci if (inotifyFd_ < 0) { 94c29fa5a6Sopenharmony_ci FI_HILOGE("Initializing inotify, errno:%{public}s", strerror(errno)); 95c29fa5a6Sopenharmony_ci return RET_ERR; 96c29fa5a6Sopenharmony_ci } 97c29fa5a6Sopenharmony_ci return RET_OK; 98c29fa5a6Sopenharmony_ci} 99c29fa5a6Sopenharmony_ci 100c29fa5a6Sopenharmony_ciint32_t Monitor::EnableReceiving() 101c29fa5a6Sopenharmony_ci{ 102c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 103c29fa5a6Sopenharmony_ci devWd_ = inotify_add_watch(inotifyFd_, DEV_INPUT_PATH.c_str(), IN_CREATE | IN_DELETE); 104c29fa5a6Sopenharmony_ci if (devWd_ < 0) { 105c29fa5a6Sopenharmony_ci FI_HILOGE("Watching (\'%{public}s\') failed, errno:%{public}s", DEV_INPUT_PATH.c_str(), strerror(errno)); 106c29fa5a6Sopenharmony_ci return RET_ERR; 107c29fa5a6Sopenharmony_ci } 108c29fa5a6Sopenharmony_ci return RET_OK; 109c29fa5a6Sopenharmony_ci} 110c29fa5a6Sopenharmony_ci 111c29fa5a6Sopenharmony_civoid Monitor::ReceiveDevice() 112c29fa5a6Sopenharmony_ci{ 113c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 114c29fa5a6Sopenharmony_ci char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; 115c29fa5a6Sopenharmony_ci size_t bufSize { sizeof(struct inotify_event) }; 116c29fa5a6Sopenharmony_ci ssize_t numRead { 0 }; 117c29fa5a6Sopenharmony_ci 118c29fa5a6Sopenharmony_ci do { 119c29fa5a6Sopenharmony_ci bufSize += sizeof(struct inotify_event); 120c29fa5a6Sopenharmony_ci numRead = ::read(inotifyFd_, buf, bufSize); 121c29fa5a6Sopenharmony_ci } while ((numRead < 0) && (errno == EINVAL) && 122c29fa5a6Sopenharmony_ci (bufSize + sizeof(struct inotify_event) <= sizeof(buf))); 123c29fa5a6Sopenharmony_ci 124c29fa5a6Sopenharmony_ci if (numRead < 0) { 125c29fa5a6Sopenharmony_ci FI_HILOGE("Reading failed, errno:%{public}s", strerror(errno)); 126c29fa5a6Sopenharmony_ci return; 127c29fa5a6Sopenharmony_ci } 128c29fa5a6Sopenharmony_ci if (numRead == 0) { 129c29fa5a6Sopenharmony_ci FI_HILOGW("End of file encountered"); 130c29fa5a6Sopenharmony_ci return; 131c29fa5a6Sopenharmony_ci } 132c29fa5a6Sopenharmony_ci FI_HILOGD("Read %{public}zd bytes from inotify events", numRead); 133c29fa5a6Sopenharmony_ci for (char *p = buf; p < buf + numRead;) { 134c29fa5a6Sopenharmony_ci struct inotify_event *event = reinterpret_cast<struct inotify_event *>(p); 135c29fa5a6Sopenharmony_ci HandleInotifyEvent(event); 136c29fa5a6Sopenharmony_ci p += sizeof(struct inotify_event) + event->len; 137c29fa5a6Sopenharmony_ci } 138c29fa5a6Sopenharmony_ci} 139c29fa5a6Sopenharmony_ci 140c29fa5a6Sopenharmony_civoid Monitor::HandleInotifyEvent(struct inotify_event *event) const 141c29fa5a6Sopenharmony_ci{ 142c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 143c29fa5a6Sopenharmony_ci CHKPV(event); 144c29fa5a6Sopenharmony_ci if (Utility::IsEmpty(event->name)) { 145c29fa5a6Sopenharmony_ci return; 146c29fa5a6Sopenharmony_ci } 147c29fa5a6Sopenharmony_ci std::string devNode { event->name }; 148c29fa5a6Sopenharmony_ci 149c29fa5a6Sopenharmony_ci if ((event->mask & IN_CREATE) == IN_CREATE) { 150c29fa5a6Sopenharmony_ci AddDevice(devNode); 151c29fa5a6Sopenharmony_ci } else if ((event->mask & IN_DELETE) == IN_DELETE) { 152c29fa5a6Sopenharmony_ci RemoveDevice(devNode); 153c29fa5a6Sopenharmony_ci } 154c29fa5a6Sopenharmony_ci} 155c29fa5a6Sopenharmony_ci 156c29fa5a6Sopenharmony_civoid Monitor::AddDevice(const std::string &devNode) const 157c29fa5a6Sopenharmony_ci{ 158c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 159c29fa5a6Sopenharmony_ci CHKPV(devMgr_); 160c29fa5a6Sopenharmony_ci devMgr_->AddDevice(devNode); 161c29fa5a6Sopenharmony_ci} 162c29fa5a6Sopenharmony_ci 163c29fa5a6Sopenharmony_civoid Monitor::RemoveDevice(const std::string &devNode) const 164c29fa5a6Sopenharmony_ci{ 165c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 166c29fa5a6Sopenharmony_ci CHKPV(devMgr_); 167c29fa5a6Sopenharmony_ci devMgr_->RemoveDevice(devNode); 168c29fa5a6Sopenharmony_ci} 169c29fa5a6Sopenharmony_ci} // namespace DeviceStatus 170c29fa5a6Sopenharmony_ci} // namespace Msdp 171c29fa5a6Sopenharmony_ci} // namespace OHOS