Skip to content

Commit

Permalink
spi: add advanced open function with 32-bit extra flags
Browse files Browse the repository at this point in the history
  • Loading branch information
vsergeev committed Dec 16, 2020
1 parent 28ab557 commit 56755ac
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
14 changes: 14 additions & 0 deletions docs/spi.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ spi_t *spi_new(void);
int spi_open(spi_t *spi, const char *path, unsigned int mode, uint32_t max_speed);
int spi_open_advanced(spi_t *spi, const char *path, unsigned int mode, uint32_t max_speed,
spi_bit_order_t bit_order, uint8_t bits_per_word, uint8_t extra_flags);
int spi_open_advanced2(spi_t *spi, const char *path, unsigned int mode, uint32_t max_speed,
spi_bit_order_t bit_order, uint8_t bits_per_word, uint32_t extra_flags);
int spi_transfer(spi_t *spi, const uint8_t *txbuf, uint8_t *rxbuf, size_t len);
int spi_close(spi_t *spi);
void spi_free(spi_t *spi);
Expand Down Expand Up @@ -81,6 +83,18 @@ Returns 0 on success, or a negative [SPI error code](#return-value) on failure.

------

``` c
int spi_open_advanced2(spi_t *spi, const char *path, unsigned int mode, uint32_t max_speed,
spi_bit_order_t bit_order, uint8_t bits_per_word, uint32_t extra_flags);
```
Open the `spidev` device at the specified path, with the specified SPI mode, max speed in hertz, bit order, bits per word, and extra flags. This open function is the same as `spi_open_advanced()`, except that `extra_flags` can be 32-bits.
`spi` should be a valid pointer to an allocated SPI handle structure. SPI mode can be 0, 1, 2, or 3. Bit order can be `MSB_FIRST` or `LSB_FIRST`, as defined [above](#enumerations). Bits per word specifies the transfer word size. Extra flags specified additional flags bitwise-ORed with the SPI mode.
Returns 0 on success, or a negative [SPI error code](#return-value) on failure.
------
``` c
int spi_transfer(spi_t *spi, const uint8_t *txbuf, uint8_t *rxbuf, size_t len);
```
Expand Down
32 changes: 32 additions & 0 deletions src/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,22 @@ int spi_open(spi_t *spi, const char *path, unsigned int mode, uint32_t max_speed
}

int spi_open_advanced(spi_t *spi, const char *path, unsigned int mode, uint32_t max_speed, spi_bit_order_t bit_order, uint8_t bits_per_word, uint8_t extra_flags) {
return spi_open_advanced2(spi, path, mode, max_speed, bit_order, bits_per_word, extra_flags);
}

int spi_open_advanced2(spi_t *spi, const char *path, unsigned int mode, uint32_t max_speed, spi_bit_order_t bit_order, uint8_t bits_per_word, uint32_t extra_flags) {
uint32_t data32;
uint8_t data8;

/* Validate arguments */
if (mode & ~0x3)
return _spi_error(spi, SPI_ERROR_ARG, 0, "Invalid mode (can be 0,1,2,3)");
if (bit_order != MSB_FIRST && bit_order != LSB_FIRST)
return _spi_error(spi, SPI_ERROR_ARG, 0, "Invalid bit order (can be MSB_FIRST,LSB_FIRST)");
#ifndef SPI_IOC_WR_MODE32
if (extra_flags > 0xff)
return _spi_error(spi, SPI_ERROR_UNSUPPORTED, "Kernel version does not support 32-bit SPI mode flags");
#endif

memset(spi, 0, sizeof(spi_t));

Expand All @@ -83,13 +92,36 @@ int spi_open_advanced(spi_t *spi, const char *path, unsigned int mode, uint32_t
return _spi_error(spi, SPI_ERROR_OPEN, errno, "Opening SPI device \"%s\"", path);

/* Set mode, bit order, extra flags */
#ifndef SPI_IOC_WR_MODE32
data8 = mode | ((bit_order == LSB_FIRST) ? SPI_LSB_FIRST : 0) | extra_flags;
if (ioctl(spi->fd, SPI_IOC_WR_MODE, &data8) < 0) {
int errsv = errno;
close(spi->fd);
spi->fd = -1;
return _spi_error(spi, SPI_ERROR_CONFIGURE, errsv, "Setting SPI mode");
}
#else
if (extra_flags > 0xff) {
/* Use 32-bit mode if extra_flags is wider than 8-bits */
data32 = mode | ((bit_order == LSB_FIRST) ? SPI_LSB_FIRST : 0) | extra_flags;
if (ioctl(spi->fd, SPI_IOC_WR_MODE32, &data32) < 0) {
int errsv = errno;
close(spi->fd);
spi->fd = -1;
return _spi_error(spi, SPI_ERROR_CONFIGURE, errsv, "Setting SPI mode");
}
} else {
/* Prefer 8-bit mode, in case this library is inadvertently used on an
* older kernel. */
data8 = mode | ((bit_order == LSB_FIRST) ? SPI_LSB_FIRST : 0) | extra_flags;
if (ioctl(spi->fd, SPI_IOC_WR_MODE, &data8) < 0) {
int errsv = errno;
close(spi->fd);
spi->fd = -1;
return _spi_error(spi, SPI_ERROR_CONFIGURE, errsv, "Setting SPI mode");
}
}
#endif

/* Set max speed */
if (ioctl(spi->fd, SPI_IOC_WR_MAX_SPEED_HZ, &max_speed) < 0) {
Expand Down
3 changes: 3 additions & 0 deletions src/spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ int spi_open(spi_t *spi, const char *path, unsigned int mode,
int spi_open_advanced(spi_t *spi, const char *path, unsigned int mode,
uint32_t max_speed, spi_bit_order_t bit_order,
uint8_t bits_per_word, uint8_t extra_flags);
int spi_open_advanced2(spi_t *spi, const char *path, unsigned int mode,
uint32_t max_speed, spi_bit_order_t bit_order,
uint8_t bits_per_word, uint32_t extra_flags);
int spi_transfer(spi_t *spi, const uint8_t *txbuf, uint8_t *rxbuf, size_t len);
int spi_close(spi_t *spi);
void spi_free(spi_t *spi);
Expand Down

0 comments on commit 56755ac

Please sign in to comment.