18#include <linux/gpio.h>
30 switch (errno_input) {
66 switch (errno_input) {
88 switch (configuration) {
90 flags = GPIOHANDLE_REQUEST_OUTPUT;
97 flags = GPIOHANDLE_REQUEST_INPUT;
108 switch (configuration) {
110 flags = GPIOEVENT_REQUEST_RISING_EDGE;
113 flags = GPIOEVENT_REQUEST_FALLING_EDGE;
116 flags = GPIOEVENT_REQUEST_RISING_EDGE | GPIOEVENT_REQUEST_FALLING_EDGE;
125LinuxGpioDriver ::~LinuxGpioDriver() {
126 (void) ::close(this->m_fd);
135 const GpioConfiguration& configuration,
140 struct gpiohandle_request request;
141 (void) ::memset(&request, 0,
sizeof request);
142 request.lineoffsets[0] = gpio;
144 static_cast<FwSizeType>(
sizeof request.consumer_label));
145 request.default_values[0] = (default_state ==
Fw::Logic::HIGH) ? 1 : 0;
151 PlatformIntType return_value = ioctl(chip_descriptor, GPIO_GET_LINEHANDLE_IOCTL, &request);
153 if (return_value != 0) {
162 const GpioConfiguration& configuration,
166 struct gpioevent_request event;
167 (void) ::memset(&event, 0,
sizeof event);
168 event.lineoffset = gpio;
170 static_cast<FwSizeType>(
sizeof event.consumer_label));
175 PlatformIntType return_value = ioctl(chip_descriptor, GPIO_GET_LINEEVENT_IOCTL, &event);
177 if (return_value != 0) {
191 FW_ASSERT(configuration < MAX_GPIO_CONFIGURATION and configuration >= 0,
static_cast<FwAssertArgType>(configuration));
202 struct gpiochip_info chip_info;
203 (void) ::memset(&chip_info, 0,
sizeof chip_info);
204 PlatformIntType return_value = ioctl(chip_descriptor, GPIO_GET_CHIPINFO_IOCTL, &chip_info);
205 if (return_value != 0) {
211 if (gpio >= chip_info.lines) {
217 struct gpioline_info pin_info;
218 (void) ::memset(&pin_info, 0,
sizeof pin_info);
219 pin_info.line_offset = gpio;
220 return_value = ioctl(chip_descriptor, GPIO_GET_LINEINFO_IOCTL, &pin_info);
221 if (return_value == 0) {
222 const bool has_consumer = pin_info.consumer[0] !=
'\0';
223 pin_message.
format(
"%s%s%s", pin_info.name, has_consumer ?
" with current consumer " :
"",
224 has_consumer ? pin_info.consumer :
"");
229 switch (configuration) {
233 status = this->setupLineHandle(chip_descriptor, gpio, configuration, default_state, pin_fd);
236 case GPIO_INTERRUPT_RISING_EDGE:
237 case GPIO_INTERRUPT_FALLING_EDGE:
238 case GPIO_INTERRUPT_BOTH_RISING_AND_FALLING_EDGES:
239 status = this->setupLineEvent(chip_descriptor, gpio, configuration, pin_fd);
247 this->log_WARNING_HI_OpenPinError(
Fw::String(device), gpio, pin_message,
253 this->m_configuration = configuration;
260 if (this->m_configuration == GpioConfiguration::GPIO_INPUT) {
261 struct gpiohandle_data values;
262 (void) ::memset(&values, 0,
sizeof values);
263 PlatformIntType return_value = ioctl(this->m_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &values);
264 if (return_value != 0) {
276 if (this->m_configuration == GpioConfiguration::GPIO_OUTPUT) {
277 struct gpiohandle_data values;
278 (void) ::memset(&values, 0,
sizeof values);
280 PlatformIntType return_value = ioctl(this->m_fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &values);
281 if (return_value != 0) {
290void LinuxGpioDriver ::pollLoop() {
294 static_assert(GPIO_POLL_TIMEOUT < static_cast<unsigned int>(std::numeric_limits<int>::max()),
"Poll timeout would overflow");
295 static_assert(
sizeof(
struct gpioevent_data) < std::numeric_limits<FwSizeType>::max(), "
FwSizeType too small");
296 using unsigned_ssize_t = std::make_unsigned<ssize_t>::type;
297 static_assert(static_cast<unsigned_ssize_t>(std::numeric_limits<ssize_t>::max()) <= std::numeric_limits<FwSizeType>::max(), "FwSizeType too small");
299 pollfd file_descriptors[1];
301 while (this->getRunning()) {
303 (void) ::memset(file_descriptors, 0,
sizeof file_descriptors);
304 file_descriptors[0].fd = this->m_fd;
305 file_descriptors[0].events = POLLIN;
307 PlatformIntType status = ::poll(file_descriptors, 1,
static_cast<int>(GPIO_POLL_TIMEOUT));
310 struct gpioevent_data event_data;
311 FwSizeType read_bytes =
static_cast<FwSizeType>(::read(this->m_fd, &event_data,
sizeof event_data));
312 if (read_bytes ==
sizeof event_data) {
315 this->gpioInterrupt_out(0, timestamp);
319 this->log_WARNING_HI_InterruptReadError(
static_cast<U32
>(
sizeof event_data),
320 static_cast<U32
>(read_bytes));
324 else if (status < 0) {
325 this->log_WARNING_HI_PollingError(
static_cast<I32
>(errno));
PlatformIntType NATIVE_INT_TYPE
int PlatformIntType
DefaultTypes.hpp provides fallback defaults for the platform types.
PlatformAssertArgType FwAssertArgType
#define FW_OPTIONAL_NAME(name)
PlatformSizeType FwSizeType
C++-compatible configuration header for fprime configuration.
@ INVALID_MODE
Operation not permitted with current configuration.
@ NOT_OPENED
Pin was never opened.
@ UNKNOWN_ERROR
An unknown error occurred.
@ OP_OK
Operation succeeded.
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
@ INVALID_ARGUMENT
Invalid argument passed in.
@ INVALID_MODE
Mode for file access is invalid for current operation.
@ NO_PERMISSION
No permission to read/write file.
@ NOT_OPENED
file hasn't been opened yet
@ OTHER_ERROR
A catch-all for other errors. Have to look in implementation-specific code.
@ OP_OK
Operation was successful.
@ DOESNT_EXIST
File doesn't exist (for read)
@ OPEN_WRITE
Open file for writing.
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