18 #include <linux/gpio.h>
20 #include <sys/ioctl.h>
29 switch (errno_input) {
34 status = Os::File::Status::NOT_OPENED;
37 status = Os::File::Status::INVALID_ARGUMENT;
40 status = Os::File::Status::DOESNT_EXIST;
46 status = Os::File::Status::NO_PERMISSION;
49 status = Os::File::Status::INVALID_MODE;
65 switch (errno_input) {
67 status = Drv::GpioStatus::T::NOT_OPENED;
79 status = Drv::GpioStatus::T::UNKNOWN_ERROR;
87 switch (configuration) {
89 flags = GPIOHANDLE_REQUEST_OUTPUT;
96 flags = GPIOHANDLE_REQUEST_INPUT;
107 switch (configuration) {
109 flags = GPIOEVENT_REQUEST_RISING_EDGE;
112 flags = GPIOEVENT_REQUEST_FALLING_EDGE;
115 flags = GPIOEVENT_REQUEST_RISING_EDGE | GPIOEVENT_REQUEST_FALLING_EDGE;
125 (void) ::close(this->m_fd);
134 const GpioConfiguration& configuration,
139 struct gpiohandle_request request;
140 (void) ::memset(&request, 0,
sizeof request);
141 request.lineoffsets[0] = gpio;
143 static_cast<FwSizeType>(
sizeof request.consumer_label));
144 request.default_values[0] = (default_state ==
Fw::Logic::HIGH) ? 1 : 0;
150 PlatformIntType return_value = ioctl(chip_descriptor, GPIO_GET_LINEHANDLE_IOCTL, &request);
152 if (return_value != 0) {
161 const GpioConfiguration& configuration,
165 struct gpioevent_request event;
166 (void) ::memset(&event, 0,
sizeof event);
167 event.lineoffset = gpio;
169 static_cast<FwSizeType>(
sizeof event.consumer_label));
174 PlatformIntType return_value = ioctl(chip_descriptor, GPIO_GET_LINEEVENT_IOCTL, &event);
176 if (return_value != 0) {
190 FW_ASSERT(configuration < MAX_GPIO_CONFIGURATION and configuration >= 0,
static_cast<FwAssertArgType>(configuration));
193 status = chip_file.
open(device, Os::File::Mode::OPEN_WRITE);
201 struct gpiochip_info chip_info;
202 (void) ::memset(&chip_info, 0,
sizeof chip_info);
203 PlatformIntType return_value = ioctl(chip_descriptor, GPIO_GET_CHIPINFO_IOCTL, &chip_info);
204 if (return_value != 0) {
210 if (gpio >= chip_info.lines) {
216 struct gpioline_info pin_info;
217 (void) ::memset(&pin_info, 0,
sizeof pin_info);
218 pin_info.line_offset = gpio;
219 return_value = ioctl(chip_descriptor, GPIO_GET_LINEINFO_IOCTL, &pin_info);
220 if (return_value == 0) {
221 const bool has_consumer = pin_info.consumer[0] !=
'\0';
222 pin_message.
format(
"%s%s%s", pin_info.name, has_consumer ?
" with current consumer " :
"",
223 has_consumer ? pin_info.consumer :
"");
228 switch (configuration) {
232 status = this->setupLineHandle(chip_descriptor, gpio, configuration, default_state, pin_fd);
238 status = this->setupLineEvent(chip_descriptor, gpio, configuration, pin_fd);
252 this->m_configuration = configuration;
259 if (this->m_configuration == GpioConfiguration::GPIO_INPUT) {
260 struct gpiohandle_data values;
261 (void) ::memset(&values, 0,
sizeof values);
262 PlatformIntType return_value = ioctl(this->m_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &values);
263 if (return_value != 0) {
275 if (this->m_configuration == GpioConfiguration::GPIO_OUTPUT) {
276 struct gpiohandle_data values;
277 (void) ::memset(&values, 0,
sizeof values);
279 PlatformIntType return_value = ioctl(this->m_fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &values);
280 if (return_value != 0) {
289 void LinuxGpioDriver ::pollLoop() {
290 static_assert(
GPIO_POLL_TIMEOUT < std::numeric_limits<int>::max(),
"Poll timeout would overflow");
291 static_assert(
sizeof(
struct gpioevent_data) < std::numeric_limits<FwSizeType>::max(),
"FwSizeType too small");
292 static_assert(std::numeric_limits<ssize_t>::max() <= std::numeric_limits<FwSizeType>::max(),
"FwSizeType too small");
294 pollfd file_descriptors[1];
296 while (this->getRunning()) {
298 (void) ::memset(file_descriptors, 0,
sizeof file_descriptors);
299 file_descriptors[0].fd = this->m_fd;
300 file_descriptors[0].events = POLLIN;
305 struct gpioevent_data event_data;
306 FwSizeType read_bytes =
static_cast<FwSizeType>(::read(this->m_fd, &event_data,
sizeof event_data));
307 if (read_bytes ==
sizeof event_data) {
315 static_cast<U32
>(read_bytes));
319 else if (status < 0) {
PlatformIntType NATIVE_INT_TYPE
int PlatformIntType
DefaultTypes.hpp provides fallback defaults for the platform types.
PlatformAssertArgType FwAssertArgType
PlatformSizeType FwSizeType
C++-compatible configuration header for fprime configuration.
@ INVALID_MODE
Operation not permitted with current configuration.
@ OP_OK
Operation succeeded.
void log_DIAGNOSTIC_OpenChip(const Fw::StringBase &chip, const Fw::StringBase &chipLabel, U32 pin, const Fw::StringBase &pinMessage)
Log event OpenChip.
void log_WARNING_HI_OpenPinError(const Fw::StringBase &chip, U32 pin, const Fw::StringBase &pinMessage, Os::FileStatus status)
Log event OpenPinError.
void log_WARNING_HI_OpenChipError(const Fw::StringBase &chip, Os::FileStatus status)
Log event OpenChipError.
void log_WARNING_HI_InterruptReadError(U32 expected, U32 got)
Log event InterruptReadError.
void log_WARNING_HI_PollingError(I32 error_number)
Log event PollingError.
void gpioInterrupt_out(FwIndexType portNum, Os::RawTime &cycleStart)
Invoke output port gpioInterrupt.
static constexpr FwSizeType GPIO_POLL_TIMEOUT
Os::File::Status open(const char *device, const U32 gpio, const GpioConfiguration &configuration, const Fw::Logic &default_state=Fw::Logic::LOW)
open a GPIO pin for use in the system
GpioConfiguration
configure the GPIO pin
@ GPIO_INPUT
Input GPIO pin for direct reading.
@ GPIO_INTERRUPT_FALLING_EDGE
Input GPIO pin triggers interrupt port on falling edge.
@ GPIO_INTERRUPT_BOTH_RISING_AND_FALLING_EDGES
Input GPIO pin triggers interrupt port on both edges.
@ GPIO_INTERRUPT_RISING_EDGE
Input GPIO pin triggers interrupt port on rising edge.
@ GPIO_OUTPUT
Output GPIO pin for direct writing.
void format(const CHAR *formatString,...)
write formatted string to buffer
FileHandle * getHandle() override
returns the raw file handle
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
@ OP_OK
Operation was successful.
FPP shadow-enum representing Os::File::Status.
Status now() override
Get the current time.
U32 configuration_to_event_flags(Drv::LinuxGpioDriver::GpioConfiguration configuration)
Drv::GpioStatus errno_to_gpio_status(PlatformIntType errno_input)
U32 configuration_to_handler_flags(Drv::LinuxGpioDriver::GpioConfiguration configuration)
Os::File::Status errno_to_file_status(PlatformIntType errno_input)
char * string_copy(char *destination, const char *source, FwSizeType num)
copy string with null-termination guaranteed
@ OP_OK
Operation succeeded.
@ OTHER_ERROR
A catch-all for other errors. Have to look in implementation-specific code.
@ NO_SPACE
No space left on the device for writing.