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 <regex>
17 #include "usb_port_manager.h"
18 #include <unistd.h>
19 #include "hisysevent.h"
20 #include "usb_errors.h"
21 #include "usb_srv_support.h"
22 
23 using namespace OHOS::HiviewDFX;
24 using namespace OHOS::HDI::Usb::V1_0;
25 
26 namespace OHOS {
27 namespace USB {
28 constexpr int32_t SUPPORTED_MODES = 3;
29 constexpr int32_t PARAM_COUNT_TWO = 2;
30 constexpr int32_t PARAM_COUNT_THR = 3;
31 constexpr int32_t DEFAULT_ROLE_HOST = 1;
32 constexpr int32_t DEFAULT_ROLE_DEVICE = 2;
33 constexpr uint32_t CMD_INDEX = 1;
34 constexpr uint32_t PARAM_INDEX = 2;
35 constexpr int32_t HOST_MODE = 2;
36 constexpr int32_t WAIT_DELAY_US = 20000;
UsbPortManager()37 UsbPortManager::UsbPortManager()
38 {
39     USB_HILOGI(MODULE_USB_SERVICE, "UsbPortManager::Init start");
40     GetIUsbInterface();
41 }
42 
~UsbPortManager()43 UsbPortManager::~UsbPortManager()
44 {
45     USB_HILOGI(MODULE_USB_SERVICE, "UsbPortManager::unInit start");
46 }
47 
Init()48 void UsbPortManager::Init()
49 {
50     USB_HILOGI(MODULE_USB_SERVICE, "UsbPortManager::QueryPort start");
51     int32_t ret = QueryPort();
52     if (ret) {
53         USB_HILOGE(MODULE_USB_SERVICE, "UsbPortManager::QueryPort false");
54     }
55 }
56 
GetIUsbInterface()57 void UsbPortManager::GetIUsbInterface()
58 {
59     if (usbd_ == nullptr) {
60         for (int32_t i = 0; i < PARAM_COUNT_THR; i++) {
61             usbd_ = IUsbInterface::Get();
62             if (usbd_ == nullptr) {
63                 USB_HILOGE(MODULE_USB_SERVICE, "Get iUsbInteface failed");
64                 usleep(WAIT_DELAY_US);
65             } else {
66                 break;
67             }
68         }
69     }
70 }
71 
SetUsbd(const sptr<IUsbInterface> &usbd)72 int32_t UsbPortManager::SetUsbd(const sptr<IUsbInterface> &usbd)
73 {
74     if (usbd == nullptr) {
75         USB_HILOGE(MODULE_USB_SERVICE, "UsbPortManager usbd is nullptr");
76         return UEC_SERVICE_INVALID_VALUE;
77     }
78     usbd_ = usbd;
79     return UEC_OK;
80 }
81 
GetPorts(std::vector<UsbPort> &ports)82 int32_t UsbPortManager::GetPorts(std::vector<UsbPort> &ports)
83 {
84     std::lock_guard<std::mutex> lock(mutex_);
85     if (portMap_.size() > 0) {
86         for (auto it = portMap_.begin(); it != portMap_.end(); ++it) {
87             ports.push_back(it->second);
88         }
89         USB_HILOGI(MODULE_USB_SERVICE, "UsbPortManager::GetPorts success");
90         return UEC_OK;
91     } else {
92         int32_t ret = QueryPort();
93         if (ret == UEC_OK) {
94             for (auto it = portMap_.begin(); it != portMap_.end(); ++it) {
95                 ports.push_back(it->second);
96             }
97             USB_HILOGI(MODULE_USB_SERVICE, "UsbPortManager::QueryPort and GetPorts success");
98             return ret;
99         }
100     }
101     USB_HILOGE(MODULE_USB_SERVICE, "UsbPortManager::GetPorts false");
102     return UEC_SERVICE_INVALID_VALUE;
103 }
104 
GetSupportedModes(int32_t portId, int32_t &supportedModes)105 int32_t UsbPortManager::GetSupportedModes(int32_t portId, int32_t &supportedModes)
106 {
107     std::lock_guard<std::mutex> lock(mutex_);
108     auto it = portMap_.find(portId);
109     if (it != portMap_.end()) {
110         supportedModes = it->second.supportedModes;
111         USB_HILOGI(MODULE_USB_SERVICE, "UsbPortManager::GetSupportedModes success");
112         return UEC_OK;
113     }
114     USB_HILOGE(MODULE_USB_SERVICE, "UsbPortManager::GetSupportedModes false");
115     return UEC_SERVICE_INVALID_VALUE;
116 }
117 
QueryPort()118 int32_t UsbPortManager::QueryPort()
119 {
120     int32_t portId = 0;
121     int32_t powerRole = 0;
122     int32_t dataRole = 0;
123     int32_t mode = 0;
124     GetIUsbInterface();
125     if (usbd_ == nullptr) {
126         USB_HILOGE(MODULE_USB_SERVICE, "UsbPortManager::usbd_ is nullptr");
127         return UEC_SERVICE_INVALID_VALUE;
128     }
129     int32_t ret = usbd_->QueryPort(portId, powerRole, dataRole, mode);
130     USB_HILOGI(MODULE_USB_SERVICE, "portId:%{public}d powerRole:%{public}d dataRole:%{public}d mode:%{public}d ",
131         portId, powerRole, dataRole, mode);
132     if (ret) {
133         USB_HILOGE(MODULE_USB_SERVICE, "Get().queryPorts failed");
134         return ret;
135     }
136     UsbPortStatus usbPortStatus;
137     UsbPort usbPort;
138     usbPortStatus.currentMode = mode;
139     usbPortStatus.currentDataRole = dataRole;
140     usbPortStatus.currentPowerRole = powerRole;
141     usbPort.id = portId;
142     usbPort.supportedModes = SUPPORTED_MODES;
143     usbPort.usbPortStatus = usbPortStatus;
144     AddPort(usbPort);
145     return ret;
146 }
147 
UpdatePort(int32_t portId, int32_t powerRole, int32_t dataRole, int32_t mode)148 void UsbPortManager::UpdatePort(int32_t portId, int32_t powerRole, int32_t dataRole, int32_t mode)
149 {
150     USB_HILOGI(MODULE_USB_SERVICE, "UsbPortManager::updatePort run");
151     std::lock_guard<std::mutex> lock(mutex_);
152     auto it = portMap_.find(portId);
153     if (it != portMap_.end()) {
154         if (it->second.id == portId) {
155             ReportPortRoleChangeSysEvent(it->second.usbPortStatus.currentPowerRole, powerRole,
156                 it->second.usbPortStatus.currentDataRole, dataRole);
157             it->second.usbPortStatus.currentPowerRole = powerRole;
158             it->second.usbPortStatus.currentDataRole = dataRole;
159             it->second.usbPortStatus.currentMode = mode;
160             USB_HILOGI(MODULE_USB_SERVICE, "UsbPortManager::updatePort seccess");
161             return;
162         }
163     }
164     USB_HILOGE(MODULE_USB_SERVICE, "updatePort false");
165 }
166 
AddPort(UsbPort &port)167 void UsbPortManager::AddPort(UsbPort &port)
168 {
169     USB_HILOGI(MODULE_USB_SERVICE, "addPort run");
170 
171     auto res = portMap_.insert(std::map<int32_t, UsbPort>::value_type(port.id, port));
172     if (!res.second) {
173         USB_HILOGW(MODULE_USB_SERVICE, "addPort port id duplicated");
174         return;
175     }
176     USB_HILOGI(MODULE_USB_SERVICE, "addPort successed");
177 }
178 
RemovePort(int32_t portId)179 void UsbPortManager::RemovePort(int32_t portId)
180 {
181     USB_HILOGI(MODULE_USB_SERVICE, "removePort run");
182     std::lock_guard<std::mutex> lock(mutex_);
183     size_t num = portMap_.erase(portId);
184     if (num == 0) {
185         USB_HILOGW(MODULE_USB_SERVICE, "removePort false");
186         return;
187     }
188     USB_HILOGI(MODULE_USB_SERVICE, "removePort seccess");
189 }
190 
GetPortsInfo(int32_t fd)191 void UsbPortManager::GetPortsInfo(int32_t fd)
192 {
193     std::vector<UsbPort> usbports;
194     int32_t ret = GetPorts(usbports);
195     if (ret != UEC_OK) {
196         dprintf(fd, "%s:GetPorts failed\n", __func__);
197         return;
198     }
199 
200     if (usbports[0].usbPortStatus.currentMode == HOST_MODE) {
201         dprintf(fd, "get current port %d: host\n", usbports[0].usbPortStatus.currentMode);
202     } else {
203         dprintf(fd, "get current port %d: device\n", usbports[0].usbPortStatus.currentMode);
204     }
205 }
206 
GetDumpHelp(int32_t fd)207 void UsbPortManager::GetDumpHelp(int32_t fd)
208 {
209     dprintf(fd, "=========== dump the all device port ===========\n");
210     dprintf(fd, "usb_port -a: Query All Port List\n");
211     dprintf(fd, "usb_port -p Q: Query Port\n");
212     dprintf(fd, "usb_port -p 1: Switch to host\n");
213     dprintf(fd, "usb_port -p 2: Switch to device\n");
214     dprintf(fd, "------------------------------------------------\n");
215 }
216 
DumpGetSupportPort(int32_t fd)217 void UsbPortManager::DumpGetSupportPort(int32_t fd)
218 {
219     dprintf(fd, "Usb Port device status:\n");
220     std::vector<UsbPort> ports;
221     if (GetPorts(ports) != UEC_OK) {
222         dprintf(fd, "UsbPortManager::GetPorts failed, port is empty\n");
223         return;
224     }
225 
226     if (ports.size() == 0) {
227         dprintf(fd, "all port list is empty\n");
228         return;
229     }
230     for (size_t i = 0; i < ports.size(); ++i) {
231         dprintf(fd, "id: %d | supportedModes: %d | currentMode: %d | currentPowerRole: %d | currentDataRole: %d\n",
232             ports[i].id, ports[i].supportedModes, ports[i].usbPortStatus.currentMode,
233             ports[i].usbPortStatus.currentPowerRole, ports[i].usbPortStatus.currentDataRole);
234     }
235 }
236 
DumpSetPortRoles(int32_t fd, const std::string &args)237 void UsbPortManager::DumpSetPortRoles(int32_t fd, const std::string &args)
238 {
239     if (args.compare("Q") == 0) {
240         GetPortsInfo(fd);
241         return;
242     }
243     if (usbd_ == nullptr) {
244         USB_HILOGE(MODULE_USB_SERVICE, "UsbPortManager::DumpSetPortRoles usbd_ is nullptr");
245         return;
246     }
247     if (!std::regex_match(args, std::regex("^[0-9]+$"))) {
248         dprintf(fd, "Invalid input, please enter a valid integer\n");
249         GetDumpHelp(fd);
250         return;
251     }
252     int32_t mode = stoi(args);
253     switch (mode) {
254         case DEFAULT_ROLE_HOST:
255             usbd_->SetPortRole(
256                 UsbSrvSupport::PORT_MODE_DEVICE, UsbSrvSupport::POWER_ROLE_SOURCE, UsbSrvSupport::DATA_ROLE_HOST);
257             GetPortsInfo(fd);
258             break;
259         case DEFAULT_ROLE_DEVICE:
260             usbd_->SetPortRole(
261                 UsbSrvSupport::PORT_MODE_DEVICE, UsbSrvSupport::POWER_ROLE_SINK, UsbSrvSupport::DATA_ROLE_DEVICE);
262             GetPortsInfo(fd);
263             break;
264         default:
265             dprintf(fd, "port param error, please enter again\n");
266             GetDumpHelp(fd);
267     }
268 }
269 
Dump(int32_t fd, const std::vector<std::string> &args)270 void UsbPortManager::Dump(int32_t fd, const std::vector<std::string> &args)
271 {
272     if (args.size() < PARAM_COUNT_TWO || args.size() > PARAM_COUNT_THR) {
273         GetDumpHelp(fd);
274         return;
275     }
276 
277     if (args[CMD_INDEX] == "-a" && args.size() == PARAM_COUNT_TWO) {
278         DumpGetSupportPort(fd);
279     } else if (args[CMD_INDEX] == "-p" && args.size() == PARAM_COUNT_THR) {
280         DumpSetPortRoles(fd, args[PARAM_INDEX]);
281     } else {
282         dprintf(fd, "port param error, please enter again\n");
283         GetDumpHelp(fd);
284     }
285 }
286 
ReportPortRoleChangeSysEvent( int32_t currentPowerRole, int32_t updatePowerRole, int32_t currentDataRole, int32_t updateDataRole)287 void UsbPortManager::ReportPortRoleChangeSysEvent(
288     int32_t currentPowerRole, int32_t updatePowerRole, int32_t currentDataRole, int32_t updateDataRole)
289 {
290     USB_HILOGI(MODULE_USB_SERVICE, "Port switch points are as follows:");
291     HiSysEventWrite(HiSysEvent::Domain::USB, "PORT_ROLE_CHANGED",
292         HiSysEvent::EventType::BEHAVIOR, "CURRENT_POWERROLE",
293         currentPowerRole, "UPDATE_POWERROLE", updatePowerRole, "CURRENT_DATAROLE", currentDataRole, "UPDATE_DATAROLE",
294         updateDataRole);
295 }
296 } // namespace USB
297 } // namespace OHOS
298