1 // Copyright 2024 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://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, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include <sys/ioctl.h> 17 #include <unistd.h> 18 19 #include <utility> 20 21 namespace pw::digital_io::internal { 22 23 // An "owned" file descriptor wrapper which closes the fd on destruction. 24 // TODO(b/328262654): Move this to out a better place. 25 class OwnedFd final { 26 public: OwnedFd(int fd)27 explicit OwnedFd(int fd) : fd_(fd) {} OwnedFd()28 explicit OwnedFd() : OwnedFd(kInvalid) {} 29 ~OwnedFd()30 ~OwnedFd() { Close(); } 31 32 // Delete copy constructor/assignment to prevent double close. 33 OwnedFd(const OwnedFd&) = delete; 34 OwnedFd& operator=(const OwnedFd&) = delete; 35 36 // Providing move constructor is required due to custom dtor. OwnedFd(OwnedFd && other)37 OwnedFd(OwnedFd&& other) noexcept : fd_(std::exchange(other.fd_, kInvalid)) {} 38 39 OwnedFd& operator=(OwnedFd&& other) noexcept { 40 Close(); 41 fd_ = std::exchange(other.fd_, kInvalid); 42 return *this; 43 } 44 Close()45 void Close() { 46 if (fd_ != kInvalid) { 47 close(fd_); 48 } 49 fd_ = kInvalid; 50 } 51 fd()52 int fd() const { return fd_; } valid()53 bool valid() const { return fd_ != kInvalid; } 54 55 // Helper functions 56 template <typename... Args> ioctl(Args &&...args)57 int ioctl(Args&&... args) { 58 return ::ioctl(fd_, std::forward<Args>(args)...); 59 } 60 read(void * buf,size_t nbytes)61 ssize_t read(void* buf, size_t nbytes) { return ::read(fd_, buf, nbytes); } 62 write(const void * buf,size_t nbytes)63 ssize_t write(const void* buf, size_t nbytes) { 64 return ::write(fd_, buf, nbytes); 65 } 66 67 private: 68 static constexpr int kInvalid = -1; 69 int fd_ = kInvalid; 70 }; 71 72 } // namespace pw::digital_io::internal 73