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