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