* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "serial_device.h"
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <cstring>
#include "securec.h"
#include "serial_consts.h"
#include "hdf_trace.h"
#include "hdf_base.h"
#include "hdf_log.h"
#undef LOG_TAG
#define LOG_TAG "SERIAL_IMPL"
#undef LOG_DOMAIN
#define LOG_DOMAIN 0xD002519
#ifndef BOTHER
#define BOTHER 0010000
#endif
#ifndef CBAUD
#define CBAUD 001017
#endif
namespace OHOS {
namespace HDI {
namespace Serial {
namespace V1_0 {
SerialDevice::SerialDevice(std::string& portName, const sptr<ISerialDeviceCallback>& cb, const SerialConfig& config)
: portName_(portName), fd_(INVALID_FD), currentConfig_(config), isOpen_(false), startRead_(false),
stopPipe_{INVALID_FD, INVALID_FD}, closePipe_{INVALID_FD, INVALID_FD}
{
cb_ = std::make_unique<SerialDeviceCallback>(cb);
HDF_LOGI("path=%{public}s!", portName_.c_str());
}
SerialDevice::~SerialDevice()
{
HDF_LOGI("%{public}s called!", __func__);
Close();
}
int32_t SerialDevice::Open()
{
std::unique_lock lock(mutex_);
if (isOpen_) {
HDF_LOGW("device already open.%{public}s", portName_.c_str());
return HDF_ERR_DEVICE_BUSY;
}
HdfTrace openTrace("Serial::Open");
fd_ = open(portName_.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if (fd_ < 0) {
if (errno == ENODEV) {
HDF_LOGW("device not exist.%{public}s", portName_.c_str());
return HDF_DEV_ERR_NO_DEVICE;
} else {
HDF_LOGE("open failed.%{public}s - errno=%{public}d (%{public}s)\n",
portName_.c_str(), errno, strerror(errno));
}
return HDF_ERR_IO;
}
fdsan_exchange_owner_tag(fd_, 0, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
if (flock(fd_, LOCK_EX | LOCK_NB) < 0) {
HDF_LOGE("lock failed.%{public}s-err=%{public}d (%{public}s)\n", portName_.c_str(), errno, strerror(errno));
fdsan_close_with_tag(fd_, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
fd_ = INVALID_FD;
return HDF_ERR_IO;
}
int32_t ret = HDF_SUCCESS;
if ((ret = ConfigurePort()) != HDF_SUCCESS) {
fdsan_close_with_tag(fd_, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
fd_ = INVALID_FD;
return ret;
}
if (InitPipes() != HDF_SUCCESS) {
fdsan_close_with_tag(fd_, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
fd_ = INVALID_FD;
return HDF_ERR_IO;
}
isOpen_ = true;
HDF_LOGI("Open %{public}s success! fd:%{public}d", portName_.c_str(), fd_);
return HDF_SUCCESS;
}
int32_t SerialDevice::StartRead()
{
HDF_LOGI("StartRead %{public}s! fd:%{public}d", portName_.c_str(), fd_);
std::shared_lock lock(mutex_);
if (!isOpen_.load()) {
HDF_LOGE("%{public}s, device not open!", __func__);
return HDF_ERR_INVALID_OBJECT;
}
if (startRead_.load()) {
return HDF_SUCCESS;
}
startRead_.store(true);
readThread_ = std::thread(&SerialDevice::ReadThread, this, READ_WAIT_TIME);
return HDF_SUCCESS;
}
int32_t SerialDevice::StopRead()
{
std::shared_lock lock(mutex_);
return StopReadLocked();
}
int32_t SerialDevice::StopReadLocked()
{
HDF_LOGI("StopReadLocked %{public}s! fd:%{public}d", portName_.c_str(), fd_);
if (startRead_.load() && stopPipe_[PIPE_WRITE_IDX] >= 0) {
char msg = 'S';
write(stopPipe_[PIPE_WRITE_IDX], &msg, BYTE_SIZE_ONE);
}
startRead_.store(false);
if (readThread_.joinable()) {
readThread_.join();
}
return HDF_SUCCESS;
}
int32_t SerialDevice::Close()
{
isOpen_.store(false);
if (closePipe_[PIPE_WRITE_IDX] >= 0) {
char ch = 'C';
write(closePipe_[PIPE_WRITE_IDX], &ch, sizeof(ch));
}
std::unique_lock lock(mutex_);
if (startRead_.load()) {
StopReadLocked();
}
if (fd_ >= 0) {
flock(fd_, LOCK_UN);
fdsan_close_with_tag(fd_, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
fd_ = INVALID_FD;
}
ClosePipes();
HDF_LOGI("Close %{public}s! fd:%{public}d", portName_.c_str(), fd_);
return HDF_SUCCESS;
}
int32_t SerialDevice::NotifyDeviceOffline()
{
std::shared_lock lock(mutex_);
if (cb_ == nullptr) {
HDF_LOGE("%{public}s, cb_ == nullptr", __func__);
return HDF_FAILURE;
}
HDF_LOGI("device %{public}s offline fd:%{public}d", portName_.c_str(), fd_);
return cb_->OnDeviceOffline();
}
int32_t SerialDevice::ConfigurePort()
{
HdfTrace openTrace("Serial::ConfigurePort");
struct termios options;
int32_t ret = tcgetattr(fd_, &options);
if (ret != 0) {
HDF_LOGE("%{public}s, tcgetattr failed! ret:%{public}d", __func__, ret);
return HDF_FAILURE;
}
cfmakeraw(&options);
options.c_cflag |= (CLOCAL | CREAD);
if ((ret = SetBaudRateInternal(options)) != 0) {
return ret;
}
if ((ret = SetParityInternal(options)) != 0) {
return ret;
}
if ((ret = SetDataBitsInternal(options)) != 0) {
return ret;
}
if ((ret = SetStopBitsInternal(options)) != 0) {
return ret;
}
if ((ret = SetRtsCtsInternal(options)) != 0) {
return ret;
}
if ((ret = SetXonXoffInternal(options)) != 0) {
return ret;
}
options.c_oflag &= ~OPOST;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_cc[VMIN] = VMIN_DEFAULT;
options.c_cc[VTIME] = 0;
if (tcsetattr(fd_, TCSANOW, &options) != 0) {
HDF_LOGE("%{public}s, tcsetattr failed!", __func__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::SetDataBitsInternal(struct termios& options)
{
options.c_cflag &= ~CSIZE;
switch (currentConfig_.dataBits) {
case DATA_BIT_5: options.c_cflag |= CS5; break;
case DATA_BIT_6: options.c_cflag |= CS6; break;
case DATA_BIT_7: options.c_cflag |= CS7; break;
case DATA_BIT_8: options.c_cflag |= CS8; break;
default:
HDF_LOGE("invalid databits:%{public}d\n", currentConfig_.dataBits);
return HDF_ERR_INVALID_PARAM;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::SetStopBitsInternal(struct termios& options)
{
switch (currentConfig_.stopBits) {
case STOP_BIT_ONE:
options.c_cflag &= ~CSTOPB;
break;
case STOP_BIT_TWO:
options.c_cflag |= CSTOPB;
break;
default:
HDF_LOGE("invalid stopBits:%{public}d\n", currentConfig_.stopBits);
return HDF_ERR_INVALID_PARAM;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::SetRtsCtsInternal(struct termios& options)
{
if (currentConfig_.rtscts) {
options.c_cflag |= CRTSCTS;
} else {
options.c_cflag &= ~CRTSCTS;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::SetXonXoffInternal(struct termios& options)
{
options.c_cflag |= (CLOCAL | CREAD);
options.c_iflag &= ~(IXON | IXOFF | IXANY);
if (currentConfig_.xon) {
options.c_iflag |= IXON;
}
if (currentConfig_.xoff) {
options.c_iflag |= IXOFF;
}
if (currentConfig_.xany) {
options.c_iflag |= IXANY;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::SetParityInternal(struct termios& options)
{
options.c_cflag &= ~(PARENB | PARODD | CMSPAR);
switch (currentConfig_.parity) {
case FLAG_PARITY_0:
options.c_cflag &= ~PARENB;
break;
case FLAG_PARITY_1:
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
break;
case FLAG_PARITY_2:
options.c_cflag |= (PARENB | PARODD);
break;
case FLAG_PARITY_3:
options.c_cflag |= (PARENB | PARODD | CMSPAR);
break;
case FLAG_PARITY_4:
options.c_cflag |= (PARENB | CMSPAR);
options.c_cflag &= ~PARODD;
break;
default:
HDF_LOGE("invalid parity:%{public}d\n", currentConfig_.parity);
return HDF_ERR_INVALID_PARAM;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::SetBaudRateInternal(struct termios& options)
{
if (currentConfig_.baudRate <= 0) {
HDF_LOGE("baudRate:%{public}d invalid!", currentConfig_.baudRate);
return HDF_ERR_INVALID_PARAM;
}
static const struct { int32_t baud; speed_t speed; } baudTable[] = {
{BR50, B50}, {BR75, B75}, {BR110, B110}, {BR134, B134},
{BR150, B150}, {BR200, B200}, {BR300, B300}, {BR600, B600},
{BR1200, B1200}, {BR1800, B1800}, {BR2400, B2400}, {BR4800, B4800},
{BR9600, B9600}, {BR19200, B19200}, {BR38400, B38400}, {BR57600, B57600},
{BR115200, B115200}, {BR230400, B230400}, {BR460800, B460800},
{BR500000, B500000}, {BR576000, B576000}, {BR921600, B921600},
{BR1000000, B1000000}, {BR1152000, B1152000}, {BR1500000, B1500000},
{BR2000000, B2000000}, {BR2500000, B2500000}, {BR3000000, B3000000},
{BR3500000, B3500000}, {BR4000000, B4000000}
};
for (size_t i = 0; i < sizeof(baudTable) / sizeof(baudTable[0]); i++) {
if (currentConfig_.baudRate == baudTable[i].baud) {
if (cfsetispeed(&options, baudTable[i].speed) < 0) {
HDF_LOGE("cfsetispeed:%{public}d failed!", currentConfig_.baudRate);
return HDF_ERR_INVALID_PARAM;
}
if (cfsetospeed(&options, baudTable[i].speed) < 0) {
HDF_LOGE("cfsetospeed:%{public}d failed!", currentConfig_.baudRate);
return HDF_ERR_INVALID_PARAM;
}
return HDF_SUCCESS;
}
}
HDF_LOGE("invalid baud:%{public}d!", currentConfig_.baudRate);
return HDF_ERR_INVALID_PARAM;
}
int32_t SerialDevice::Write(const std::vector<uint8_t>& data, int32_t timeout, int32_t& bytesWritten)
{
HDF_LOGD("%{public}s called, size=%{public}zu!", __func__, data.size());
bytesWritten = 0;
if (data.empty() || data.size() > MAX_BUFFER_LEN) {
HDF_LOGW("data is invalid!size:%{public}zu", data.size());
return HDF_ERR_INVALID_PARAM;
}
struct pollfd fds[PIPE_FD_LEN];
{
std::shared_lock lock(mutex_);
if (!isOpen_.load() || fd_ < 0) {
HDF_LOGE("%{public}s, device not open!", __func__);
return HDF_ERR_INVALID_OBJECT;
}
fds[ARRAY_INDEX_0].fd = fd_;
fds[ARRAY_INDEX_0].events = POLLOUT;
fds[ARRAY_INDEX_1].fd = closePipe_[PIPE_READ_IDX];
fds[ARRAY_INDEX_1].events = POLLIN;
}
int32_t ret = PollForWrite(fds, timeout);
if (ret != HDF_SUCCESS) {
return ret;
}
std::shared_lock lock(mutex_);
if (!isOpen_.load() || fd_ < 0) {
return HDF_ERR_INVALID_OBJECT;
}
if ((fds[ARRAY_INDEX_0].revents & POLLOUT) == 0) {
return HDF_ERR_IO;
}
ssize_t bytes = write(fd_, data.data(), data.size());
if (bytes < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
return HDF_SUCCESS;
}
HDF_LOGE("write failed, errno:%{public}d", errno);
return HDF_FAILURE;
}
bytesWritten = static_cast<int32_t>(bytes);
return HDF_SUCCESS;
}
int32_t SerialDevice::PollForWrite(struct pollfd* fds, int32_t timeout)
{
int32_t ret = poll(fds, PIPE_FD_LEN, timeout);
if (ret < 0) {
if (errno == EINTR) {
return HDF_SUCCESS;
}
HDF_LOGE("poll error, errno:%{public}d", errno);
return HDF_ERR_IO;
}
if (ret == 0) {
return HDF_ERR_TIMEOUT;
}
if ((fds[ARRAY_INDEX_1].revents & POLLIN) != 0) {
char buff;
read(closePipe_[PIPE_READ_IDX], &buff, BYTE_SIZE_ONE);
return HDF_ERR_DEVICE_BUSY;
}
if ((fds[ARRAY_INDEX_0].revents & POLLHUP) != 0) {
return HDF_DEV_ERR_NO_DEVICE;
}
if ((fds[ARRAY_INDEX_0].revents & (POLLERR | POLLNVAL)) != 0) {
return HDF_ERR_IO;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::Flush()
{
HDF_LOGI("%{public}s called!", __func__);
std::shared_lock lock(mutex_);
if (!isOpen_.load() || fd_ < 0) {
HDF_LOGE("%{public}s, device not open!", __func__);
return HDF_ERR_INVALID_OBJECT;
}
if (tcflush(fd_, TCIOFLUSH) != 0) {
HDF_LOGE("%{public}s, tcflush failed- errno=%{public}d (%{public}s)!",
__func__, errno, strerror(errno));
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::Drain()
{
HDF_LOGD("%{public}s called!", __func__);
std::shared_lock lock(mutex_);
if (!isOpen_.load() || fd_ < 0) {
HDF_LOGE("%{public}s, device not open!", __func__);
return HDF_ERR_INVALID_OBJECT;
}
if (tcdrain(fd_) != 0) {
HDF_LOGE("%{public}s, tcdrain failed- errno=%{public}d (%{public}s)!",
__func__, errno, strerror(errno));
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::SendBrkSignal()
{
HDF_LOGD("%{public}s called!", __func__);
std::shared_lock lock(mutex_);
if (!isOpen_.load() || fd_ < 0) {
HDF_LOGE("%{public}s, device not open!", __func__);
return HDF_ERR_INVALID_OBJECT;
}
HdfTrace openTrace("Serial::tcsendbreak");
if (tcsendbreak(fd_, 0) != 0) {
HDF_LOGE("%{public}s, tcsendbreak failed- errno=%{public}d (%{public}s)!",
__func__, errno, strerror(errno));
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::SetRtsSignal(bool rts)
{
HDF_LOGD("%{public}s called, rts=%{public}d!", __func__, rts);
std::shared_lock lock(mutex_);
HdfTrace openTrace("Serial::SetRtsSignal");
if (!isOpen_.load() || fd_ < 0) {
HDF_LOGE("%{public}s, device not open!", __func__);
return HDF_ERR_INVALID_OBJECT;
}
int flags;
if (ioctl(fd_, TIOCMGET, &flags) != 0) {
HDF_LOGE("%{public}s, TIOCMGET failed- errno=%{public}d (%{public}s)!",
__func__, errno, strerror(errno));
return HDF_FAILURE;
}
if (rts) {
flags |= TIOCM_RTS;
} else {
flags &= ~TIOCM_RTS;
}
if (ioctl(fd_, TIOCMSET, &flags) != 0) {
HDF_LOGE("%{public}s, TIOCMSET failed- errno=%{public}d (%{public}s)!",
__func__, errno, strerror(errno));
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::GetCtsSignal(bool& cts)
{
HDF_LOGD("%{public}s called!", __func__);
std::shared_lock lock(mutex_);
HdfTrace openTrace("Serial::GetCtsSignal");
if (!isOpen_.load() || fd_ < 0) {
HDF_LOGE("%{public}s, device not open!", __func__);
return HDF_ERR_INVALID_OBJECT;
}
int flags;
if (ioctl(fd_, TIOCMGET, &flags) != 0) {
HDF_LOGE("%{public}s, TIOCMGET failed- errno=%{public}d (%{public}s)!",
__func__, errno, strerror(errno));
return HDF_FAILURE;
}
cts = (flags & TIOCM_CTS) != 0;
return HDF_SUCCESS;
}
int32_t SerialDevice::SetDtrSignal(bool dtr)
{
HDF_LOGD("%{public}s called, dtr=%{public}d!", __func__, dtr);
std::shared_lock lock(mutex_);
HdfTrace openTrace("Serial::SetDtrSignal");
if (!isOpen_.load() || fd_ < 0) {
HDF_LOGE("%{public}s, device not open!", __func__);
return HDF_ERR_INVALID_OBJECT;
}
int flags;
if (ioctl(fd_, TIOCMGET, &flags) != 0) {
HDF_LOGE("%{public}s, TIOCMGET failed-errno=%{public}d (%{public}s)\n", __func__, errno, strerror(errno));
return HDF_FAILURE;
}
if (dtr) {
flags |= TIOCM_DTR;
} else {
flags &= ~TIOCM_DTR;
}
if (ioctl(fd_, TIOCMSET, &flags) != 0) {
HDF_LOGE("%{public}s, TIOCMSET failed-errno=%{public}d (%{public}s)\n", __func__, errno, strerror(errno));
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t SerialDevice::GetDsrSignal(bool& dsr)
{
HDF_LOGD("%{public}s called!", __func__);
std::shared_lock lock(mutex_);
HdfTrace openTrace("Serial::GetDsrSignal");
if (!isOpen_.load() || fd_ < 0) {
HDF_LOGE("%{public}s, device not open!", __func__);
return HDF_ERR_INVALID_OBJECT;
}
int flags;
if (ioctl(fd_, TIOCMGET, &flags) != 0) {
HDF_LOGE("%{public}s, TIOCMGET failed-errno=%{public}d (%{public}s)\n", __func__, errno, strerror(errno));
return HDF_FAILURE;
}
dsr = (flags & TIOCM_DSR) != 0;
return HDF_SUCCESS;
}
void SerialDevice::ReadThread(int32_t timeout)
{
std::vector<int8_t> buffer(MAX_BUFFER_LEN);
int32_t bytesRead = 0;
struct pollfd fds[POLL_FDS_COUNT_READ];
fds[ARRAY_INDEX_0].fd = fd_;
fds[ARRAY_INDEX_0].events = POLLIN;
fds[ARRAY_INDEX_1].fd = stopPipe_[PIPE_READ_IDX];
fds[ARRAY_INDEX_1].events = POLLIN;
fds[ARRAY_INDEX_2].fd = closePipe_[PIPE_READ_IDX];
fds[ARRAY_INDEX_2].events = POLLIN;
while (startRead_.load()) {
if (!isOpen_.load() || fd_ < 0) {
HDF_LOGE("not able to read!");
break;
}
int32_t ret = PollForRead(fds, timeout);
if (ret == HDF_FAILURE || ret == HDF_SUCCESS) {
if (ret == HDF_SUCCESS && HandleReadEvent(fds, buffer, bytesRead)) {
continue;
}
break;
}
}
HDF_LOGI("finish read! bytesRead:%{public}d", bytesRead);
}
int32_t SerialDevice::PollForRead(struct pollfd* fds, int32_t timeout)
{
fds[ARRAY_INDEX_0].revents = 0;
fds[ARRAY_INDEX_1].revents = 0;
fds[ARRAY_INDEX_2].revents = 0;
int32_t ret = poll(fds, POLL_FDS_COUNT_READ, timeout);
if (ret < 0) {
if (errno == EINTR) {
return HDF_SUCCESS;
}
HDF_LOGE("poll error, errno:%{public}d", errno);
return HDF_FAILURE;
}
if (ret == 0) {
return HDF_ERR_TIMEOUT;
}
if ((fds[ARRAY_INDEX_2].revents & POLLIN) != 0) {
char buff;
read(closePipe_[PIPE_READ_IDX], &buff, BYTE_SIZE_ONE);
HDF_LOGI("Read interrupted by close signal");
return HDF_FAILURE;
}
if ((fds[ARRAY_INDEX_1].revents & POLLIN) != 0) {
char buff;
read(stopPipe_[PIPE_READ_IDX], &buff, BYTE_SIZE_ONE);
HDF_LOGI("Read stopped by StopRead");
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
bool SerialDevice::HandleReadEvent(struct pollfd* fds, std::vector<int8_t>& buffer, int32_t& bytesRead)
{
if ((fds[ARRAY_INDEX_0].revents & POLLHUP) != 0) {
HDF_LOGE("device offline!");
return false;
}
if ((fds[ARRAY_INDEX_0].revents & (POLLERR | POLLNVAL)) != 0) {
HDF_LOGE("Port error or closed.");
return false;
}
if ((fds[ARRAY_INDEX_0].revents & POLLIN) == 0) {
return true;
}
if (memset_s(buffer.data(), buffer.size(), 0, buffer.size()) != EOK) {
HDF_LOGE("memset_s failed!");
return false;
}
ssize_t readBytes = read(fd_, buffer.data(), buffer.size());
if (readBytes < 0) {
HDF_LOGE("read failed, errno:%{public}d!", errno);
return true;
}
if (readBytes == 0) {
HDF_LOGW("device offline!");
return false;
}
bytesRead += static_cast<int32_t>(readBytes);
cb_->OnReadData(buffer, readBytes);
return true;
}
int32_t SerialDevice::InitPipes()
{
if (pipe(stopPipe_) != 0) {
HDF_LOGE("stopPipe create failed, errno=%{public}d", errno);
return HDF_FAILURE;
}
fdsan_exchange_owner_tag(stopPipe_[PIPE_READ_IDX], 0, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
fdsan_exchange_owner_tag(stopPipe_[PIPE_WRITE_IDX], 0, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
if (pipe(closePipe_) != 0) {
HDF_LOGE("closePipe create failed, errno=%{public}d", errno);
fdsan_close_with_tag(stopPipe_[PIPE_READ_IDX], fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
fdsan_close_with_tag(stopPipe_[PIPE_WRITE_IDX], fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
stopPipe_[PIPE_READ_IDX] = INVALID_FD;
stopPipe_[PIPE_WRITE_IDX] = INVALID_FD;
return HDF_FAILURE;
}
fdsan_exchange_owner_tag(closePipe_[PIPE_READ_IDX], 0, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
fdsan_exchange_owner_tag(closePipe_[PIPE_WRITE_IDX], 0, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
return HDF_SUCCESS;
}
void SerialDevice::ClosePipes()
{
if (stopPipe_[PIPE_READ_IDX] >= 0) {
fdsan_close_with_tag(stopPipe_[PIPE_READ_IDX], fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
stopPipe_[PIPE_READ_IDX] = INVALID_FD;
}
if (stopPipe_[PIPE_WRITE_IDX] >= 0) {
fdsan_close_with_tag(stopPipe_[PIPE_WRITE_IDX], fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
stopPipe_[PIPE_WRITE_IDX] = INVALID_FD;
}
if (closePipe_[PIPE_READ_IDX] >= 0) {
fdsan_close_with_tag(closePipe_[PIPE_READ_IDX], fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
closePipe_[PIPE_READ_IDX] = INVALID_FD;
}
if (closePipe_[PIPE_WRITE_IDX] >= 0) {
fdsan_close_with_tag(closePipe_[PIPE_WRITE_IDX], fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
closePipe_[PIPE_WRITE_IDX] = INVALID_FD;
}
}
}
}
}
}