diff options
Diffstat (limited to '')
-rw-r--r-- | tools/Makefile | 7 | ||||
-rw-r--r-- | tools/spi/.gitignore (renamed from Documentation/spi/.gitignore) | 0 | ||||
-rw-r--r-- | tools/spi/Makefile | 4 | ||||
-rw-r--r-- | tools/spi/spidev_fdx.c (renamed from Documentation/spi/spidev_fdx.c) | 0 | ||||
-rw-r--r-- | tools/spi/spidev_test.c (renamed from Documentation/spi/spidev_test.c) | 119 |
5 files changed, 108 insertions, 22 deletions
diff --git a/tools/Makefile b/tools/Makefile index 7dc820a8c1f1..58689d3b5625 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -17,6 +17,7 @@ help: @echo ' lguest - a minimal 32-bit x86 hypervisor' @echo ' perf - Linux performance measurement and analysis tool' @echo ' selftests - various kernel selftests' + @echo ' spi - spi tools' @echo ' turbostat - Intel CPU idle stats and freq reporting tool' @echo ' usb - USB testing tools' @echo ' virtio - vhost test module' @@ -52,7 +53,7 @@ acpi: FORCE cpupower: FORCE $(call descend,power/$@) -cgroup firewire hv guest usb virtio vm net iio: FORCE +cgroup firewire hv guest spi usb virtio vm net iio: FORCE $(call descend,$@) liblockdep: FORCE @@ -118,7 +119,7 @@ acpi_clean: cpupower_clean: $(call descend,power/cpupower,clean) -cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean iio_clean: +cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean: $(call descend,$(@:_clean=),clean) liblockdep_clean: @@ -143,7 +144,7 @@ freefall_clean: $(call descend,laptop/freefall,clean) clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \ - perf_clean selftests_clean turbostat_clean usb_clean virtio_clean \ + perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ freefall_clean diff --git a/Documentation/spi/.gitignore b/tools/spi/.gitignore index 4280576397e8..4280576397e8 100644 --- a/Documentation/spi/.gitignore +++ b/tools/spi/.gitignore diff --git a/tools/spi/Makefile b/tools/spi/Makefile new file mode 100644 index 000000000000..cd0db62e4d9d --- /dev/null +++ b/tools/spi/Makefile @@ -0,0 +1,4 @@ +all: spidev_test spidev_fdx + +clean: + $(RM) spidev_test spidev_fdx diff --git a/Documentation/spi/spidev_fdx.c b/tools/spi/spidev_fdx.c index 0ea3e51292fc..0ea3e51292fc 100644 --- a/Documentation/spi/spidev_fdx.c +++ b/tools/spi/spidev_fdx.c diff --git a/Documentation/spi/spidev_test.c b/tools/spi/spidev_test.c index 135b3f592b83..8a73d8185316 100644 --- a/Documentation/spi/spidev_test.c +++ b/tools/spi/spidev_test.c @@ -19,6 +19,7 @@ #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> +#include <sys/stat.h> #include <linux/types.h> #include <linux/spi/spidev.h> @@ -33,6 +34,8 @@ static void pabort(const char *s) static const char *device = "/dev/spidev1.1"; static uint32_t mode; static uint8_t bits = 8; +static char *input_file; +static char *output_file; static uint32_t speed = 500000; static uint16_t delay; static int verbose; @@ -49,7 +52,8 @@ uint8_t default_tx[] = { uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, }; char *input_tx; -static void hex_dump(const void *src, size_t length, size_t line_size, char *prefix) +static void hex_dump(const void *src, size_t length, size_t line_size, + char *prefix) { int i = 0; const unsigned char *address = src; @@ -83,13 +87,17 @@ static void hex_dump(const void *src, size_t length, size_t line_size, char *pre static int unescape(char *_dst, char *_src, size_t len) { int ret = 0; + int match; char *src = _src; char *dst = _dst; unsigned int ch; while (*src) { if (*src == '\\' && *(src+1) == 'x') { - sscanf(src + 2, "%2x", &ch); + match = sscanf(src + 2, "%2x", &ch); + if (!match) + pabort("malformed input string"); + src += 4; *dst++ = (unsigned char)ch; } else { @@ -103,7 +111,7 @@ static int unescape(char *_dst, char *_src, size_t len) static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len) { int ret; - + int out_fd; struct spi_ioc_transfer tr = { .tx_buf = (unsigned long)tx, .rx_buf = (unsigned long)rx, @@ -134,7 +142,21 @@ static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len) if (verbose) hex_dump(tx, len, 32, "TX"); - hex_dump(rx, len, 32, "RX"); + + if (output_file) { + out_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (out_fd < 0) + pabort("could not open output file"); + + ret = write(out_fd, rx, len); + if (ret != len) + pabort("not all bytes written to output file"); + + close(out_fd); + } + + if (verbose || !output_file) + hex_dump(rx, len, 32, "RX"); } static void print_usage(const char *prog) @@ -143,7 +165,9 @@ static void print_usage(const char *prog) puts(" -D --device device to use (default /dev/spidev1.1)\n" " -s --speed max speed (Hz)\n" " -d --delay delay (usec)\n" - " -b --bpw bits per word \n" + " -b --bpw bits per word\n" + " -i --input input data from a file (e.g. \"test.bin\")\n" + " -o --output output data to a file (e.g. \"results.bin\")\n" " -l --loop loopback\n" " -H --cpha clock phase\n" " -O --cpol clock polarity\n" @@ -167,6 +191,8 @@ static void parse_opts(int argc, char *argv[]) { "speed", 1, 0, 's' }, { "delay", 1, 0, 'd' }, { "bpw", 1, 0, 'b' }, + { "input", 1, 0, 'i' }, + { "output", 1, 0, 'o' }, { "loop", 0, 0, 'l' }, { "cpha", 0, 0, 'H' }, { "cpol", 0, 0, 'O' }, @@ -182,7 +208,8 @@ static void parse_opts(int argc, char *argv[]) }; int c; - c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24p:v", lopts, NULL); + c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3NR24p:v", + lopts, NULL); if (c == -1) break; @@ -200,6 +227,12 @@ static void parse_opts(int argc, char *argv[]) case 'b': bits = atoi(optarg); break; + case 'i': + input_file = optarg; + break; + case 'o': + output_file = optarg; + break; case 'l': mode |= SPI_LOOP; break; @@ -249,13 +282,63 @@ static void parse_opts(int argc, char *argv[]) } } +static void transfer_escaped_string(int fd, char *str) +{ + size_t size = strlen(str + 1); + uint8_t *tx; + uint8_t *rx; + + tx = malloc(size); + if (!tx) + pabort("can't allocate tx buffer"); + + rx = malloc(size); + if (!rx) + pabort("can't allocate rx buffer"); + + size = unescape((char *)tx, str, size); + transfer(fd, tx, rx, size); + free(rx); + free(tx); +} + +static void transfer_file(int fd, char *filename) +{ + ssize_t bytes; + struct stat sb; + int tx_fd; + uint8_t *tx; + uint8_t *rx; + + if (stat(filename, &sb) == -1) + pabort("can't stat input file"); + + tx_fd = open(filename, O_RDONLY); + if (fd < 0) + pabort("can't open input file"); + + tx = malloc(sb.st_size); + if (!tx) + pabort("can't allocate tx buffer"); + + rx = malloc(sb.st_size); + if (!rx) + pabort("can't allocate rx buffer"); + + bytes = read(tx_fd, tx, sb.st_size); + if (bytes != sb.st_size) + pabort("failed to read input file"); + + transfer(fd, tx, rx, sb.st_size); + free(rx); + free(tx); + close(tx_fd); +} + int main(int argc, char *argv[]) { int ret = 0; int fd; - uint8_t *tx; - uint8_t *rx; - int size; parse_opts(argc, argv); @@ -300,17 +383,15 @@ int main(int argc, char *argv[]) printf("bits per word: %d\n", bits); printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); - if (input_tx) { - size = strlen(input_tx+1); - tx = malloc(size); - rx = malloc(size); - size = unescape((char *)tx, input_tx, size); - transfer(fd, tx, rx, size); - free(rx); - free(tx); - } else { + if (input_tx && input_file) + pabort("only one of -p and --input may be selected"); + + if (input_tx) + transfer_escaped_string(fd, input_tx); + else if (input_file) + transfer_file(fd, input_file); + else transfer(fd, default_tx, default_rx, sizeof(default_tx)); - } close(fd); |