160 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <stdio.h>3#include <unistd.h>4#include <stdlib.h>5#include <fcntl.h>6#include <string.h>7 8#include <sys/ioctl.h>9#include <sys/types.h>10#include <sys/stat.h>11 12#include <linux/types.h>13#include <linux/spi/spidev.h>14 15 16static int verbose;17 18static void do_read(int fd, int len)19{20 unsigned char buf[32], *bp;21 int status;22 23 /* read at least 2 bytes, no more than 32 */24 if (len < 2)25 len = 2;26 else if (len > sizeof(buf))27 len = sizeof(buf);28 memset(buf, 0, sizeof buf);29 30 status = read(fd, buf, len);31 if (status < 0) {32 perror("read");33 return;34 }35 if (status != len) {36 fprintf(stderr, "short read\n");37 return;38 }39 40 printf("read(%2d, %2d): %02x %02x,", len, status,41 buf[0], buf[1]);42 status -= 2;43 bp = buf + 2;44 while (status-- > 0)45 printf(" %02x", *bp++);46 printf("\n");47}48 49static void do_msg(int fd, int len)50{51 struct spi_ioc_transfer xfer[2];52 unsigned char buf[32], *bp;53 int status;54 55 memset(xfer, 0, sizeof xfer);56 memset(buf, 0, sizeof buf);57 58 if (len > sizeof buf)59 len = sizeof buf;60 61 buf[0] = 0xaa;62 xfer[0].tx_buf = (unsigned long)buf;63 xfer[0].len = 1;64 65 xfer[1].rx_buf = (unsigned long) buf;66 xfer[1].len = len;67 68 status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);69 if (status < 0) {70 perror("SPI_IOC_MESSAGE");71 return;72 }73 74 printf("response(%2d, %2d): ", len, status);75 for (bp = buf; len; len--)76 printf(" %02x", *bp++);77 printf("\n");78}79 80static void dumpstat(const char *name, int fd)81{82 __u8 lsb, bits;83 __u32 mode, speed;84 85 if (ioctl(fd, SPI_IOC_RD_MODE32, &mode) < 0) {86 perror("SPI rd_mode");87 return;88 }89 if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) {90 perror("SPI rd_lsb_fist");91 return;92 }93 if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) {94 perror("SPI bits_per_word");95 return;96 }97 if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) {98 perror("SPI max_speed_hz");99 return;100 }101 102 printf("%s: spi mode 0x%x, %d bits %sper word, %u Hz max\n",103 name, mode, bits, lsb ? "(lsb first) " : "", speed);104}105 106int main(int argc, char **argv)107{108 int c;109 int readcount = 0;110 int msglen = 0;111 int fd;112 const char *name;113 114 while ((c = getopt(argc, argv, "hm:r:v")) != EOF) {115 switch (c) {116 case 'm':117 msglen = atoi(optarg);118 if (msglen < 0)119 goto usage;120 continue;121 case 'r':122 readcount = atoi(optarg);123 if (readcount < 0)124 goto usage;125 continue;126 case 'v':127 verbose++;128 continue;129 case 'h':130 case '?':131usage:132 fprintf(stderr,133 "usage: %s [-h] [-m N] [-r N] /dev/spidevB.D\n",134 argv[0]);135 return 1;136 }137 }138 139 if ((optind + 1) != argc)140 goto usage;141 name = argv[optind];142 143 fd = open(name, O_RDWR);144 if (fd < 0) {145 perror("open");146 return 1;147 }148 149 dumpstat(name, fd);150 151 if (msglen)152 do_msg(fd, msglen);153 154 if (readcount)155 do_read(fd, readcount);156 157 close(fd);158 return 0;159}160