blob: eb1fba1f66e2fc37ec0482afefec55330d63567c [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/unsafe.h>
#include <lib/spi/spi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/status.h>
void usage(char* prog) {
fprintf(stderr, "usage:\n");
fprintf(stderr, " %s DEVICE r LENGTH\n", prog);
fprintf(stderr, " %s DEVICE w BYTES ...\n", prog);
fprintf(stderr, " %s DEVICE x BYTES ...\n", prog);
}
void convert_args(char** argv, size_t length, uint8_t* buffer) {
for (size_t i = 0; i < length; i++) {
buffer[i] = static_cast<uint8_t>(strtoul(argv[i], nullptr, 0));
}
}
void print_buffer(uint8_t* buffer, size_t length) {
char ascii[16];
char* a = ascii;
size_t i;
for (i = 0; i < length; i++) {
if (i % 16 == 0) {
printf("%04zx: ", i);
a = ascii;
}
printf("%02x ", buffer[i]);
if (isprint(buffer[i])) {
*a++ = buffer[i];
} else {
*a++ = '.';
}
if (i % 16 == 15) {
printf("|%.16s|\n", ascii);
} else if (i % 8 == 7) {
printf(" ");
}
}
int rem = i % 16;
if (rem != 0) {
int spaces = (16 - rem) * 3;
if (rem < 8) {
spaces++;
}
printf("%*s|%.*s|\n", spaces, "", rem, ascii);
}
}
int main(int argc, char** argv) {
if (argc < 4) {
usage(argv[0]);
return -1;
}
int fd = open(argv[1], O_RDWR);
if (fd < 0) {
fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
usage(argv[0]);
return -2;
}
fdio_t* io = fdio_unsafe_fd_to_io(fd);
if (io == nullptr) {
fprintf(stderr, "%s: fdio conversion failed\n", argv[1]);
close(fd);
return -3;
}
zx_status_t status;
switch (argv[2][0]) {
case 'r': {
size_t length = strtoull(argv[3], nullptr, 0);
uint8_t buffer[length];
status = spilib_receive(fdio_unsafe_borrow_channel(io), buffer, length);
print_buffer(buffer, length);
break;
}
case 'w': {
size_t length = argc - 3;
uint8_t buffer[length];
convert_args(&argv[3], length, buffer);
status = spilib_transmit(fdio_unsafe_borrow_channel(io), buffer, length);
break;
}
case 'x': {
size_t length = argc - 3;
uint8_t send[length];
uint8_t recv[length];
convert_args(&argv[3], length, send);
status = spilib_exchange(fdio_unsafe_borrow_channel(io), send, recv, length);
print_buffer(recv, length);
break;
}
default:
fprintf(stderr, "%c: unrecognized command\n", argv[2][0]);
usage(argv[0]);
status = -4;
}
fdio_unsafe_release(io);
close(fd);
return status;
}