1 /*
2  * Copyright (C) 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 #include "oh_usb.h"
16 #include "usb_ffs.h"
17 #include "usb_util.h"
18 #include "sys_para.h"
19 #include "log.h"
20 
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <cstring>
24 #include <cerrno>
25 #include <csignal>
26 
27 using namespace Hdc;
28 
29 static constexpr int CONFIG_COUNT2 = 2;
30 static constexpr int CONFIG_COUNT3 = 3;
31 static constexpr int CONFIG_COUNT5 = 5;
32 
33 // make gnuc++ happy. Clang support direct assignment value to structure, buf g++ weakness
FillUsbV2Head(struct Hdc::UsbFunctionfsDescV2 &descUsbFfs)34 void FillUsbV2Head(struct Hdc::UsbFunctionfsDescV2 &descUsbFfs)
35 {
36     descUsbFfs.head.magic = LONG_LE(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
37     descUsbFfs.head.length = LONG_LE(sizeof(descUsbFfs));
38     descUsbFfs.head.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
39                             FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC;
40     descUsbFfs.config1Count = CONFIG_COUNT3;
41     descUsbFfs.config2Count = CONFIG_COUNT3;
42     descUsbFfs.config3Count = CONFIG_COUNT5;
43     descUsbFfs.configWosCount = CONFIG_COUNT2;
44     descUsbFfs.config1Desc = Hdc::config1;
45     descUsbFfs.config2Desc = Hdc::config2;
46     descUsbFfs.config3Desc = Hdc::config3;
47     descUsbFfs.wosHead = Hdc::g_wosHead;
48     descUsbFfs.wosDesc = Hdc::g_wosDesc;
49     descUsbFfs.osPropHead = Hdc::g_osPropHead;
50     descUsbFfs.osPropValues = Hdc::g_osPropValues;
51 }
52 
ConfigEpPoint(int& controlEp, const std::string& path)53 int ConfigEpPoint(int& controlEp, const std::string& path)
54 {
55     struct Hdc::UsbFunctionfsDescV2 descUsbFfs = {};
56     FillUsbV2Head(descUsbFfs);
57     while (true) {
58         if (controlEp <= 0) {
59             // After the control port sends the instruction, the device is initialized by the device to the HOST host,
60             // which can be found for USB devices. Do not send initialization to the EP0 control port, the USB
61             // device will not be initialized by Host
62             WRITE_LOG(LOG_INFO, "Begin send to control(EP0) for usb descriptor init\n");
63             if ((controlEp = open(path.c_str(), O_RDWR)) < 0) {
64                 WRITE_LOG(LOG_WARN, "%s: cannot open control endpoint: errno=%d\n", path.c_str(), errno);
65                 break;
66             }
67             if (write(controlEp, &descUsbFfs, sizeof(descUsbFfs)) < 0) {
68                 WRITE_LOG(LOG_WARN, "%s: write ffs configs failed: errno=%d\n", path.c_str(), errno);
69                 break;
70             }
71             if (write(controlEp, &Hdc::USB_FFS_VALUE, sizeof(Hdc::USB_FFS_VALUE)) < 0) {
72                 WRITE_LOG(LOG_WARN, "%s: write USB_FFS_VALUE failed: errno=%d\n", path.c_str(), errno);
73                 break;
74             }
75             // active usbrc, Send USB initialization signal
76             WRITE_LOG(LOG_INFO, "ConnectEPPoint ctrl init finish, set usb-ffs ready\n");
77             fcntl(controlEp, F_SETFD, FD_CLOEXEC);
78             Hdc::SetDevItem("sys.usb.ffs.ready.hdc", "0");
79             Hdc::SetDevItem("sys.usb.ffs.ready", "1");
80             Hdc::SetDevItem("sys.usb.ffs.ready.hdc", "1");
81             return ERR_SUCCESS;
82         }
83     }
84     return ERR_GENERIC;
85 }
86 
OpenEpPoint(int &fd, const std::string path)87 int OpenEpPoint(int &fd, const std::string path)
88 {
89     if ((fd = open(path.c_str(), O_RDWR)) < 0) {
90         WRITE_LOG(LOG_WARN, "%s: cannot open ep: errno=%d\n", path.c_str(), errno);
91         return ERR_GENERIC;
92     }
93     fcntl(fd, F_SETFD, FD_CLOEXEC);
94     return ERR_SUCCESS;
95 }
96 
CloseUsbFd(int &fd)97 int CloseUsbFd(int &fd)
98 {
99         int rc = 0;
100 #ifndef HDC_HOST
101         WRITE_LOG(LOG_INFO, "CloseFd fd:%d\n", fd);
102 #endif
103         if (fd > 0) {
104             rc = close(fd);
105             if (rc < 0) {
106                 char buffer[Hdc::BUF_SIZE_DEFAULT] = { 0 };
107 #ifdef _WIN32
108                 strerror_s(buffer, Hdc::BUF_SIZE_DEFAULT, errno);
109 #else
110                 strerror_r(errno, buffer, Hdc::BUF_SIZE_DEFAULT);
111 #endif
112                 WRITE_LOG(LOG_WARN, "close failed errno:%d %s\n", errno, buffer);
113             } else {
114                 fd = -1;
115             }
116         }
117         return rc;
118 }
119 
CloseEndpoint(int &bulkInFd, int &bulkOutFd, int &controlEp, bool closeCtrlEp)120 void CloseEndpoint(int &bulkInFd, int &bulkOutFd, int &controlEp, bool closeCtrlEp)
121 {
122     CloseUsbFd(bulkInFd);
123     CloseUsbFd(bulkOutFd);
124     if (controlEp > 0 && closeCtrlEp) {
125         CloseUsbFd(controlEp);
126         controlEp = 0;
127     }
128     WRITE_LOG(LOG_INFO, "close endpoint ok\n");
129 }
130 
WriteData(int bulkIn, const uint8_t *data, const int length)131 int WriteData(int bulkIn, const uint8_t *data, const int length)
132 {
133     int ret;
134     int writen = 0;
135     bool restoreSigmask = true;
136 
137     sigset_t newmask;
138     sigset_t oldmask;
139     sigemptyset(&newmask);
140     sigaddset(&newmask, SIGCHLD);
141     if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
142 #ifndef HDC_HOST
143         WRITE_LOG(LOG_FATAL, "before write usb, ignor the sigchld failed, err(%d)\n", errno);
144 #endif
145         restoreSigmask = false;
146     }
147 
148     while (writen < length) {
149         ret = write(bulkIn, const_cast<uint8_t *>(data + writen), length - writen);
150         if (ret < 0) {
151             if (errno == EINTR) {
152 #ifndef HDC_HOST
153                 WRITE_LOG(LOG_FATAL, "write usb fd(%d) (%d) bytes interrupted, will retry\n",
154                     bulkIn, length - writen);
155 #endif
156                 continue;
157             }
158 #ifndef HDC_HOST
159             WRITE_LOG(LOG_FATAL, "write usb fd(%d) (%d) bytes failed(%d), err(%d)\n",
160                 bulkIn, length - writen, ret, errno);
161 #endif
162             break;
163         }
164         writen += ret;
165     }
166 
167     if (restoreSigmask && sigprocmask(SIG_SETMASK, &oldmask, nullptr) < 0) {
168 #ifndef HDC_HOST
169         WRITE_LOG(LOG_FATAL, "after write usb, restore signal mask failed, err(%d)\n", errno);
170 #endif
171     }
172 
173     return ret < 0 ? ret : writen;
174 }
175 
ReadData(int bulkOut, uint8_t* buf, const size_t size)176 size_t ReadData(int bulkOut, uint8_t* buf, const size_t size)
177 {
178     int ret = -1;
179     size_t readed = 0;
180 
181     while (readed < size) {
182         ret = read(bulkOut, buf + readed, size - readed);
183         if (ret >= 0) {
184             readed += static_cast<size_t>(ret);
185         } else if (errno == EINTR) {
186 #ifndef HDC_HOST
187                 WRITE_LOG(LOG_FATAL, "read usb fd(%d) (%d) bytes interrupted, will retry\n",
188                     bulkOut, size - readed);
189 #endif
190                 continue;
191         } else {
192 #ifndef HDC_HOST
193             WRITE_LOG(LOG_FATAL, "read usb fd(%d) (%d) bytes failed(%d), err(%d)\n",
194                 bulkOut, size - readed, ret, errno);
195 #endif
196             break;
197         }
198     }
199 
200     return ret < 0 ? 0 : readed;
201 }
202