1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "usbd_port.h"
17094332d3Sopenharmony_ci#include "hdf_base.h"
18094332d3Sopenharmony_ci#include "hdf_log.h"
19094332d3Sopenharmony_ci#include "usbd_function.h"
20094332d3Sopenharmony_ci#include "usbd_wrapper.h"
21094332d3Sopenharmony_ci
22094332d3Sopenharmony_cinamespace OHOS {
23094332d3Sopenharmony_cinamespace HDI {
24094332d3Sopenharmony_cinamespace Usb {
25094332d3Sopenharmony_cinamespace V1_1 {
26094332d3Sopenharmony_ciUsbdPort &UsbdPort::GetInstance()
27094332d3Sopenharmony_ci{
28094332d3Sopenharmony_ci    static UsbdPort instance;
29094332d3Sopenharmony_ci    return instance;
30094332d3Sopenharmony_ci}
31094332d3Sopenharmony_ci
32094332d3Sopenharmony_ciint32_t UsbdPort::IfCanSwitch(int32_t portId, int32_t powerRole, int32_t dataRole)
33094332d3Sopenharmony_ci{
34094332d3Sopenharmony_ci    if (portId != DEFAULT_PORT_ID) {
35094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: portId error", __func__);
36094332d3Sopenharmony_ci        return HDF_FAILURE;
37094332d3Sopenharmony_ci    }
38094332d3Sopenharmony_ci
39094332d3Sopenharmony_ci    if (powerRole <= POWER_ROLE_NONE || powerRole >= POWER_ROLE_MAX) {
40094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: powerRole error", __func__);
41094332d3Sopenharmony_ci        return HDF_FAILURE;
42094332d3Sopenharmony_ci    }
43094332d3Sopenharmony_ci
44094332d3Sopenharmony_ci    if (dataRole <= DATA_ROLE_NONE || dataRole >= DATA_ROLE_MAX) {
45094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: dataRole error", __func__);
46094332d3Sopenharmony_ci        return HDF_FAILURE;
47094332d3Sopenharmony_ci    }
48094332d3Sopenharmony_ci
49094332d3Sopenharmony_ci    if (path_ == "/data/service/el1/public/usb/mode") {
50094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: not support", __func__);
51094332d3Sopenharmony_ci        return HDF_ERR_NOT_SUPPORT;
52094332d3Sopenharmony_ci    }
53094332d3Sopenharmony_ci    return HDF_SUCCESS;
54094332d3Sopenharmony_ci}
55094332d3Sopenharmony_ci
56094332d3Sopenharmony_ciint32_t UsbdPort::OpenPortFile(int32_t flags)
57094332d3Sopenharmony_ci{
58094332d3Sopenharmony_ci    if (path_.empty()) {
59094332d3Sopenharmony_ci        return HDF_FAILURE;
60094332d3Sopenharmony_ci    }
61094332d3Sopenharmony_ci
62094332d3Sopenharmony_ci    char pathBuf[PATH_MAX] = {'\0'};
63094332d3Sopenharmony_ci    if (realpath(path_.c_str(), pathBuf) == NULL) {
64094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: path conversion failed", __func__);
65094332d3Sopenharmony_ci        return HDF_FAILURE;
66094332d3Sopenharmony_ci    }
67094332d3Sopenharmony_ci
68094332d3Sopenharmony_ci    return open(pathBuf, flags);
69094332d3Sopenharmony_ci}
70094332d3Sopenharmony_ci
71094332d3Sopenharmony_ciint32_t UsbdPort::WritePortFile(int32_t powerRole, int32_t dataRole, int32_t mode)
72094332d3Sopenharmony_ci{
73094332d3Sopenharmony_ci    std::string modeStr;
74094332d3Sopenharmony_ci
75094332d3Sopenharmony_ci    if (mode == PORT_MODE_HOST || mode == PORT_MODE_DEVICE) {
76094332d3Sopenharmony_ci        switch (mode) {
77094332d3Sopenharmony_ci            case PORT_MODE_HOST:
78094332d3Sopenharmony_ci                modeStr = PORT_MODE_HOST_STR;
79094332d3Sopenharmony_ci                UsbdFunction::UsbdSetFunction(USB_FUNCTION_NONE);
80094332d3Sopenharmony_ci                break;
81094332d3Sopenharmony_ci            case PORT_MODE_DEVICE:
82094332d3Sopenharmony_ci                modeStr = PORT_MODE_DEVICE_STR;
83094332d3Sopenharmony_ci                break;
84094332d3Sopenharmony_ci            default:
85094332d3Sopenharmony_ci                break;
86094332d3Sopenharmony_ci        }
87094332d3Sopenharmony_ci    }
88094332d3Sopenharmony_ci    if (modeStr.empty()) {
89094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: modeStr error", __func__);
90094332d3Sopenharmony_ci        return HDF_FAILURE;
91094332d3Sopenharmony_ci    }
92094332d3Sopenharmony_ci
93094332d3Sopenharmony_ci    uint32_t len = modeStr.size();
94094332d3Sopenharmony_ci    int32_t fd = OpenPortFile(O_WRONLY | O_TRUNC);
95094332d3Sopenharmony_ci    if (fd < 0) {
96094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: file open error fd = %{public}d", __func__, fd);
97094332d3Sopenharmony_ci        return HDF_FAILURE;
98094332d3Sopenharmony_ci    }
99094332d3Sopenharmony_ci
100094332d3Sopenharmony_ci    int32_t ret = write(fd, modeStr.c_str(), len);
101094332d3Sopenharmony_ci    close(fd);
102094332d3Sopenharmony_ci    if (ret < 0) {
103094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: write  error", __func__);
104094332d3Sopenharmony_ci        return HDF_FAILURE;
105094332d3Sopenharmony_ci    }
106094332d3Sopenharmony_ci    return HDF_SUCCESS;
107094332d3Sopenharmony_ci}
108094332d3Sopenharmony_ci
109094332d3Sopenharmony_ciint32_t UsbdPort::ReadPortFile(int32_t &powerRole, int32_t &dataRole, int32_t &mode)
110094332d3Sopenharmony_ci{
111094332d3Sopenharmony_ci    int32_t fd = OpenPortFile(O_RDONLY);
112094332d3Sopenharmony_ci    if (fd < 0) {
113094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: file open error fd = %{public}d", __func__, fd);
114094332d3Sopenharmony_ci        return HDF_FAILURE;
115094332d3Sopenharmony_ci    }
116094332d3Sopenharmony_ci
117094332d3Sopenharmony_ci    char modeBuf[PATH_MAX] = {'\0'};
118094332d3Sopenharmony_ci    int32_t ret = read(fd, modeBuf, PATH_MAX - 1);
119094332d3Sopenharmony_ci    close(fd);
120094332d3Sopenharmony_ci
121094332d3Sopenharmony_ci    if (ret < 0) {
122094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: read error: %{public}s", __func__, path_.c_str());
123094332d3Sopenharmony_ci        return HDF_FAILURE;
124094332d3Sopenharmony_ci    }
125094332d3Sopenharmony_ci
126094332d3Sopenharmony_ci    if (strcmp(modeBuf, PORT_MODE_HOST_STR) == 0) {
127094332d3Sopenharmony_ci        powerRole = POWER_ROLE_SOURCE;
128094332d3Sopenharmony_ci        dataRole = DATA_ROLE_HOST;
129094332d3Sopenharmony_ci        mode = PORT_MODE_HOST;
130094332d3Sopenharmony_ci        return HDF_SUCCESS;
131094332d3Sopenharmony_ci    }
132094332d3Sopenharmony_ci
133094332d3Sopenharmony_ci    if (strcmp(modeBuf, PORT_MODE_DEVICE_STR) == 0) {
134094332d3Sopenharmony_ci        powerRole = POWER_ROLE_SINK;
135094332d3Sopenharmony_ci        dataRole = DATA_ROLE_DEVICE;
136094332d3Sopenharmony_ci        mode = PORT_MODE_DEVICE;
137094332d3Sopenharmony_ci        return HDF_SUCCESS;
138094332d3Sopenharmony_ci    }
139094332d3Sopenharmony_ci
140094332d3Sopenharmony_ci    HDF_LOGE("%{public}s: read invalid mode: %{public}s", __func__, modeBuf);
141094332d3Sopenharmony_ci    return HDF_FAILURE;
142094332d3Sopenharmony_ci}
143094332d3Sopenharmony_ci
144094332d3Sopenharmony_civoid UsbdPort::setPortPath(const std::string &path)
145094332d3Sopenharmony_ci{
146094332d3Sopenharmony_ci    path_ = path;
147094332d3Sopenharmony_ci}
148094332d3Sopenharmony_ci
149094332d3Sopenharmony_ciint32_t UsbdPort::SetPortInit(int32_t portId, int32_t powerRole, int32_t dataRole)
150094332d3Sopenharmony_ci{
151094332d3Sopenharmony_ci    auto ret = IfCanSwitch(portId, powerRole, dataRole);
152094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
153094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: can not switch function", __func__);
154094332d3Sopenharmony_ci        return ret;
155094332d3Sopenharmony_ci    }
156094332d3Sopenharmony_ci
157094332d3Sopenharmony_ci    int32_t mode = PORT_MODE_DEVICE;
158094332d3Sopenharmony_ci    if (powerRole == POWER_ROLE_SOURCE && dataRole == DATA_ROLE_HOST) {
159094332d3Sopenharmony_ci        mode = PORT_MODE_HOST;
160094332d3Sopenharmony_ci    }
161094332d3Sopenharmony_ci
162094332d3Sopenharmony_ci    if (powerRole == POWER_ROLE_SINK && dataRole == DATA_ROLE_DEVICE) {
163094332d3Sopenharmony_ci        mode = PORT_MODE_DEVICE;
164094332d3Sopenharmony_ci    }
165094332d3Sopenharmony_ci
166094332d3Sopenharmony_ci    if (WritePortFile(powerRole, dataRole, mode)) {
167094332d3Sopenharmony_ci        return HDF_FAILURE;
168094332d3Sopenharmony_ci    }
169094332d3Sopenharmony_ci    currentPortInfo_.portId = portId;
170094332d3Sopenharmony_ci    currentPortInfo_.powerRole = powerRole;
171094332d3Sopenharmony_ci    currentPortInfo_.dataRole = dataRole;
172094332d3Sopenharmony_ci    currentPortInfo_.mode = mode;
173094332d3Sopenharmony_ci    if (currentPortInfo_.mode == PORT_MODE_DEVICE) {
174094332d3Sopenharmony_ci        UsbdFunction::UsbdSetFunction(USB_FUNCTION_HDC);
175094332d3Sopenharmony_ci    }
176094332d3Sopenharmony_ci    return HDF_SUCCESS;
177094332d3Sopenharmony_ci}
178094332d3Sopenharmony_ci
179094332d3Sopenharmony_ciint32_t UsbdPort::SetPort(
180094332d3Sopenharmony_ci    int32_t portId, int32_t powerRole, int32_t dataRole, UsbdSubscriber *usbdSubscribers, uint32_t len)
181094332d3Sopenharmony_ci{
182094332d3Sopenharmony_ci    int32_t ret = SetPortInit(portId, powerRole, dataRole);
183094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
184094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: SetPortInit failed! ret:%{public}d", __func__, ret);
185094332d3Sopenharmony_ci        return ret;
186094332d3Sopenharmony_ci    }
187094332d3Sopenharmony_ci    for (uint32_t i = 0; i < len; i++) {
188094332d3Sopenharmony_ci        if (usbdSubscribers[i].subscriber != nullptr) {
189094332d3Sopenharmony_ci            usbdSubscribers[i].subscriber->PortChangedEvent(currentPortInfo_);
190094332d3Sopenharmony_ci        }
191094332d3Sopenharmony_ci    }
192094332d3Sopenharmony_ci
193094332d3Sopenharmony_ci    return HDF_SUCCESS;
194094332d3Sopenharmony_ci}
195094332d3Sopenharmony_ci
196094332d3Sopenharmony_ciint32_t UsbdPort::QueryPort(int32_t &portId, int32_t &powerRole, int32_t &dataRole, int32_t &mode)
197094332d3Sopenharmony_ci{
198094332d3Sopenharmony_ci    (void)ReadPortFile(currentPortInfo_.powerRole, currentPortInfo_.dataRole, currentPortInfo_.mode);
199094332d3Sopenharmony_ci    portId = currentPortInfo_.portId;
200094332d3Sopenharmony_ci    powerRole = currentPortInfo_.powerRole;
201094332d3Sopenharmony_ci    dataRole = currentPortInfo_.dataRole;
202094332d3Sopenharmony_ci    mode = currentPortInfo_.mode;
203094332d3Sopenharmony_ci    return HDF_SUCCESS;
204094332d3Sopenharmony_ci}
205094332d3Sopenharmony_ci
206094332d3Sopenharmony_ciint32_t UsbdPort::UpdatePort(int32_t mode, const sptr<IUsbdSubscriber> &subscriber)
207094332d3Sopenharmony_ci{
208094332d3Sopenharmony_ci    switch (mode) {
209094332d3Sopenharmony_ci        case PORT_MODE_HOST:
210094332d3Sopenharmony_ci            currentPortInfo_.powerRole = POWER_ROLE_SOURCE;
211094332d3Sopenharmony_ci            currentPortInfo_.dataRole = DATA_ROLE_HOST;
212094332d3Sopenharmony_ci            currentPortInfo_.mode = PORT_MODE_HOST;
213094332d3Sopenharmony_ci            break;
214094332d3Sopenharmony_ci        case PORT_MODE_DEVICE:
215094332d3Sopenharmony_ci            currentPortInfo_.powerRole = POWER_ROLE_SINK;
216094332d3Sopenharmony_ci            currentPortInfo_.dataRole = DATA_ROLE_DEVICE;
217094332d3Sopenharmony_ci            currentPortInfo_.mode = PORT_MODE_DEVICE;
218094332d3Sopenharmony_ci            break;
219094332d3Sopenharmony_ci        default:
220094332d3Sopenharmony_ci            HDF_LOGE("%{public}s invalid mode:%{public}d", __func__, mode);
221094332d3Sopenharmony_ci            return HDF_FAILURE;
222094332d3Sopenharmony_ci    }
223094332d3Sopenharmony_ci
224094332d3Sopenharmony_ci    if (subscriber == nullptr) {
225094332d3Sopenharmony_ci        HDF_LOGE("%{public}s subscriber is nullptr", __func__);
226094332d3Sopenharmony_ci        return HDF_FAILURE;
227094332d3Sopenharmony_ci    }
228094332d3Sopenharmony_ci    subscriber->PortChangedEvent(currentPortInfo_);
229094332d3Sopenharmony_ci    return HDF_SUCCESS;
230094332d3Sopenharmony_ci}
231094332d3Sopenharmony_ci} // namespace V1_1
232094332d3Sopenharmony_ci} // namespace Usb
233094332d3Sopenharmony_ci} // namespace HDI
234094332d3Sopenharmony_ci} // namespace OHOS
235