spi: add advanced open function with 32-bit extra flags

This commit is contained in:
Vanya A. Sergeev
2020-12-16 01:11:04 -06:00
parent 28ab557d6f
commit 56755acc78
3 changed files with 49 additions and 0 deletions
+14
View File
@@ -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);
@@ -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);
```
+32
View File
@@ -68,6 +68,11 @@ 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 */
@@ -75,6 +80,10 @@ int spi_open_advanced(spi_t *spi, const char *path, unsigned int mode, uint32_t
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));
@@ -83,6 +92,7 @@ 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;
@@ -90,6 +100,28 @@ int spi_open_advanced(spi_t *spi, const char *path, unsigned int mode, uint32_t
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) {
+3
View File
@@ -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);