aboutsummaryrefslogtreecommitdiffstats
path: root/src/linux/spidev.c
blob: d68f9861d5985657007fbfd54e448267b8a38fc6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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");