1 /* 2 * Copyright (c) 2021-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 "hdi_netlink_monitor.h" 17 #include <arpa/inet.h> 18 #include <netinet/in.h> 19 #include <sys/socket.h> 20 #include <linux/netlink.h> 21 #include "hdi_session.h" 22 23 namespace OHOS { 24 namespace HDI { 25 namespace DISPLAY { HdiNetLinkMonitor()26 HdiNetLinkMonitor::HdiNetLinkMonitor() 27 { 28 DISPLAY_LOGD(); 29 } 30 Init()31 int HdiNetLinkMonitor::Init() 32 { 33 DISPLAY_LOGD(); 34 mThread = std::make_unique<std::thread>(std::bind(&HdiNetLinkMonitor::MonitorThread, this)); 35 mThread->detach(); 36 mRunning = true; 37 return DISPLAY_SUCCESS; 38 } 39 ~HdiNetLinkMonitor()40 HdiNetLinkMonitor::~HdiNetLinkMonitor() 41 { 42 DISPLAY_LOGD(); 43 if (mScoketFd >= 0) { 44 close(mScoketFd); 45 } 46 } 47 ThreadInit()48 static int ThreadInit() 49 { 50 int ret; 51 int fd = -1; 52 const int32_t bufferSize = 1024; 53 struct sockaddr_nl snl; 54 55 bzero(&snl, sizeof(struct sockaddr_nl)); 56 snl.nl_family = AF_NETLINK; 57 snl.nl_pid = getpid(); 58 snl.nl_groups = 1; 59 fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); 60 DISPLAY_CHK_RETURN(fd < 0, DISPLAY_FAILURE, DISPLAY_LOGE("socket fail")); 61 ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); 62 if (ret == -1) { 63 DISPLAY_LOGE("setsockopt fail"); 64 close(fd); 65 return -1; 66 } 67 ret = bind(fd, reinterpret_cast<struct sockaddr *>(&snl), sizeof(struct sockaddr_nl)); 68 if (ret < 0) { 69 DISPLAY_LOGE("bind fail"); 70 close(fd); 71 return -1; 72 } 73 return fd; 74 } 75 ParseUeventMessage(const char * buf,uint32_t len)76 static void ParseUeventMessage(const char *buf, uint32_t len) 77 { 78 uint32_t num; 79 80 for (num = 0; num < len;) { 81 const char *event = buf + num; 82 if (strcmp(event, "STATE=HDMI=0") == 0) { 83 HdiSession::GetInstance().HandleHotplug(false); 84 break; 85 } else if (strcmp(event, "STATE=HDMI=1") == 0) { 86 HdiSession::GetInstance().HandleHotplug(true); 87 break; 88 } 89 num += strlen(event) + 1; 90 } 91 } 92 MonitorThread()93 void HdiNetLinkMonitor::MonitorThread() 94 { 95 constexpr int BUFFER_SIZE = 2048; /* buffer for the variables */ 96 int len; 97 int fd = -1; 98 99 fd = ThreadInit(); 100 DISPLAY_CHK_RETURN_NOT_VALUE(fd < 0, DISPLAY_LOGE("socket fail")); 101 mScoketFd = fd; 102 while (mRunning) { 103 char buf[BUFFER_SIZE] = { 0 }; 104 len = read(fd, &buf, sizeof(buf)); 105 if (len < 0) { 106 DISPLAY_LOGE("read uevent message fail"); 107 break; 108 } 109 ParseUeventMessage(buf, len); 110 } 111 } 112 } // DISPLAY 113 } // HDI 114 } // OHOS 115