Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions examples/htool_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,28 @@ struct libhoth_device* htool_libhoth_spi_device(void) {
return NULL;
}

// Get retry parameters from global flags
const char* timeout_str;
if (htool_get_param_string(htool_global_flags(), "connect_timeout",
&timeout_str)) {
return NULL;
}

int64_t timeout_us = parse_time_string_us(timeout_str);

if (timeout_us < 0) {
fprintf(stderr, "Invalid format for --connect_timeout: %s\n", timeout_str);
return NULL;
}

struct libhoth_spi_device_init_options opts = {
.path = spidev_path_str,
.mailbox = mailbox_location,
.atomic = atomic,
.speed = spidev_speed_hz,
.device_busy_wait_timeout = spidev_device_busy_wait_timeout,
.device_busy_wait_check_interval = spidev_device_busy_wait_check_interval,
.timeout_us = timeout_us,
};
rv = libhoth_spi_open(&opts, &result);
if (rv) {
Expand Down
67 changes: 26 additions & 41 deletions transports/libhoth_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <time.h>
#include <unistd.h>

#include "libhoth_device.h"
#include "libhoth_spi.h"
#include "transports/libhoth_device.h"
#include "transports/libhoth_ec.h"
Expand Down Expand Up @@ -303,27 +304,6 @@ int libhoth_spi_open(const struct libhoth_spi_device_init_options* options,
goto err_out;
}

// Try to take an exclusive advisory lock without blocking. The current
// implementation of operations on spidev device splits transactions into
// multiple `ioctl` calls out of necessity. But this may lead to conditions
// where multiple processes (all using the same spidev device at the same
// time) can interfere with transactions on the spidev device. This lock is
// meant to prevent such situations assuming that all processes using this
// spidev device check for this advisory lock.
//
// This lock is intentionally not released explicitly in `libhoth_spi_close`.
// `man 2 flock` mentions that if the file descriptor is duplicated (for eg.
// using `fork`), unlocking **any** of the file descriptors would release the
// lock. Without explicitly releasing the lock, the lock will be
// automatically released when **all** the duplicated file descriptors are
// closed. API users may choose to override this behavior and manage this
// lock using `libhoth_spi_claim` and `libhoth_spi_release` APIs
if (flock(fd, LOCK_EX | LOCK_NB) != 0) {
// Maybe some other process has the lock?
status = LIBHOTH_ERR_INTERFACE_BUSY;
goto err_out;
}

dev = calloc(1, sizeof(struct libhoth_device));
if (dev == NULL) {
status = LIBHOTH_ERR_MALLOC_FAILED;
Expand All @@ -336,6 +316,31 @@ int libhoth_spi_open(const struct libhoth_spi_device_init_options* options,
goto err_out;
}

spi_dev->fd = fd;
spi_dev->mailbox_address = options->mailbox;
spi_dev->address_mode_4b = true;
spi_dev->device_busy_wait_timeout = options->device_busy_wait_timeout;
spi_dev->device_busy_wait_check_interval =
options->device_busy_wait_check_interval;

if (options->atomic) {
dev->send = libhoth_spi_buffer_request;
dev->receive = libhoth_spi_send_and_receive_response;
} else {
dev->send = libhoth_spi_send_request;
dev->receive = libhoth_spi_receive_response;
}
dev->close = libhoth_spi_close;
dev->claim = libhoth_spi_claim;
dev->release = libhoth_spi_release;
dev->reconnect = libhoth_spi_reconnect;
dev->user_ctx = spi_dev;

status = libhoth_claim_device(dev, options->timeout_us);
if (status != LIBHOTH_OK) {
goto err_out;
}

if (options->bits) {
const uint8_t bits = (uint8_t)options->bits;
if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, bits) < 0) {
Expand All @@ -360,26 +365,6 @@ int libhoth_spi_open(const struct libhoth_spi_device_init_options* options,
}
}

spi_dev->fd = fd;
spi_dev->mailbox_address = options->mailbox;
spi_dev->address_mode_4b = true;
spi_dev->device_busy_wait_timeout = options->device_busy_wait_timeout;
spi_dev->device_busy_wait_check_interval =
options->device_busy_wait_check_interval;

if (options->atomic) {
dev->send = libhoth_spi_buffer_request;
dev->receive = libhoth_spi_send_and_receive_response;
} else {
dev->send = libhoth_spi_send_request;
dev->receive = libhoth_spi_receive_response;
}
dev->close = libhoth_spi_close;
dev->claim = libhoth_spi_claim;
dev->release = libhoth_spi_release;
dev->reconnect = libhoth_spi_reconnect;
dev->user_ctx = spi_dev;

*out = dev;
return LIBHOTH_OK;

Expand Down
1 change: 1 addition & 0 deletions transports/libhoth_spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct libhoth_spi_device_init_options {
int atomic;
uint32_t device_busy_wait_timeout;
uint32_t device_busy_wait_check_interval;
uint32_t timeout_us;
};

// Note that the options struct only needs to to live for the duration of
Expand Down
Loading