1 /*
2 * Copyright (c) 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
16 #include <regex>
17 #include <unistd.h>
18 #include "hisysevent.h"
19 #include "usb_errors.h"
20 #include "securec.h"
21 #include "serial_manager.h"
22 #include "hilog_wrapper.h"
23 #include "tokenid_kit.h"
24 #include "accesstoken_kit.h"
25
26 #define DUMP_PARAMS_NUM_2 2
27
28 using namespace OHOS::HiviewDFX;
29 using OHOS::USB::USB_MGR_LABEL;
30 using OHOS::USB::MODULE_USB_SERVICE;
31 using OHOS::USB::UEC_OK;
32
33 namespace OHOS {
34 namespace SERIAL {
35 constexpr int32_t PARAM_COUNT_ONE = 1;
36 constexpr int32_t ERR_CODE_IOEXCEPTION = -1;
37 constexpr int32_t ERR_CODE_DEVICENOTOPEN = -6;
38 constexpr int32_t ERR_CODE_TIMEOUT = -7;
39 constexpr int32_t ERR_CODE_ERROR_OVERFLOW = -8;
40
SerialManager()41 SerialManager::SerialManager()
42 {
43 if (serial_ == nullptr) {
44 serial_ = OHOS::HDI::Usb::Serial::V1_0::ISerialInterface::Get("serial_interface_service", true);
45 if (serial_ == nullptr) {
46 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: serial_ is nullptr", __func__);
47 }
48 }
49
50 usbRightManager_ = std::make_shared<USB::UsbRightManager>();
51 }
52
~SerialManager()53 SerialManager::~SerialManager()
54 {
55 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: start", __func__);
56 }
57
ErrorCodeWrap(int32_t errorCode)58 inline int32_t ErrorCodeWrap(int32_t errorCode)
59 {
60 if (errorCode == ERR_CODE_IOEXCEPTION || errorCode == ERR_CODE_ERROR_OVERFLOW) {
61 return USB::UEC_SERIAL_IO_EXCEPTION;
62 } else if (errorCode == ERR_CODE_DEVICENOTOPEN) {
63 return USB::UEC_SERIAL_DEVICENOTOPEN;
64 } else if (errorCode == ERR_CODE_TIMEOUT) {
65 return USB::UEC_INTERFACE_TIMED_OUT;
66 } else {
67 return USB::UEC_SERIAL_OTHER_ERROR;
68 }
69 }
70
CheckPortAndTokenId(int32_t portId)71 int32_t SerialManager::CheckPortAndTokenId(int32_t portId)
72 {
73 if (serial_ == nullptr) {
74 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: serial_ is nullptr", __func__);
75 return OHOS::USB::UEC_SERVICE_INVALID_VALUE;
76 }
77
78 if (!IsPortStatus(portId)) {
79 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: The port is not open", __func__);
80 return OHOS::USB::UEC_SERIAL_PORT_NOT_OPEN;
81 }
82
83 if (!CheckTokenIdValidity(portId)) {
84 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: Application ID mismatch", __func__);
85 return OHOS::USB::UEC_SERIAL_PORT_NOT_OPEN;
86 }
87
88 return UEC_OK;
89 }
90
SerialOpen(int32_t portId)91 int32_t SerialManager::SerialOpen(int32_t portId)
92 {
93 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: start", __func__);
94 if (serial_ == nullptr) {
95 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: serial_ is nullptr", __func__);
96 return OHOS::USB::UEC_SERVICE_INVALID_VALUE;
97 }
98
99 if (portTokenMap_.find(portId) != portTokenMap_.end()) {
100 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: The port has been opened", __func__);
101 return OHOS::USB::UEC_SERIAL_PORT_REPEAT_OPEN;
102 }
103
104 int32_t ret = serial_->SerialOpen(portId);
105 if (ret != UEC_OK) {
106 return ErrorCodeWrap(ret);
107 }
108
109 portTokenMap_[portId] = IPCSkeleton::GetCallingTokenID();
110 return ret;
111 }
112
SerialClose(int32_t portId)113 int32_t SerialManager::SerialClose(int32_t portId)
114 {
115 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: start", __func__);
116 if (serial_ == nullptr) {
117 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: serial_ is nullptr", __func__);
118 return OHOS::USB::UEC_SERVICE_INVALID_VALUE;
119 }
120
121 if (!IsPortStatus(portId)) {
122 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: The port not open", __func__);
123 return OHOS::USB::UEC_SERIAL_PORT_NOT_OPEN;
124 }
125
126 if (!CheckTokenIdValidity(portId)) {
127 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: The port not open", __func__);
128 return OHOS::USB::UEC_SERIAL_PORT_NOT_OPEN;
129 }
130
131 int32_t ret = serial_->SerialClose(portId);
132 if (ret != UEC_OK) {
133 return ErrorCodeWrap(ret);
134 }
135
136 portTokenMap_.erase(portId);
137 return ret;
138 }
139
SerialRead(int32_t portId,std::vector<uint8_t> & data,uint32_t size,uint32_t & actualSize,uint32_t timeout)140 int32_t SerialManager::SerialRead(int32_t portId, std::vector<uint8_t> &data, uint32_t size,
141 uint32_t &actualSize, uint32_t timeout)
142 {
143 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: start", __func__);
144
145 int32_t ret = CheckPortAndTokenId(portId);
146 if (ret != UEC_OK) {
147 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: CheckPortAndTokenId failed", __func__);
148 return ret;
149 }
150
151 ret = serial_->SerialRead(portId, data, size, timeout);
152 if (ret < UEC_OK) {
153 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: SerialRead failed ret = %{public}d", __func__, ret);
154 return ErrorCodeWrap(ret);
155 }
156 actualSize = static_cast<uint32_t>(ret);
157 return UEC_OK;
158 }
159
SerialWrite(int32_t portId,const std::vector<uint8_t> & data,uint32_t size,uint32_t & actualSize,uint32_t timeout)160 int32_t SerialManager::SerialWrite(int32_t portId, const std::vector<uint8_t>& data, uint32_t size,
161 uint32_t &actualSize, uint32_t timeout)
162 {
163 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: start", __func__);
164 int32_t ret = CheckPortAndTokenId(portId);
165 if (ret != UEC_OK) {
166 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: CheckPortAndTokenId failed", __func__);
167 return ret;
168 }
169
170 ret = serial_->SerialWrite(portId, data, size, timeout);
171 if (ret < UEC_OK) {
172 return ErrorCodeWrap(ret);
173 }
174 actualSize = static_cast<uint32_t>(ret);
175 return UEC_OK;
176 }
177
SerialGetAttribute(int32_t portId,OHOS::HDI::Usb::Serial::V1_0::SerialAttribute & attribute)178 int32_t SerialManager::SerialGetAttribute(int32_t portId, OHOS::HDI::Usb::Serial::V1_0::SerialAttribute& attribute)
179 {
180 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: start", __func__);
181 int32_t ret = CheckPortAndTokenId(portId);
182 if (ret != UEC_OK) {
183 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: CheckPortAndTokenId failed", __func__);
184 return ret;
185 }
186
187 ret = serial_->SerialGetAttribute(portId, attribute);
188 if (ret != UEC_OK) {
189 return ErrorCodeWrap(ret);
190 }
191
192 return ret;
193 }
194
SerialSetAttribute(int32_t portId,const OHOS::HDI::Usb::Serial::V1_0::SerialAttribute & attribute)195 int32_t SerialManager::SerialSetAttribute(int32_t portId,
196 const OHOS::HDI::Usb::Serial::V1_0::SerialAttribute& attribute)
197 {
198 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: start", __func__);
199 int32_t ret = CheckPortAndTokenId(portId);
200 if (ret != UEC_OK) {
201 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: CheckPortAndTokenId failed", __func__);
202 return ret;
203 }
204
205 ret = serial_->SerialSetAttribute(portId, attribute);
206 if (ret != UEC_OK) {
207 return ErrorCodeWrap(ret);
208 }
209
210 return ret;
211 }
212
SerialGetPortList(std::vector<OHOS::HDI::Usb::Serial::V1_0::SerialPort> & serialPortList)213 int32_t SerialManager::SerialGetPortList(std::vector<OHOS::HDI::Usb::Serial::V1_0::SerialPort>& serialPortList)
214 {
215 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: start", __func__);
216
217 if (serial_ == nullptr) {
218 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: serial_ is nullptr", __func__);
219 return OHOS::USB::UEC_SERVICE_INVALID_VALUE;
220 }
221
222 int32_t ret = serial_->SerialGetPortList(serialPortList);
223 if (ret != UEC_OK) {
224 return ret;
225 }
226
227 UpdateSerialPortMap(serialPortList);
228 return ret;
229 }
230
UpdateSerialPortMap(std::vector<OHOS::HDI::Usb::Serial::V1_0::SerialPort> & serialPortList)231 void SerialManager::UpdateSerialPortMap(std::vector<OHOS::HDI::Usb::Serial::V1_0::SerialPort>& serialPortList)
232 {
233 std::lock_guard<std::mutex> guard(serialPortMapMutex_);
234 for (auto& it : serialPortList) {
235 serialPortMap_[it.portId] = it;
236 }
237 }
238
IsPortIdExist(int32_t portId)239 bool SerialManager::IsPortIdExist(int32_t portId)
240 {
241 std::lock_guard<std::mutex> guard(serialPortMapMutex_);
242 if (serialPortMap_.find(portId) == serialPortMap_.end()) {
243 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: port %{public}d not exist", __func__, portId);
244 return false;
245 }
246
247 return true;
248 }
249
IsPortStatus(int32_t portId)250 bool SerialManager::IsPortStatus(int32_t portId)
251 {
252 return portTokenMap_.find(portId) != portTokenMap_.end();
253 }
254
CheckTokenIdValidity(int32_t portId)255 bool SerialManager::CheckTokenIdValidity(int32_t portId)
256 {
257 if (IPCSkeleton::GetCallingTokenID() != portTokenMap_[portId]) {
258 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: The tokenId corresponding to the port is incorrect", __func__);
259 return false;
260 }
261
262 return true;
263 }
264
FreeTokenId(int32_t portId,uint32_t tokenId)265 void SerialManager::FreeTokenId(int32_t portId, uint32_t tokenId)
266 {
267 USB_HILOGI(MODULE_USB_SERVICE, "%{public}s: start", __func__);
268 if ((portTokenMap_.find(portId) == portTokenMap_.end()) || (portTokenMap_[portId] != tokenId)) {
269 USB_HILOGE(MODULE_USB_SERVICE, "%{public}s: portid not exist or tokenId failed", __func__);
270 return;
271 }
272
273 if (serial_ != nullptr) {
274 serial_->SerialClose(portId);
275 }
276
277 portTokenMap_.erase(portId);
278 }
279
SerialPortListDump(int32_t fd,const std::vector<std::string> & args)280 void SerialManager::SerialPortListDump(int32_t fd, const std::vector<std::string>& args)
281 {
282 if (args.size() != PARAM_COUNT_ONE) {
283 dprintf(fd, "port param error: exactly %d parameters are required\n", PARAM_COUNT_ONE);
284 ListGetDumpHelp(fd);
285 return;
286 }
287
288 if (args[0] == "-l") {
289 std::vector<OHOS::HDI::Usb::Serial::V1_0::SerialPort> serialPortList;
290 SerialGetPortList(serialPortList);
291 dprintf(fd, "=========== dump the serial port list ===========\n");
292 for (size_t i = 0; i < serialPortList.size(); ++i) {
293 char portName[20];
294 snprintf_s(portName, sizeof(portName), sizeof(portName)-1, "ttyUSB%zu", i);
295 dprintf(fd, "%s\n", portName);
296 }
297 dprintf(fd, "------------------------------------------------\n");
298 } else {
299 dprintf(fd, "port param error: invalid command '%s'\n", args[0].c_str());
300 ListGetDumpHelp(fd);
301 }
302 }
303
CheckDataAndProcessPortId(int32_t fd,const std::vector<std::string> & args,OHOS::HDI::Usb::Serial::V1_0::SerialAttribute attribute)304 bool SerialManager::CheckDataAndProcessPortId(int32_t fd, const std::vector<std::string>& args,
305 OHOS::HDI::Usb::Serial::V1_0::SerialAttribute attribute)
306 {
307 if (!args.empty() && !std::regex_match(args[1], std::regex("^[0-9]+$"))) {
308 dprintf(fd, "Invalid input, please enter a valid integer\n");
309 return false;
310 }
311 int32_t portId = std::stoi(args[1]);
312 int32_t ret = SerialGetAttribute(portId, attribute);
313 if (ret != UEC_OK) {
314 ret = SerialOpen(portId);
315 if (ret != UEC_OK) {
316 USB_HILOGE(MODULE_USB_SERVICE, "SerialOpen failed");
317 dprintf(fd, "Port %zu: port does not exist\n", portId);
318 return false;
319 }
320 ret = SerialGetAttribute(portId, attribute);
321 if (ret != UEC_OK) {
322 USB_HILOGE(MODULE_USB_SERVICE, "SerialGetAttribute failed");
323 }
324 SerialClose(portId);
325 }
326 dprintf(fd, "Port %zu: baudrate: %zu stopBits:%zu parity:%zu dataBits:%zu\n",
327 portId, attribute.baudrate, attribute.stopBits, attribute.parity, attribute.dataBits);
328 return true;
329 }
330
SerialGetAttributeDump(int32_t fd,const std::vector<std::string> & args)331 void SerialManager::SerialGetAttributeDump(int32_t fd, const std::vector<std::string>& args)
332 {
333 size_t size = args.size();
334 OHOS::HDI::Usb::Serial::V1_0::SerialAttribute attribute;
335 if (size == 1) {
336 std::vector<OHOS::HDI::Usb::Serial::V1_0::SerialPort> serialPortList;
337 int32_t ret = SerialGetPortList(serialPortList);
338 if (ret != UEC_OK) {
339 USB_HILOGE(MODULE_USB_SERVICE, "SerialGetPortList failed");
340 return;
341 }
342 size_t portCount = serialPortList.size();
343 for (size_t i = 0; i < portCount; ++i) {
344 if (i > INT32_MAX) {
345 USB_HILOGE(MODULE_USB_SERVICE, "SerialGetPortList port index out of range");
346 break;
347 }
348 int32_t portId = static_cast<int32_t>(serialPortList[i].portId);
349 ret = SerialGetAttribute(portId, attribute);
350 if (ret != UEC_OK) {
351 SerialOpen(portId);
352 SerialGetAttribute(portId, attribute);
353 SerialClose(portId);
354 }
355 dprintf(fd, "Port %zu: baudrate: %zu stopBits:%zu parity:%zu dataBits:%zu\n",
356 i, attribute.baudrate, attribute.stopBits, attribute.parity, attribute.dataBits);
357 }
358 } else if (size == DUMP_PARAMS_NUM_2) {
359 if (!CheckDataAndProcessPortId(fd, args, attribute)) {
360 USB_HILOGE(MODULE_USB_SERVICE, "CheckDataAndProcessPortId failed");
361 return;
362 }
363 } else {
364 ListGetDumpHelp(fd);
365 }
366 }
367
ListGetDumpHelp(int32_t fd)368 void SerialManager::ListGetDumpHelp(int32_t fd)
369 {
370 dprintf(fd, "=========== dump the serial port information ===========\n");
371 dprintf(fd, "serail -l: Query All Serial Port List\n");
372 dprintf(fd, "serial -h: Serial port help\n");
373 dprintf(fd, "serial -g : Gets the properties of all ports\n");
374 dprintf(fd, "serial \"-g [port number]\": Gets the properties of the specified port\n");
375 dprintf(fd, "------------------------------------------------\n");
376 }
377
GetSerialPort(int32_t portId,OHOS::HDI::Usb::Serial::V1_0::SerialPort & serialPort)378 bool SerialManager::GetSerialPort(int32_t portId, OHOS::HDI::Usb::Serial::V1_0::SerialPort& serialPort)
379 {
380 if (serialPortMap_.find(portId) == serialPortMap_.end()) {
381 USB_HILOGI(MODULE_USB_SERVICE, "serialPort not found");
382 return false;
383 }
384
385 serialPort = serialPortMap_[portId];
386 return true;
387 }
388 } //namespace SERIAL
389 } //namespace OHOS
390