aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2017-08-13 21:06:14 -0400
committerKevin O'Connor <kevin@koconnor.net>2017-09-20 12:55:28 -0400
commit4d60567bc66417c48e7c3095ceded6c24ec1888f (patch)
tree56f8afc8c1e6181314855ac517894e5ab5190129
parent73a1c9d249170a2edc842af7f852e60c427f0f6d (diff)
downloadkutter-4d60567bc66417c48e7c3095ceded6c24ec1888f.tar.gz
kutter-4d60567bc66417c48e7c3095ceded6c24ec1888f.tar.xz
kutter-4d60567bc66417c48e7c3095ceded6c24ec1888f.zip
linux: Add support for spidev devices
Add support for sending SPI messages to devices via the standard Linux SPI interface. This can be used to configure the shift registers on Replicape boards. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--src/linux/Makefile2
-rw-r--r--src/linux/spidev.c68
2 files changed, 69 insertions, 1 deletions
diff --git a/src/linux/Makefile b/src/linux/Makefile
index 7fe17395..6d432d15 100644
--- a/src/linux/Makefile
+++ b/src/linux/Makefile
@@ -3,7 +3,7 @@
dirs-y += src/linux src/generic
src-y += linux/main.c linux/timer.c linux/console.c linux/watchdog.c
-src-y += linux/pca9685.c
+src-y += linux/pca9685.c linux/spidev.c
src-y += generic/crc16_ccitt.c generic/alloc.c
CFLAGS_klipper.elf += -lutil
diff --git a/src/linux/spidev.c b/src/linux/spidev.c
new file mode 100644
index 00000000..d68f9861
--- /dev/null
+++ b/src/linux/spidev.c
@@ -0,0 +1,68 @@
+// Communicating with an SPI device via linux spidev
+//
+// Copyright (C) 2017 Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include <fcntl.h> // open
+#include <stdio.h> // snprintf
+#include <unistd.h> // write
+#include "command.h" // DECL_COMMAND
+#include "internal.h" // report_errno
+#include "sched.h" // shutdown
+
+struct spi_s {
+ uint32_t bus, dev;
+ int fd;
+};
+static struct spi_s devices[16];
+static int devices_count;
+
+static int
+spi_open(uint32_t bus, uint32_t dev)
+{
+ // Find existing device (if already opened)
+ int i;
+ for (i=0; i<devices_count; i++)
+ if (devices[i].bus == bus && devices[i].dev == dev)
+ return devices[i].fd;
+
+ // Setup new SPI device
+ if (devices_count >= ARRAY_SIZE(devices))
+ shutdown("Too many spi devices");
+ char fname[256];
+ snprintf(fname, sizeof(fname), "/dev/spidev%d.%d", bus, dev);
+ int fd = open(fname, O_RDWR|O_CLOEXEC);
+ if (fd < 0) {
+ report_errno("open spi", fd);
+ shutdown("Unable to open spi device");
+ }
+ int ret = set_non_blocking(fd);
+ if (ret < 0)
+ shutdown("Unable to set non-blocking on spi device");
+
+ devices[devices_count].bus = bus;
+ devices[devices_count].dev = dev;
+ devices[devices_count].fd = fd;
+ return fd;
+}
+
+static void
+spi_write(int fd, char *data, int len)
+{
+ int ret = write(fd, data, len);
+ if (ret < 0) {
+ report_errno("write spi", ret);
+ shutdown("Unable to write to spi");
+ }
+}
+
+void
+command_send_spi(uint32_t *args)
+{
+ int fd = spi_open(args[0], args[1]);
+ uint8_t len = args[2];
+ char *msg = (void*)(size_t)args[3];
+ spi_write(fd, msg, len);
+}
+DECL_COMMAND(command_send_spi, "send_spi bus=%u dev=%u msg=%*s");