blob: 9179942d7f15ceb5cab17477d950800f545b6ab4 [file] [log] [blame]
Thomas Gleixner84a14ae2019-05-28 09:57:07 -07001// SPDX-License-Identifier: GPL-2.0-only
Anton Vorontsov22b238b2007-07-31 00:38:44 -07002/*
3 * SPI testing utility (using spidev driver)
4 *
5 * Copyright (c) 2007 MontaVista Software, Inc.
6 * Copyright (c) 2007 Anton Vorontsov <[email protected]>
7 *
Anton Vorontsov22b238b2007-07-31 00:38:44 -07008 * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
9 */
10
11#include <stdint.h>
12#include <unistd.h>
13#include <stdio.h>
14#include <stdlib.h>
Adrian Remondab78ce7e2015-03-10 16:12:30 -040015#include <string.h>
Tiezhu Yang470a0722020-02-13 12:16:07 +080016#include <errno.h>
Anton Vorontsov22b238b2007-07-31 00:38:44 -070017#include <getopt.h>
18#include <fcntl.h>
Frode Isaksen9006a7b2017-03-21 16:48:46 +010019#include <time.h>
Anton Vorontsov22b238b2007-07-31 00:38:44 -070020#include <sys/ioctl.h>
Baruch Siach8736f802016-08-12 16:04:33 +030021#include <linux/ioctl.h>
Joshua Clayton7af475a2015-11-18 14:30:39 -080022#include <sys/stat.h>
Anton Vorontsov22b238b2007-07-31 00:38:44 -070023#include <linux/types.h>
24#include <linux/spi/spidev.h>
25
26#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
27
28static void pabort(const char *s)
29{
Tiezhu Yang470a0722020-02-13 12:16:07 +080030 if (errno != 0)
31 perror(s);
32 else
33 printf("%s\n", s);
34
Anton Vorontsov22b238b2007-07-31 00:38:44 -070035 abort();
36}
37
WANG Congcd583102007-10-16 01:27:47 -070038static const char *device = "/dev/spidev1.1";
Geert Uytterhoevenc2e78c32014-02-25 11:40:18 +010039static uint32_t mode;
Anton Vorontsov22b238b2007-07-31 00:38:44 -070040static uint8_t bits = 8;
Joshua Clayton7af475a2015-11-18 14:30:39 -080041static char *input_file;
Joshua Clayton983b278862015-11-18 14:30:40 -080042static char *output_file;
Anton Vorontsov22b238b2007-07-31 00:38:44 -070043static uint32_t speed = 500000;
44static uint16_t delay;
Adrian Remonda31a5c5a2015-03-10 16:12:31 -040045static int verbose;
Frode Isaksen9006a7b2017-03-21 16:48:46 +010046static int transfer_size;
47static int iterations;
48static int interval = 5; /* interval in seconds for showing transfer rate */
Anton Vorontsov22b238b2007-07-31 00:38:44 -070049
Qing Zhangbd207792020-06-11 20:56:51 +080050static uint8_t default_tx[] = {
Adrian Remonda30061912015-03-10 16:12:32 -040051 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
52 0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
53 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
54 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
55 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
56 0xF0, 0x0D,
57};
58
Qing Zhangbd207792020-06-11 20:56:51 +080059static uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, };
60static char *input_tx;
Adrian Remonda30061912015-03-10 16:12:32 -040061
Joshua Claytonb2cfc902015-11-18 14:30:42 -080062static void hex_dump(const void *src, size_t length, size_t line_size,
63 char *prefix)
Adrian Remondab78ce7e2015-03-10 16:12:30 -040064{
65 int i = 0;
66 const unsigned char *address = src;
67 const unsigned char *line = address;
68 unsigned char c;
69
70 printf("%s | ", prefix);
71 while (length-- > 0) {
72 printf("%02X ", *address++);
73 if (!(++i % line_size) || (length == 0 && i % line_size)) {
74 if (length == 0) {
75 while (i++ % line_size)
76 printf("__ ");
77 }
Geert Uytterhoeven35386df2018-09-03 19:33:23 +020078 printf(" |");
Adrian Remondab78ce7e2015-03-10 16:12:30 -040079 while (line < address) {
80 c = *line++;
Geert Uytterhoeven35386df2018-09-03 19:33:23 +020081 printf("%c", (c < 32 || c > 126) ? '.' : c);
Adrian Remondab78ce7e2015-03-10 16:12:30 -040082 }
Geert Uytterhoeven35386df2018-09-03 19:33:23 +020083 printf("|\n");
Adrian Remondab78ce7e2015-03-10 16:12:30 -040084 if (length > 0)
85 printf("%s | ", prefix);
86 }
87 }
88}
89
Adrian Remonda30061912015-03-10 16:12:32 -040090/*
91 * Unescape - process hexadecimal escape character
92 * converts shell input "\x23" -> 0x23
93 */
Andrew Morton07eec622015-04-16 12:49:29 -070094static int unescape(char *_dst, char *_src, size_t len)
Adrian Remonda30061912015-03-10 16:12:32 -040095{
96 int ret = 0;
Joshua Claytona20874f2015-11-18 14:30:41 -080097 int match;
Adrian Remonda30061912015-03-10 16:12:32 -040098 char *src = _src;
99 char *dst = _dst;
100 unsigned int ch;
101
102 while (*src) {
103 if (*src == '\\' && *(src+1) == 'x') {
Joshua Claytona20874f2015-11-18 14:30:41 -0800104 match = sscanf(src + 2, "%2x", &ch);
105 if (!match)
106 pabort("malformed input string");
107
Adrian Remonda30061912015-03-10 16:12:32 -0400108 src += 4;
109 *dst++ = (unsigned char)ch;
110 } else {
111 *dst++ = *src++;
112 }
113 ret++;
114 }
115 return ret;
116}
117
118static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700119{
120 int ret;
Joshua Clayton983b278862015-11-18 14:30:40 -0800121 int out_fd;
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700122 struct spi_ioc_transfer tr = {
123 .tx_buf = (unsigned long)tx,
124 .rx_buf = (unsigned long)rx,
Adrian Remonda30061912015-03-10 16:12:32 -0400125 .len = len,
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700126 .delay_usecs = delay,
127 .speed_hz = speed,
128 .bits_per_word = bits,
129 };
130
Geert Uytterhoeven896fa732020-04-16 12:18:35 +0200131 if (mode & SPI_TX_OCTAL)
132 tr.tx_nbits = 8;
133 else if (mode & SPI_TX_QUAD)
Geert Uytterhoevenc2e78c32014-02-25 11:40:18 +0100134 tr.tx_nbits = 4;
135 else if (mode & SPI_TX_DUAL)
136 tr.tx_nbits = 2;
Geert Uytterhoeven896fa732020-04-16 12:18:35 +0200137 if (mode & SPI_RX_OCTAL)
138 tr.rx_nbits = 8;
139 else if (mode & SPI_RX_QUAD)
Geert Uytterhoevenc2e78c32014-02-25 11:40:18 +0100140 tr.rx_nbits = 4;
141 else if (mode & SPI_RX_DUAL)
142 tr.rx_nbits = 2;
143 if (!(mode & SPI_LOOP)) {
Geert Uytterhoeven896fa732020-04-16 12:18:35 +0200144 if (mode & (SPI_TX_OCTAL | SPI_TX_QUAD | SPI_TX_DUAL))
Geert Uytterhoevenc2e78c32014-02-25 11:40:18 +0100145 tr.rx_buf = 0;
Geert Uytterhoeven896fa732020-04-16 12:18:35 +0200146 else if (mode & (SPI_RX_OCTAL | SPI_RX_QUAD | SPI_RX_DUAL))
Geert Uytterhoevenc2e78c32014-02-25 11:40:18 +0100147 tr.tx_buf = 0;
148 }
149
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700150 ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
Hector Palacios95b1ed22010-04-29 15:02:28 -0700151 if (ret < 1)
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700152 pabort("can't send spi message");
153
Adrian Remonda31a5c5a2015-03-10 16:12:31 -0400154 if (verbose)
Adrian Remonda30061912015-03-10 16:12:32 -0400155 hex_dump(tx, len, 32, "TX");
Joshua Clayton983b278862015-11-18 14:30:40 -0800156
157 if (output_file) {
158 out_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
159 if (out_fd < 0)
160 pabort("could not open output file");
161
162 ret = write(out_fd, rx, len);
163 if (ret != len)
Fabio Estevamedd38992015-12-04 10:59:14 -0200164 pabort("not all bytes written to output file");
Joshua Clayton983b278862015-11-18 14:30:40 -0800165
166 close(out_fd);
167 }
168
Frode Isaksen9006a7b2017-03-21 16:48:46 +0100169 if (verbose)
Joshua Clayton983b278862015-11-18 14:30:40 -0800170 hex_dump(rx, len, 32, "RX");
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700171}
172
Ladinu Chandrasingheb7ed6982009-09-22 16:43:42 -0700173static void print_usage(const char *prog)
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700174{
Boerge Struempfelb229a7f2023-05-30 16:16:41 +0200175 printf("Usage: %s [-2348CDFHILMNORSZbdilopsv]\n", prog);
Boerge Struempfel113f36f2023-05-30 16:16:40 +0200176 puts("general device settings:\n"
177 " -D --device device to use (default /dev/spidev1.1)\n"
178 " -s --speed max speed (Hz)\n"
179 " -d --delay delay (usec)\n"
180 " -l --loop loopback\n"
181 "spi mode:\n"
182 " -H --cpha clock phase\n"
183 " -O --cpol clock polarity\n"
Boerge Struempfelb229a7f2023-05-30 16:16:41 +0200184 " -F --rx-cpha-flip flip CPHA on Rx only xfer\n"
Boerge Struempfel113f36f2023-05-30 16:16:40 +0200185 "number of wires for transmission:\n"
186 " -2 --dual dual transfer\n"
187 " -4 --quad quad transfer\n"
188 " -8 --octal octal transfer\n"
189 " -3 --3wire SI/SO signals shared\n"
Boerge Struempfelb229a7f2023-05-30 16:16:41 +0200190 " -Z --3wire-hiz high impedance turnaround\n"
Boerge Struempfel113f36f2023-05-30 16:16:40 +0200191 "data:\n"
192 " -i --input input data from a file (e.g. \"test.bin\")\n"
193 " -o --output output data to a file (e.g. \"results.bin\")\n"
194 " -p Send data (e.g. \"1234\\xde\\xad\")\n"
195 " -S --size transfer size\n"
196 " -I --iter iterations\n"
197 "additional parameters:\n"
198 " -b --bpw bits per word\n"
199 " -L --lsb least significant bit first\n"
200 " -C --cs-high chip select active high\n"
201 " -N --no-cs no chip select\n"
202 " -R --ready slave pulls low to pause\n"
Boerge Struempfelb229a7f2023-05-30 16:16:41 +0200203 " -M --mosi-idle-low leave mosi line low when idle\n"
Boerge Struempfel113f36f2023-05-30 16:16:40 +0200204 "misc:\n"
205 " -v --verbose Verbose (show tx buffer)\n");
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700206 exit(1);
207}
208
Ladinu Chandrasingheb7ed6982009-09-22 16:43:42 -0700209static void parse_opts(int argc, char *argv[])
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700210{
211 while (1) {
WANG Congcd583102007-10-16 01:27:47 -0700212 static const struct option lopts[] = {
Boerge Struempfel113f36f2023-05-30 16:16:40 +0200213 { "device", 1, 0, 'D' },
214 { "speed", 1, 0, 's' },
215 { "delay", 1, 0, 'd' },
216 { "loop", 0, 0, 'l' },
217 { "cpha", 0, 0, 'H' },
218 { "cpol", 0, 0, 'O' },
Boerge Struempfelb229a7f2023-05-30 16:16:41 +0200219 { "rx-cpha-flip", 0, 0, 'F' },
Boerge Struempfel113f36f2023-05-30 16:16:40 +0200220 { "dual", 0, 0, '2' },
221 { "quad", 0, 0, '4' },
222 { "octal", 0, 0, '8' },
223 { "3wire", 0, 0, '3' },
Boerge Struempfelb229a7f2023-05-30 16:16:41 +0200224 { "3wire-hiz", 0, 0, 'Z' },
Boerge Struempfel113f36f2023-05-30 16:16:40 +0200225 { "input", 1, 0, 'i' },
226 { "output", 1, 0, 'o' },
227 { "size", 1, 0, 'S' },
228 { "iter", 1, 0, 'I' },
229 { "bpw", 1, 0, 'b' },
230 { "lsb", 0, 0, 'L' },
231 { "cs-high", 0, 0, 'C' },
232 { "no-cs", 0, 0, 'N' },
233 { "ready", 0, 0, 'R' },
Boerge Struempfelb229a7f2023-05-30 16:16:41 +0200234 { "mosi-idle-low", 0, 0, 'M' },
Boerge Struempfel113f36f2023-05-30 16:16:40 +0200235 { "verbose", 0, 0, 'v' },
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700236 { NULL, 0, 0, 0 },
237 };
238 int c;
239
Boerge Struempfelb229a7f2023-05-30 16:16:41 +0200240 c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3ZFMNR248p:vS:I:",
Joshua Clayton7af475a2015-11-18 14:30:39 -0800241 lopts, NULL);
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700242
243 if (c == -1)
244 break;
245
246 switch (c) {
247 case 'D':
248 device = optarg;
249 break;
250 case 's':
251 speed = atoi(optarg);
252 break;
253 case 'd':
254 delay = atoi(optarg);
255 break;
256 case 'b':
257 bits = atoi(optarg);
258 break;
Joshua Clayton7af475a2015-11-18 14:30:39 -0800259 case 'i':
260 input_file = optarg;
261 break;
Joshua Clayton983b278862015-11-18 14:30:40 -0800262 case 'o':
263 output_file = optarg;
264 break;
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700265 case 'l':
266 mode |= SPI_LOOP;
267 break;
268 case 'H':
269 mode |= SPI_CPHA;
270 break;
271 case 'O':
272 mode |= SPI_CPOL;
273 break;
274 case 'L':
275 mode |= SPI_LSB_FIRST;
276 break;
277 case 'C':
278 mode |= SPI_CS_HIGH;
279 break;
280 case '3':
281 mode |= SPI_3WIRE;
282 break;
Boerge Struempfelb229a7f2023-05-30 16:16:41 +0200283 case 'Z':
284 mode |= SPI_3WIRE_HIZ;
285 break;
286 case 'F':
287 mode |= SPI_RX_CPHA_FLIP;
288 break;
289 case 'M':
290 mode |= SPI_MOSI_IDLE_LOW;
291 break;
David Brownellb55f6272009-06-30 11:41:26 -0700292 case 'N':
293 mode |= SPI_NO_CS;
294 break;
Adrian Remonda31a5c5a2015-03-10 16:12:31 -0400295 case 'v':
296 verbose = 1;
297 break;
David Brownellb55f6272009-06-30 11:41:26 -0700298 case 'R':
299 mode |= SPI_READY;
300 break;
Adrian Remonda30061912015-03-10 16:12:32 -0400301 case 'p':
302 input_tx = optarg;
303 break;
Geert Uytterhoevenc2e78c32014-02-25 11:40:18 +0100304 case '2':
305 mode |= SPI_TX_DUAL;
306 break;
307 case '4':
308 mode |= SPI_TX_QUAD;
309 break;
Geert Uytterhoeven896fa732020-04-16 12:18:35 +0200310 case '8':
311 mode |= SPI_TX_OCTAL;
312 break;
Frode Isaksen9006a7b2017-03-21 16:48:46 +0100313 case 'S':
314 transfer_size = atoi(optarg);
315 break;
316 case 'I':
317 iterations = atoi(optarg);
318 break;
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700319 default:
320 print_usage(argv[0]);
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700321 }
322 }
Geert Uytterhoevenc2e78c32014-02-25 11:40:18 +0100323 if (mode & SPI_LOOP) {
324 if (mode & SPI_TX_DUAL)
325 mode |= SPI_RX_DUAL;
326 if (mode & SPI_TX_QUAD)
327 mode |= SPI_RX_QUAD;
Geert Uytterhoeven896fa732020-04-16 12:18:35 +0200328 if (mode & SPI_TX_OCTAL)
329 mode |= SPI_RX_OCTAL;
Geert Uytterhoevenc2e78c32014-02-25 11:40:18 +0100330 }
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700331}
332
Joshua Clayton5c437a42015-11-18 14:30:38 -0800333static void transfer_escaped_string(int fd, char *str)
334{
Geert Uytterhoeven0278b342016-09-09 09:02:51 +0200335 size_t size = strlen(str);
Joshua Clayton5c437a42015-11-18 14:30:38 -0800336 uint8_t *tx;
337 uint8_t *rx;
338
339 tx = malloc(size);
340 if (!tx)
341 pabort("can't allocate tx buffer");
342
343 rx = malloc(size);
344 if (!rx)
345 pabort("can't allocate rx buffer");
346
347 size = unescape((char *)tx, str, size);
348 transfer(fd, tx, rx, size);
349 free(rx);
350 free(tx);
351}
352
Joshua Clayton7af475a2015-11-18 14:30:39 -0800353static void transfer_file(int fd, char *filename)
354{
355 ssize_t bytes;
356 struct stat sb;
357 int tx_fd;
358 uint8_t *tx;
359 uint8_t *rx;
360
361 if (stat(filename, &sb) == -1)
362 pabort("can't stat input file");
363
364 tx_fd = open(filename, O_RDONLY);
Michal Vokáče634b762016-11-04 11:30:03 +0100365 if (tx_fd < 0)
Joshua Clayton7af475a2015-11-18 14:30:39 -0800366 pabort("can't open input file");
367
368 tx = malloc(sb.st_size);
369 if (!tx)
370 pabort("can't allocate tx buffer");
371
372 rx = malloc(sb.st_size);
373 if (!rx)
374 pabort("can't allocate rx buffer");
375
376 bytes = read(tx_fd, tx, sb.st_size);
377 if (bytes != sb.st_size)
378 pabort("failed to read input file");
379
380 transfer(fd, tx, rx, sb.st_size);
381 free(rx);
382 free(tx);
383 close(tx_fd);
384}
385
Frode Isaksen9006a7b2017-03-21 16:48:46 +0100386static uint64_t _read_count;
387static uint64_t _write_count;
388
389static void show_transfer_rate(void)
390{
391 static uint64_t prev_read_count, prev_write_count;
392 double rx_rate, tx_rate;
393
394 rx_rate = ((_read_count - prev_read_count) * 8) / (interval*1000.0);
395 tx_rate = ((_write_count - prev_write_count) * 8) / (interval*1000.0);
396
397 printf("rate: tx %.1fkbps, rx %.1fkbps\n", rx_rate, tx_rate);
398
399 prev_read_count = _read_count;
400 prev_write_count = _write_count;
401}
402
403static void transfer_buf(int fd, int len)
404{
405 uint8_t *tx;
406 uint8_t *rx;
407 int i;
408
409 tx = malloc(len);
410 if (!tx)
411 pabort("can't allocate tx buffer");
412 for (i = 0; i < len; i++)
413 tx[i] = random();
414
415 rx = malloc(len);
416 if (!rx)
417 pabort("can't allocate rx buffer");
418
419 transfer(fd, tx, rx, len);
420
421 _write_count += len;
422 _read_count += len;
423
424 if (mode & SPI_LOOP) {
425 if (memcmp(tx, rx, len)) {
426 fprintf(stderr, "transfer error !\n");
427 hex_dump(tx, len, 32, "TX");
428 hex_dump(rx, len, 32, "RX");
429 exit(1);
430 }
431 }
432
433 free(rx);
434 free(tx);
435}
436
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700437int main(int argc, char *argv[])
438{
439 int ret = 0;
440 int fd;
David Fries41ecad22022-06-13 00:39:41 -0500441 uint32_t request;
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700442
443 parse_opts(argc, argv);
444
Tiezhu Yang1f3c3632020-02-13 12:16:06 +0800445 if (input_tx && input_file)
446 pabort("only one of -p and --input may be selected");
447
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700448 fd = open(device, O_RDWR);
449 if (fd < 0)
450 pabort("can't open device");
451
452 /*
453 * spi mode
454 */
David Fries41ecad22022-06-13 00:39:41 -0500455 /* WR is make a request to assign 'mode' */
456 request = mode;
Geert Uytterhoevenc2e78c32014-02-25 11:40:18 +0100457 ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700458 if (ret == -1)
459 pabort("can't set spi mode");
460
David Fries41ecad22022-06-13 00:39:41 -0500461 /* RD is read what mode the device actually is in */
Geert Uytterhoevenc2e78c32014-02-25 11:40:18 +0100462 ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700463 if (ret == -1)
464 pabort("can't get spi mode");
David Fries41ecad22022-06-13 00:39:41 -0500465 /* Drivers can reject some mode bits without returning an error.
466 * Read the current value to identify what mode it is in, and if it
467 * differs from the requested mode, warn the user.
468 */
469 if (request != mode)
470 printf("WARNING device does not support requested mode 0x%x\n",
471 request);
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700472
473 /*
474 * bits per word
475 */
476 ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
477 if (ret == -1)
478 pabort("can't set bits per word");
479
480 ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
481 if (ret == -1)
482 pabort("can't get bits per word");
483
484 /*
485 * max speed hz
486 */
487 ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
488 if (ret == -1)
489 pabort("can't set max speed hz");
490
491 ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
492 if (ret == -1)
493 pabort("can't get max speed hz");
494
Geert Uytterhoevenc2e78c32014-02-25 11:40:18 +0100495 printf("spi mode: 0x%x\n", mode);
Geert Uytterhoeven9ec8ade2020-06-08 12:00:49 +0200496 printf("bits per word: %u\n", bits);
497 printf("max speed: %u Hz (%u kHz)\n", speed, speed/1000);
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700498
Joshua Clayton5c437a42015-11-18 14:30:38 -0800499 if (input_tx)
500 transfer_escaped_string(fd, input_tx);
Joshua Clayton7af475a2015-11-18 14:30:39 -0800501 else if (input_file)
502 transfer_file(fd, input_file);
Frode Isaksen9006a7b2017-03-21 16:48:46 +0100503 else if (transfer_size) {
504 struct timespec last_stat;
505
506 clock_gettime(CLOCK_MONOTONIC, &last_stat);
507
508 while (iterations-- > 0) {
509 struct timespec current;
510
511 transfer_buf(fd, transfer_size);
512
513 clock_gettime(CLOCK_MONOTONIC, &current);
514 if (current.tv_sec - last_stat.tv_sec > interval) {
515 show_transfer_rate();
516 last_stat = current;
517 }
518 }
519 printf("total: tx %.1fKB, rx %.1fKB\n",
520 _write_count/1024.0, _read_count/1024.0);
521 } else
Adrian Remonda30061912015-03-10 16:12:32 -0400522 transfer(fd, default_tx, default_rx, sizeof(default_tx));
Anton Vorontsov22b238b2007-07-31 00:38:44 -0700523
524 close(fd);
525
526 return ret;
527}