• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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 #include <iostream>
16 #include <sstream>
17 #include <regex>
18 
19 #include "usbd_ports.h"
20 #include "hdf_base.h"
21 #include "hdf_log.h"
22 #include "usbd_function.h"
23 #include "usb_portInfo.h"
24 
25 using namespace OHOS::HDI::Usb::Port;
26 
27 namespace OHOS {
28 namespace HDI {
29 namespace Usb {
30 namespace V1_2 {
31 constexpr int32_t NONE = 0;
32 constexpr int32_t SUPPORT_MODE = 1;
33 constexpr int32_t STRING_PORT = 4;
34 
GetInstance()35 UsbdPorts &UsbdPorts::GetInstance()
36 {
37     static UsbdPorts instance;
38     return instance;
39 }
40 
UsbdPorts()41 UsbdPorts::UsbdPorts()
42 {
43     InitMap();
44 }
45 
InitMap()46 void UsbdPorts::InitMap()
47 {
48     portAttributeMap_[PORT_NONE] = NONE;
49     portAttributeMap_[PORT_MODE_UFP] = static_cast<int32_t>(Port::PortMode::UFP);
50     portAttributeMap_[PORT_MODE_DFP] = static_cast<int32_t>(Port::PortMode::DFP);
51     portAttributeMap_[PORT_MODE_DRP] = static_cast<int32_t>(Port::PortMode::DRP);
52     portAttributeMap_[POWER_ROLE_SOURCE] = static_cast<int32_t>(PowerRole::SOURCE);
53     portAttributeMap_[POWER_ROLE_SINK] = static_cast<int32_t>(PowerRole::SINK);
54     portAttributeMap_[DATA_ROLE_HOST] = static_cast<int32_t>(DataRole::HOST);
55     portAttributeMap_[DATA_ROLE_DEVICE] = static_cast<int32_t>(DataRole::DEVICE);
56     portAttributeMap_[SUPPORTED_MODE] = SUPPORT_MODE;
57 }
58 
setPortPath(const std::string & path)59 void UsbdPorts::setPortPath(const std::string &path)
60 {
61     path_ = path;
62     HDF_LOGI("%{public}s: port_file_path = %{public}s", __func__, path_.c_str());
63 }
64 
QueryPort(int32_t & portId,int32_t & powerRole,int32_t & dataRole,int32_t & mode)65 int32_t UsbdPorts::QueryPort(int32_t &portId, int32_t &powerRole, int32_t &dataRole, int32_t &mode)
66 {
67     HDF_LOGI("%{public}s: QueryPort start", __func__);
68     if (portCacheDataMap_.empty()) {
69         std::vector<V2_0::UsbPort> portList;
70         int32_t ret = QueryPorts(portList);
71         if (ret != HDF_SUCCESS) {
72             HDF_LOGE("%{public}s: QueryPorts failed!", __func__);
73             return HDF_FAILURE;
74         }
75     }
76 
77     auto usbPort = portCacheDataMap_.begin();
78     portId = usbPort->first;
79     powerRole = usbPort->second.usbPortStatus.currentPowerRole;
80     dataRole = usbPort->second.usbPortStatus.currentDataRole;
81     mode = usbPort->second.usbPortStatus.currentMode;
82     return HDF_SUCCESS;
83 }
84 
QueryPorts(std::vector<V2_0::UsbPort> & portList)85 int32_t UsbdPorts::QueryPorts(std::vector<V2_0::UsbPort>& portList)
86 {
87     HDF_LOGI("%{public}s: start", __func__);
88     std::vector<std::string> portIds;
89     int32_t ret = ParseDirectory(path_, portIds, true);
90     if (ret != HDF_SUCCESS) {
91         HDF_LOGE("%{public}s: ParseDirectory failed! ret:%{public}d", __func__, ret);
92         return HDF_FAILURE;
93     }
94 
95     std::lock_guard<std::mutex> lock(mutex_);
96     for (auto portId : portIds) {
97         V2_0::UsbPort usbPort;
98         if (ReadPortInfo(portId, usbPort) != HDF_SUCCESS) {
99             HDF_LOGE("%{public}s: ReadPortInfo failed! ret:%{public}d", __func__, ret);
100             return HDF_FAILURE;
101         }
102         if (!std::regex_match(portId, std::regex("^[0-9]+$"))) {
103             HDF_LOGE("%{public}s Invalid portId", __func__);
104             return HDF_FAILURE;
105         }
106         usbPort.id = std::stoi(portId);
107         portList.emplace_back(usbPort);
108         AddPort(usbPort);
109     }
110 
111     return HDF_SUCCESS;
112 }
113 
ParseDirectory(const std::string & path,std::vector<std::string> & portIds,bool flag)114 int32_t UsbdPorts::ParseDirectory(const std::string& path, std::vector<std::string>& portIds, bool flag)
115 {
116     HDF_LOGI("%{public}s start", __func__);
117     DIR* dir = opendir(path.c_str());
118     if (dir == nullptr) {
119         HDF_LOGE("%{public}s: directory open error! path: %{public}s", __func__, path.c_str());
120         return HDF_FAILURE;
121     }
122 
123     struct dirent* entry;
124     while ((entry = readdir(dir)) != nullptr) {
125         std::string value = entry->d_name;
126         if (value == "." || value == "..") {
127             continue;
128         }
129 
130         if (flag) {
131             if (ParsePortId(value) != HDF_SUCCESS) {
132                 HDF_LOGE("%{public}s: Parse portid failed! ", __func__);
133                 closedir(dir);
134                 return HDF_FAILURE;
135             }
136             portIds.push_back(value);
137             continue;
138         }
139 
140         if (!IsFileFormat(entry->d_name)) {
141             continue;
142         }
143         portIds.push_back(entry->d_name);
144     }
145     closedir(dir);
146 
147     return HDF_SUCCESS;
148 }
149 
IsFileFormat(const std::string & dName)150 bool UsbdPorts::IsFileFormat(const std::string& dName)
151 {
152     if (dName != "port_mode" && dName != "power_role"
153         && dName != "data_role" && dName != "supported_mode") {
154         return false;
155     }
156 
157     return true;
158 }
159 
ParsePortId(std::string & value)160 int32_t UsbdPorts::ParsePortId(std::string& value)
161 {
162     std::string str = value;
163     if (str.substr(0, STRING_PORT) != "port") {
164         HDF_LOGE("%{public}s: The portid node is incorrect! portId: %{public}s", __func__, str.c_str());
165         return HDF_FAILURE;
166     }
167 
168     value = str.substr(STRING_PORT);
169     if (value.empty()) {
170         HDF_LOGE("%{public}s: The portid node is incorrect! portId: %{public}s", __func__, str.c_str());
171         return HDF_FAILURE;
172     }
173 
174     for (size_t i = 0; i < value.size(); i++) {
175         if (value.at(i) > '9' || value.at(i) < '0') {
176             HDF_LOGE("%{public}s: this node name incorrect! portId: %{public}s.", __func__, str.c_str());
177             return HDF_FAILURE;
178         }
179     }
180 
181     return HDF_SUCCESS;
182 }
183 
ReadPortInfo(const std::string & portId,V2_0::UsbPort & usbPort)184 int32_t UsbdPorts::ReadPortInfo(const std::string& portId, V2_0::UsbPort& usbPort)
185 {
186     HDF_LOGI("%{public}s start", __func__);
187     std::vector<std::string> portAttributeFileList;
188     const std::string portAttributeDir = path_ + "port" + portId;
189 
190     int32_t ret = ParseDirectory(portAttributeDir, portAttributeFileList, false);
191     if (ret != HDF_SUCCESS) {
192         HDF_LOGE("%{public}s: ParseDirectory failed! ret:%{public}d", __func__, ret);
193         return HDF_FAILURE;
194     }
195 
196     for (auto it : portAttributeFileList) {
197         std::string portAttributeFile;
198         char buff[PATH_MAX] = {'\0'};
199 
200         portAttributeFile = portAttributeDir + "/" + it;
201         int32_t fd = OpenFile(portAttributeFile, O_RDONLY);
202         if (fd < 0) {
203             HDF_LOGE("%{public}s: file open error fd = %{public}d", __func__, fd);
204             return HDF_FAILURE;
205         }
206 
207         ret = read(fd, buff, PATH_MAX - 1);
208         close(fd);
209         if (ret < 0) {
210             HDF_LOGE("%{public}s: read error: %{public}s", __func__, portAttributeFile.c_str());
211             return HDF_FAILURE;
212         }
213 
214         ret = ParsePortAttribute(it, buff, usbPort);
215         if (ret != HDF_SUCCESS) {
216             HDF_LOGE("%{public}s: ParsePortAttribute failed! ret:%{public}d", __func__, ret);
217             return HDF_FAILURE;
218         }
219     }
220 
221     return HDF_SUCCESS;
222 }
223 
OpenFile(const std::string & path,int32_t flags)224 int32_t UsbdPorts::OpenFile(const std::string& path, int32_t flags)
225 {
226     if (path.empty()) {
227         HDF_LOGE("%{public}s: The path cannot be empty", __func__);
228         return HDF_FAILURE;
229     }
230 
231     char realpathStr[PATH_MAX] = {'\0'};
232     if (realpath(path.c_str(), realpathStr) == nullptr) {
233         HDF_LOGE("%{public}s : realpath failed. ret = %{public}s", __func__, strerror(errno));
234         return HDF_FAILURE;
235     }
236     return open(realpathStr, flags);
237 }
238 
ParsePortAttribute(const std::string & portAttributeFileName,const std::string & buff,V2_0::UsbPort & usbPort)239 int32_t UsbdPorts::ParsePortAttribute(const std::string& portAttributeFileName,
240     const std::string& buff, V2_0::UsbPort& usbPort)
241 {
242     HDF_LOGI("%{public}s start", __func__);
243     if (portAttributeFileName == "port_mode") {
244         return GetAttributeValue(buff, usbPort.usbPortStatus.currentMode);
245     } else if (portAttributeFileName == "power_role") {
246         return GetAttributeValue(buff, usbPort.usbPortStatus.currentPowerRole);
247     } else if (portAttributeFileName == "data_role") {
248         return GetAttributeValue(buff, usbPort.usbPortStatus.currentDataRole);
249     } else if (portAttributeFileName == "supported_mode") {
250         return GetAttributeValue(buff, usbPort.supportedModes);
251     }
252 
253     return HDF_SUCCESS;
254 }
255 
GetAttributeValue(const std::string & buff,int32_t & outEnumValue)256 int32_t UsbdPorts::GetAttributeValue(const std::string& buff, int32_t& outEnumValue)
257 {
258     if (portAttributeMap_.find(buff) == portAttributeMap_.end()) {
259         HDF_LOGE("%{public}s: %{public}s is invalid value", __func__, buff.c_str());
260         return HDF_FAILURE;
261     }
262 
263     outEnumValue = portAttributeMap_[buff];
264     return HDF_SUCCESS;
265 }
266 
AddPort(const V2_0::UsbPort & port)267 void UsbdPorts::AddPort(const V2_0::UsbPort &port)
268 {
269     portCacheDataMap_[port.id] = port;
270 }
271 
IsSupportedMode(int32_t portId)272 bool UsbdPorts::IsSupportedMode(int32_t portId)
273 {
274     auto it = portCacheDataMap_.find(portId);
275     if (it == portCacheDataMap_.end()) {
276         HDF_LOGE("%{public}s: portId not exist, set failed", __func__);
277         return false;
278     }
279 
280     if (it->second.supportedModes == NONE) {
281         HDF_LOGE("%{public}s The mode does not support settings", __func__);
282         return false;
283     }
284 
285     return true;
286 }
287 
SetPort(int32_t portId,int32_t powerRole,int32_t dataRole,UsbdSubscriber * usbdSubscribers,uint32_t len)288 int32_t UsbdPorts::SetPort(int32_t portId, int32_t powerRole, int32_t dataRole,
289     UsbdSubscriber *usbdSubscribers, uint32_t len)
290 {
291     HDF_LOGI("%{public}s: SetPort start", __func__);
292     auto usbPort = portCacheDataMap_.begin();
293     if (portId != usbPort->first) {
294         HDF_LOGE("%{public}s: portId not exist, set failed", __func__);
295         return HDF_FAILURE;
296     }
297 
298     if (!IsSupportedMode(portId)) {
299         return HDF_FAILURE;
300     }
301 
302     V2_0::UsbPort port;
303     int32_t ret = SetPortInfo(portId, powerRole, dataRole, port);
304     if (ret != HDF_SUCCESS) {
305         HDF_LOGE("%{public}s: SetPortInfo failed", __func__);
306         return HDF_FAILURE;
307     }
308 
309     for (uint32_t i = 0; i < len; i++) {
310         if (usbdSubscribers[i].subscriber != nullptr) {
311             PortInfo portInfo;
312             ReportData(port, portInfo);
313             usbdSubscribers[i].subscriber->PortChangedEvent(portInfo);
314         }
315     }
316 
317     AddPort(port);
318     return HDF_SUCCESS;
319 }
320 
SetPort(int32_t portId,int32_t powerRole,int32_t dataRole,V2_0::UsbdSubscriber * usbdSubscribers,uint32_t len)321 int32_t UsbdPorts::SetPort(int32_t portId, int32_t powerRole, int32_t dataRole,
322     V2_0::UsbdSubscriber *usbdSubscribers, uint32_t len)
323 {
324     HDF_LOGI("%{public}s: SetPort start", __func__);
325     if (!IsSupportedMode(portId)) {
326         return HDF_FAILURE;
327     }
328 
329     V2_0::UsbPort port;
330     int32_t ret = SetPortInfo(portId, powerRole, dataRole, port);
331     if (ret != HDF_SUCCESS) {
332         HDF_LOGE("%{public}s: SetPortInfo failed", __func__);
333         return HDF_FAILURE;
334     }
335 
336     for (uint32_t i = 0; i < len; i++) {
337         if (usbdSubscribers[i].subscriber != nullptr) {
338             V2_0::PortInfo portInfo;
339             ReportData(port, portInfo);
340             usbdSubscribers[i].subscriber->PortChangedEvent(portInfo);
341         }
342     }
343 
344     AddPort(port);
345     return HDF_SUCCESS;
346 }
347 
SetPortInfo(int32_t portId,int32_t powerRole,int32_t dataRole,V2_0::UsbPort & port)348 int32_t UsbdPorts::SetPortInfo(int32_t portId, int32_t powerRole, int32_t dataRole, V2_0::UsbPort& port)
349 {
350     if (path_ == "/data/service/el1/public/usb/mode") {
351         HDF_LOGE("%{public}s: not support", __func__);
352         return HDF_ERR_NOT_SUPPORT;
353     }
354 
355     if (!IsRoleValueLegality(powerRole, dataRole)) {
356         HDF_LOGE("%{public}s: invalid powerRole or dataRole", __func__);
357         return HDF_FAILURE;
358     }
359 
360     port = portCacheDataMap_[portId];
361     const std::string portIdNode = std::to_string(portId);
362     std::string data;
363     GetRoleStrValue(powerRole, data, true);
364     int32_t ret = WritePortInfo(portIdNode, "power_role", data);
365     if (ret != HDF_SUCCESS) {
366         HDF_LOGE("%{public}s: Execute WritePortInfo failed", __func__);
367         return HDF_FAILURE;
368     }
369 
370     GetRoleStrValue(dataRole, data, false);
371     WritePortInfo(portIdNode, "data_role", data);
372     if (ret != HDF_SUCCESS) {
373         HDF_LOGE("%{public}s: Execute WritePortInfo failed", __func__);
374         return HDF_FAILURE;
375     }
376 
377     if (portCacheDataMap_.find(portId) == portCacheDataMap_.end()) {
378         HDF_LOGE("%{public}s: portId not found", __func__);
379         return HDF_FAILURE;
380     }
381 
382     port.usbPortStatus.currentPowerRole = powerRole;
383     port.usbPortStatus.currentDataRole = dataRole;
384 
385     return HDF_SUCCESS;
386 }
387 
IsRoleValueLegality(int32_t powerRole,int32_t dataRole)388 bool UsbdPorts::IsRoleValueLegality(int32_t powerRole, int32_t dataRole)
389 {
390     if (powerRole < (int32_t)PowerRole::NONE || powerRole >= (int32_t)PowerRole::NUM_POWER_ROLES
391         || dataRole < (int32_t)DataRole::NONE || dataRole >= (int32_t)DataRole::NUM_DATA_ROLES) {
392         return false;
393     }
394 
395     return true;
396 }
397 
WritePortInfo(const std::string & portId,const std::string & portAttributeFilePath,std::string & data)398 int32_t UsbdPorts::WritePortInfo(const std::string& portId, const std::string& portAttributeFilePath, std::string& data)
399 {
400     HDF_LOGI("%{public}s: start", __func__);
401     std::lock_guard<std::mutex> lock(mutex_);
402     std::string writePath = path_ + "port" + portId + "/" + portAttributeFilePath;
403 
404     int32_t fd = OpenFile(writePath, O_WRONLY | O_TRUNC);
405     if (fd < 0) {
406         HDF_LOGE("%{public}s: file open error! ret:%{public}s", __func__, writePath.c_str());
407         return HDF_FAILURE;
408     }
409 
410     int32_t ret = write(fd, data.c_str(), data.size());
411     close(fd);
412     if (ret <= 0) {
413         HDF_LOGE("%{public}s: write file failed! ret:%{public}d path: %{public}s",
414             __func__, ret, writePath.c_str());
415         return HDF_FAILURE;
416     }
417 
418     return HDF_SUCCESS;
419 }
420 
GetRoleStrValue(int32_t role,std::string & strRole,bool flag)421 void UsbdPorts::GetRoleStrValue(int32_t role, std::string& strRole, bool flag)
422 {
423     for (auto it : portAttributeMap_) {
424         if (flag) {
425             // powerRole
426             if ((it.first != POWER_ROLE_SOURCE) && (it.first != POWER_ROLE_SINK)) {
427                 continue;
428             }
429             if (it.second == role) {
430                 strRole = it.first;
431                 break;
432             }
433         } else {
434             //dataRole
435             if ((it.first != DATA_ROLE_HOST) && (it.first != DATA_ROLE_DEVICE)) {
436                 continue;
437             }
438             if (it.second == role) {
439                 strRole = it.first;
440                 break;
441             }
442         }
443     }
444 }
445 
IsUpdate(const V2_0::UsbPort & usbPortInfo)446 bool UsbdPorts::IsUpdate(const V2_0::UsbPort& usbPortInfo)
447 {
448     HDF_LOGI("%{public}s: start", __func__);
449     if (portCacheDataMap_.find(usbPortInfo.id) == portCacheDataMap_.end()) {
450         return true;
451     }
452 
453     V2_0::UsbPort usbPort = portCacheDataMap_[usbPortInfo.id];
454     if (usbPort.usbPortStatus.currentMode != usbPortInfo.usbPortStatus.currentMode
455     || usbPort.usbPortStatus.currentPowerRole != usbPortInfo.usbPortStatus.currentPowerRole
456     || usbPort.usbPortStatus.currentDataRole != usbPortInfo.usbPortStatus.currentDataRole
457     || usbPort.supportedModes != usbPortInfo.supportedModes) {
458         return true;
459     }
460 
461     return false;
462 }
463 
ReportData(const V2_0::UsbPort & usbPort,V2_0::PortInfo & portInfo)464 void UsbdPorts::ReportData(const V2_0::UsbPort& usbPort, V2_0::PortInfo& portInfo)
465 {
466     HDF_LOGI("%{public}s: start", __func__);
467     portInfo.portId = usbPort.id;
468     portInfo.supportedModes = usbPort.supportedModes;
469     portInfo.powerRole = usbPort.usbPortStatus.currentPowerRole;
470     portInfo.dataRole = usbPort.usbPortStatus.currentDataRole;
471     portInfo.mode = usbPort.usbPortStatus.currentMode;
472 }
473 
ReportData(const V2_0::UsbPort & usbPort,PortInfo & portInfo)474 void UsbdPorts::ReportData(const V2_0::UsbPort& usbPort, PortInfo& portInfo)
475 {
476     HDF_LOGI("%{public}s: start", __func__);
477     portInfo.portId = usbPort.id;
478     portInfo.powerRole = usbPort.usbPortStatus.currentPowerRole;
479     portInfo.dataRole = usbPort.usbPortStatus.currentDataRole;
480     portInfo.mode = usbPort.usbPortStatus.currentMode;
481 }
482 
UpdatePort(int32_t mode,const sptr<IUsbdSubscriber> & subscriber)483 int32_t UsbdPorts::UpdatePort(int32_t mode, const sptr<IUsbdSubscriber>& subscriber)
484 {
485     (void)mode;
486     std::vector<V2_0::UsbPort> portList;
487     int32_t ret = QueryPorts(portList);
488     if (ret != HDF_SUCCESS) {
489         HDF_LOGE("%{public}s: data update failuer", __func__);
490         return HDF_FAILURE;
491     }
492 
493     for (size_t i = 0; i < portList.size(); i++) {
494         if (IsUpdate(portList.at(i))) {
495             PortInfo portInfo;
496             ReportData(portList.at(i), portInfo);
497             subscriber->PortChangedEvent(portInfo);
498         }
499     }
500 
501     return HDF_SUCCESS;
502 }
503 
UpdatePort(int32_t mode,const sptr<OHOS::HDI::Usb::V2_0::IUsbdSubscriber> & subscriber)504 int32_t UsbdPorts::UpdatePort(int32_t mode, const sptr<OHOS::HDI::Usb::V2_0::IUsbdSubscriber>& subscriber)
505 {
506     (void)mode;
507     std::vector<V2_0::UsbPort> portList;
508     int32_t ret = QueryPorts(portList);
509     if (ret != HDF_SUCCESS) {
510         HDF_LOGE("%{public}s: data update failuer", __func__);
511         return HDF_FAILURE;
512     }
513 
514     for (size_t i = 0; i < portList.size(); i++) {
515         if (IsUpdate(portList.at(i))) {
516             V2_0::PortInfo portInfo;
517             ReportData(portList.at(i), portInfo);
518             subscriber->PortChangedEvent(portInfo);
519         }
520     }
521 
522     return HDF_SUCCESS;
523 }
524 } // namespace V1_2
525 } // namespace Usb
526 } // namespace HDI
527 } // namespace OHOS
528