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