1 /*
2 * Copyright (c) 2017, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #define _GNU_SOURCE 1
29
30 #ifndef HAVE_CONFIG_H
31 #define HAVE_CONFIG_H 0
32 #endif
33
34 #if HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include <assert.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <getopt.h>
42 #include <signal.h>
43 #include <stdbool.h>
44 #include <stdint.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <syslog.h>
49 #include <unistd.h>
50
51 #include <sys/file.h>
52 #include <sys/ioctl.h>
53 #include <sys/select.h>
54 #include <sys/types.h>
55 #include <sys/ucontext.h>
56
57 #include <linux/ioctl.h>
58 #include <linux/spi/spidev.h>
59
60 #ifndef HAVE_EXECINFO_H
61 #define HAVE_EXECINFO_H 0
62 #endif
63
64 #if HAVE_EXECINFO_H
65 #include <execinfo.h>
66 #endif
67
68 #ifndef HAVE_PTY_H
69 #define HAVE_PTY_H 0
70 #endif
71
72 #if HAVE_PTY_H
73 #include <pty.h>
74 #endif
75
76 #ifndef HAVE_UTIL_H
77 #define HAVE_UTIL_H 0
78 #endif
79
80 #if HAVE_UTIL_H
81 #include <util.h>
82 #endif
83
84 #ifndef HAVE_OPENPTY
85 #define HAVE_OPENPTY 0
86 #endif
87
88 /* ------------------------------------------------------------------------- */
89 /* MARK: Macros and Constants */
90
91 #define SPI_HDLC_VERSION "0.07"
92
93 #define MAX_FRAME_SIZE 2048
94 #define HEADER_LEN 5
95 #define SPI_HEADER_RESET_FLAG 0x80
96 #define SPI_HEADER_CRC_FLAG 0x40
97 #define SPI_HEADER_PATTERN_VALUE 0x02
98 #define SPI_HEADER_PATTERN_MASK 0x03
99
100 #define EXIT_QUIT 65535
101
102 #ifndef MSEC_PER_SEC
103 #define MSEC_PER_SEC 1000
104 #endif
105
106 #ifndef USEC_PER_MSEC
107 #define USEC_PER_MSEC 1000
108 #endif
109
110 #ifndef USEC_PER_SEC
111 #define USEC_PER_SEC (USEC_PER_MSEC * MSEC_PER_SEC)
112 #endif
113
114 #define SPI_POLL_PERIOD_MSEC (MSEC_PER_SEC / 30)
115
116 #define IMMEDIATE_RETRY_COUNT 5
117 #define FAST_RETRY_COUNT 15
118
119 #define IMMEDIATE_RETRY_TIMEOUT_MSEC 1
120 #define FAST_RETRY_TIMEOUT_MSEC 10
121 #define SLOW_RETRY_TIMEOUT_MSEC 33
122
123 #define GPIO_INT_ASSERT_STATE 0 // I̅N̅T̅ is asserted low
124 #define GPIO_RES_ASSERT_STATE 0 // R̅E̅S̅ is asserted low
125
126 #define SPI_RX_ALIGN_ALLOWANCE_MAX 16
127
128 #define SOCKET_DEBUG_BYTES_PER_LINE 16
129
130 #ifndef AUTO_PRINT_BACKTRACE
131 #define AUTO_PRINT_BACKTRACE (HAVE_EXECINFO_H)
132 #endif
133
134 #define AUTO_PRINT_BACKTRACE_STACK_DEPTH 20
135
136 static const uint8_t kHdlcResetSignal[] = {0x7E, 0x13, 0x11, 0x7E};
137 static const uint16_t kHdlcCrcCheckValue = 0xf0b8;
138 static const uint16_t kHdlcCrcResetValue = 0xffff;
139
140 enum
141 {
142 MODE_STDIO = 0,
143 MODE_PTY = 1,
144 };
145
146 // Ignores return value from function 's'
147 #define IGNORE_RETURN_VALUE(s) \
148 do \
149 { \
150 if (s) \
151 { \
152 } \
153 } while (0)
154
155 /* ------------------------------------------------------------------------- */
156 /* MARK: Global State */
157
158 #if HAVE_OPENPTY
159 static int sMode = MODE_PTY;
160 #else
161 static int sMode = MODE_STDIO;
162 #endif
163
164 static int sLogLevel = LOG_WARNING;
165
166 static int sSpiDevFd = -1;
167 static int sResGpioValueFd = -1;
168 static int sIntGpioValueFd = -1;
169
170 static int sHdlcInputFd = -1;
171 static int sHdlcOutputFd = -1;
172
173 static int sSpiSpeed = 1000000; // in Hz (default: 1MHz)
174 static uint8_t sSpiMode = 0;
175 static int sSpiCsDelay = 20; // in microseconds
176 static int sSpiResetDelay = 0; // in milliseconds
177
178 static uint16_t sSpiRxPayloadSize;
179 static uint8_t sSpiRxFrameBuffer[MAX_FRAME_SIZE + SPI_RX_ALIGN_ALLOWANCE_MAX];
180
181 static uint16_t sSpiTxPayloadSize;
182 static bool sSpiTxIsReady = false;
183 static int sSpiTxRefusedCount = 0;
184 static uint8_t sSpiTxFrameBuffer[MAX_FRAME_SIZE + SPI_RX_ALIGN_ALLOWANCE_MAX];
185
186 static int sSpiRxAlignAllowance = 0;
187 static int sSpiSmallPacketSize = 32; // in bytes
188
189 static bool sSlaveDidReset = false;
190
191 static int sCaughtSignal = -1;
192
193 // If sUseRawFrames is set to true, HDLC encoding/encoding
194 // is skipped and the raw frames are read-from/written-to
195 // the sHdlcInputFd/sHdlcOutputFd whole. See `--raw`.
196 static bool sUseRawFrames = false;
197
198 static int sMTU = MAX_FRAME_SIZE - HEADER_LEN;
199
200 static int sRet = 0;
201
202 static bool sDumpStats = false;
203
204 static sig_t sPreviousHandlerForSIGINT;
205 static sig_t sPreviousHandlerForSIGTERM;
206
207 /* ------------------------------------------------------------------------- */
208 /* MARK: Statistics */
209
210 static uint64_t sSlaveResetCount = 0;
211 static uint64_t sSpiFrameCount = 0;
212 static uint64_t sSpiValidFrameCount = 0;
213 static uint64_t sSpiGarbageFrameCount = 0;
214 static uint64_t sSpiDuplexFrameCount = 0;
215 static uint64_t sSpiUnresponsiveFrameCount = 0;
216 static uint64_t sHdlcRxFrameByteCount = 0;
217 static uint64_t sHdlcTxFrameByteCount = 0;
218 static uint64_t sHdlcRxFrameCount = 0;
219 static uint64_t sHdlcTxFrameCount = 0;
220 static uint64_t sHdlcRxBadCrcCount = 0;
221
222 /* ------------------------------------------------------------------------- */
223 /* MARK: Signal Handlers */
224
signal_SIGINT(int sig)225 static void signal_SIGINT(int sig)
226 {
227 static const char message[] = "\nCaught SIGINT!\n";
228
229 sRet = EXIT_QUIT;
230
231 // Can't use syslog() because it isn't async signal safe.
232 // So we write to stderr
233 IGNORE_RETURN_VALUE(write(STDERR_FILENO, message, sizeof(message) - 1));
234 sCaughtSignal = sig;
235
236 // Restore the previous handler so that if we end up getting
237 // this signal again we perform the system default action.
238 signal(SIGINT, sPreviousHandlerForSIGINT);
239 sPreviousHandlerForSIGINT = NULL;
240
241 // Ignore signal argument.
242 (void)sig;
243 }
244
signal_SIGTERM(int sig)245 static void signal_SIGTERM(int sig)
246 {
247 static const char message[] = "\nCaught SIGTERM!\n";
248
249 sRet = EXIT_QUIT;
250
251 // Can't use syslog() because it isn't async signal safe.
252 // So we write to stderr
253 IGNORE_RETURN_VALUE(write(STDERR_FILENO, message, sizeof(message) - 1));
254 sCaughtSignal = sig;
255
256 // Restore the previous handler so that if we end up getting
257 // this signal again we perform the system default action.
258 signal(SIGTERM, sPreviousHandlerForSIGTERM);
259 sPreviousHandlerForSIGTERM = NULL;
260
261 // Ignore signal argument.
262 (void)sig;
263 }
264
signal_SIGHUP(int sig)265 static void signal_SIGHUP(int sig)
266 {
267 static const char message[] = "\nCaught SIGHUP!\n";
268
269 sRet = EXIT_FAILURE;
270
271 // Can't use syslog() because it isn't async signal safe.
272 // So we write to stderr
273 IGNORE_RETURN_VALUE(write(STDERR_FILENO, message, sizeof(message) - 1));
274 sCaughtSignal = sig;
275
276 // We don't restore the "previous handler"
277 // because we always want to let the main
278 // loop decide what to do for hangups.
279
280 // Ignore signal argument.
281 (void)sig;
282 }
283
signal_dumpstats(int sig)284 static void signal_dumpstats(int sig)
285 {
286 sDumpStats = true;
287
288 // Ignore signal argument.
289 (void)sig;
290 }
291
signal_clearstats(int sig)292 static void signal_clearstats(int sig)
293 {
294 sDumpStats = true;
295 sSlaveResetCount = 0;
296 sSpiFrameCount = 0;
297 sSpiValidFrameCount = 0;
298 sSpiGarbageFrameCount = 0;
299 sSpiDuplexFrameCount = 0;
300 sSpiUnresponsiveFrameCount = 0;
301 sHdlcRxFrameByteCount = 0;
302 sHdlcTxFrameByteCount = 0;
303 sHdlcRxFrameCount = 0;
304 sHdlcTxFrameCount = 0;
305 sHdlcRxBadCrcCount = 0;
306
307 // Ignore signal argument.
308 (void)sig;
309 }
310
311 #if AUTO_PRINT_BACKTRACE
signal_critical(int sig,siginfo_t * info,void * ucontext)312 static void signal_critical(int sig, siginfo_t *info, void *ucontext)
313 {
314 // This is the last hurah for this process.
315 // We dump the stack, because that's all we can do.
316
317 void * stack_mem[AUTO_PRINT_BACKTRACE_STACK_DEPTH];
318 void ** stack = stack_mem;
319 char ** stack_symbols;
320 int stack_depth, i;
321 ucontext_t *uc = (ucontext_t *)ucontext;
322
323 // Shut up compiler warning.
324 (void)uc;
325 (void)info;
326
327 // We call some functions here which aren't async-signal-safe,
328 // but this function isn't really useful without those calls.
329 // Since we are making a gamble (and we deadlock if we loose),
330 // we are going to set up a two-second watchdog to make sure
331 // we end up terminating like we should. The choice of a two
332 // second timeout is entirely arbitrary, and may be changed
333 // if needs warrant.
334 alarm(2);
335 signal(SIGALRM, SIG_DFL);
336
337 fprintf(stderr, " *** FATAL ERROR: Caught signal %d (%s):\n", sig, strsignal(sig));
338
339 stack_depth = backtrace(stack, AUTO_PRINT_BACKTRACE_STACK_DEPTH);
340
341 // Here are are trying to update the pointer in the backtrace
342 // to be the actual location of the fault.
343 #if defined(__x86_64__)
344 stack[1] = (void *)uc->uc_mcontext.gregs[REG_RIP];
345 #elif defined(__i386__)
346 stack[1] = (void *)uc->uc_mcontext.gregs[REG_EIP];
347 #elif defined(__arm__)
348 stack[1] = (void *)uc->uc_mcontext.arm_ip;
349 #else
350 #warning TODO: Add this arch to signal_critical
351 #endif
352
353 // Now dump the symbols to stderr, in case syslog barfs.
354 backtrace_symbols_fd(stack, stack_depth, STDERR_FILENO);
355
356 // Load up the symbols individually, so we can output to syslog, too.
357 stack_symbols = backtrace_symbols(stack, stack_depth);
358
359 syslog(LOG_CRIT, " *** FATAL ERROR: Caught signal %d (%s):", sig, strsignal(sig));
360
361 for (i = 0; i != stack_depth; i++)
362 {
363 syslog(LOG_CRIT, "[BT] %2d: %s", i, stack_symbols[i]);
364 }
365
366 free(stack_symbols);
367
368 exit(EXIT_FAILURE);
369 }
370 #endif // if AUTO_PRINT_BACKTRACE
371
log_debug_buffer(const char * desc,const uint8_t * buffer_ptr,int buffer_len,bool force)372 static void log_debug_buffer(const char *desc, const uint8_t *buffer_ptr, int buffer_len, bool force)
373 {
374 int i = 0;
375
376 if (!force && (sLogLevel < LOG_DEBUG))
377 {
378 return;
379 }
380
381 while (i < buffer_len)
382 {
383 int j;
384 char dump_string[SOCKET_DEBUG_BYTES_PER_LINE * 3 + 1];
385
386 for (j = 0; i < buffer_len && j < SOCKET_DEBUG_BYTES_PER_LINE; i++, j++)
387 {
388 sprintf(dump_string + j * 3, "%02X ", buffer_ptr[i]);
389 }
390
391 syslog(force ? LOG_WARNING : LOG_DEBUG, "%s: %s%s", desc, dump_string, (i < buffer_len) ? " ..." : "");
392 }
393 }
394
395 /* ------------------------------------------------------------------------- */
396 /* MARK: SPI Transfer Functions */
397
spi_header_set_flag_byte(uint8_t * header,uint8_t value)398 static void spi_header_set_flag_byte(uint8_t *header, uint8_t value)
399 {
400 header[0] = value;
401 }
402
spi_header_set_accept_len(uint8_t * header,uint16_t len)403 static void spi_header_set_accept_len(uint8_t *header, uint16_t len)
404 {
405 header[1] = ((len >> 0) & 0xFF);
406 header[2] = ((len >> 8) & 0xFF);
407 }
408
spi_header_set_data_len(uint8_t * header,uint16_t len)409 static void spi_header_set_data_len(uint8_t *header, uint16_t len)
410 {
411 header[3] = ((len >> 0) & 0xFF);
412 header[4] = ((len >> 8) & 0xFF);
413 }
414
spi_header_get_flag_byte(const uint8_t * header)415 static uint8_t spi_header_get_flag_byte(const uint8_t *header)
416 {
417 return header[0];
418 }
419
spi_header_get_accept_len(const uint8_t * header)420 static uint16_t spi_header_get_accept_len(const uint8_t *header)
421 {
422 return (header[1] + (uint16_t)(header[2] << 8));
423 }
424
spi_header_get_data_len(const uint8_t * header)425 static uint16_t spi_header_get_data_len(const uint8_t *header)
426 {
427 return (header[3] + (uint16_t)(header[4] << 8));
428 }
429
get_real_rx_frame_start(void)430 static uint8_t *get_real_rx_frame_start(void)
431 {
432 uint8_t *ret = sSpiRxFrameBuffer;
433 int i = 0;
434
435 for (i = 0; i < sSpiRxAlignAllowance; i++)
436 {
437 if (ret[0] != 0xFF)
438 {
439 break;
440 }
441 ret++;
442 }
443
444 return ret;
445 }
446
do_spi_xfer(int len)447 static int do_spi_xfer(int len)
448 {
449 int ret;
450
451 struct spi_ioc_transfer xfer[2] = {{
452 // This part is the delay between C̅S̅ being
453 // asserted and the SPI clock starting. This
454 // is not supported by all Linux SPI drivers.
455 .tx_buf = 0,
456 .rx_buf = 0,
457 .len = 0,
458 .delay_usecs = (uint16_t)sSpiCsDelay,
459 .speed_hz = (uint32_t)sSpiSpeed,
460 .bits_per_word = 8,
461 .cs_change = false,
462 },
463 {
464 // This part is the actual SPI transfer.
465 .tx_buf = (unsigned long)sSpiTxFrameBuffer,
466 .rx_buf = (unsigned long)sSpiRxFrameBuffer,
467 .len = (uint32_t)(len + HEADER_LEN + sSpiRxAlignAllowance),
468 .delay_usecs = 0,
469 .speed_hz = (uint32_t)sSpiSpeed,
470 .bits_per_word = 8,
471 .cs_change = false,
472 }};
473
474 if (sSpiCsDelay > 0)
475 {
476 // A C̅S̅ delay has been specified. Start transactions
477 // with both parts.
478 ret = ioctl(sSpiDevFd, SPI_IOC_MESSAGE(2), &xfer[0]);
479 }
480 else
481 {
482 // No C̅S̅ delay has been specified, so we skip the first
483 // part because it causes some SPI drivers to croak.
484 ret = ioctl(sSpiDevFd, SPI_IOC_MESSAGE(1), &xfer[1]);
485 }
486
487 if (ret != -1)
488 {
489 log_debug_buffer("SPI-TX", sSpiTxFrameBuffer, (int)xfer[1].len, false);
490 log_debug_buffer("SPI-RX", sSpiRxFrameBuffer, (int)xfer[1].len, false);
491
492 sSpiFrameCount++;
493 }
494
495 return ret;
496 }
497
debug_spi_header(const char * hint,bool force)498 static void debug_spi_header(const char *hint, bool force)
499 {
500 if (force || (sLogLevel >= LOG_DEBUG))
501 {
502 const uint8_t *spiRxFrameBuffer = get_real_rx_frame_start();
503
504 syslog(force ? LOG_WARNING : LOG_DEBUG, "%s-TX: H:%02X ACCEPT:%d DATA:%0d\n", hint,
505 spi_header_get_flag_byte(sSpiTxFrameBuffer), spi_header_get_accept_len(sSpiTxFrameBuffer),
506 spi_header_get_data_len(sSpiTxFrameBuffer));
507
508 syslog(force ? LOG_WARNING : LOG_DEBUG, "%s-RX: H:%02X ACCEPT:%d DATA:%0d\n", hint,
509 spi_header_get_flag_byte(spiRxFrameBuffer), spi_header_get_accept_len(spiRxFrameBuffer),
510 spi_header_get_data_len(spiRxFrameBuffer));
511 }
512 }
513
push_pull_spi(void)514 static int push_pull_spi(void)
515 {
516 int ret;
517 uint16_t spi_xfer_bytes = 0;
518 const uint8_t *spiRxFrameBuffer = NULL;
519 uint8_t slave_header;
520 uint16_t slave_max_rx;
521 int successful_exchanges = 0;
522
523 static uint16_t slave_data_len;
524
525 // For now, sSpiRxPayloadSize must be zero
526 // when entering this function. This may change
527 // at some point, for now this makes things
528 // much easier.
529 assert(sSpiRxPayloadSize == 0);
530
531 if (sSpiValidFrameCount == 0)
532 {
533 // Set the reset flag to indicate to our slave that we
534 // are coming up from scratch.
535 spi_header_set_flag_byte(sSpiTxFrameBuffer, SPI_HEADER_RESET_FLAG | SPI_HEADER_PATTERN_VALUE);
536 }
537 else
538 {
539 spi_header_set_flag_byte(sSpiTxFrameBuffer, SPI_HEADER_PATTERN_VALUE);
540 }
541
542 // Zero out our rx_accept and our data_len for now.
543 spi_header_set_accept_len(sSpiTxFrameBuffer, 0);
544 spi_header_set_data_len(sSpiTxFrameBuffer, 0);
545
546 // Sanity check.
547 if (slave_data_len > MAX_FRAME_SIZE)
548 {
549 slave_data_len = 0;
550 }
551
552 if (sSpiTxIsReady)
553 {
554 // Go ahead and try to immediately send a frame if we have it queued up.
555 spi_header_set_data_len(sSpiTxFrameBuffer, sSpiTxPayloadSize);
556
557 if (sSpiTxPayloadSize > spi_xfer_bytes)
558 {
559 spi_xfer_bytes = sSpiTxPayloadSize;
560 }
561 }
562
563 if (sSpiRxPayloadSize == 0)
564 {
565 if (slave_data_len != 0)
566 {
567 // In a previous transaction the slave indicated
568 // it had something to send us. Make sure our
569 // transaction is large enough to handle it.
570 if (slave_data_len > spi_xfer_bytes)
571 {
572 spi_xfer_bytes = slave_data_len;
573 }
574 }
575 else
576 {
577 // Set up a minimum transfer size to allow small
578 // frames the slave wants to send us to be handled
579 // in a single transaction.
580 if (sSpiSmallPacketSize > spi_xfer_bytes)
581 {
582 spi_xfer_bytes = (uint16_t)sSpiSmallPacketSize;
583 }
584 }
585
586 spi_header_set_accept_len(sSpiTxFrameBuffer, spi_xfer_bytes);
587 }
588
589 // Perform the SPI transaction.
590 ret = do_spi_xfer(spi_xfer_bytes);
591
592 if (ret < 0)
593 {
594 perror("push_pull_spi:do_spi_xfer");
595 syslog(LOG_ERR, "push_pull_spi:do_spi_xfer: errno=%d (%s)", errno, strerror(errno));
596
597 // Print out a helpful error message for
598 // a common error.
599 if ((sSpiCsDelay != 0) && (errno == EINVAL))
600 {
601 syslog(LOG_ERR, "SPI ioctl failed with EINVAL. Try adding `--spi-cs-delay=0` to command line arguments.");
602 }
603 goto bail;
604 }
605
606 // Account for misalignment (0xFF bytes at the start)
607 spiRxFrameBuffer = get_real_rx_frame_start();
608
609 debug_spi_header("push_pull", false);
610
611 slave_header = spi_header_get_flag_byte(spiRxFrameBuffer);
612
613 if ((slave_header == 0xFF) || (slave_header == 0x00))
614 {
615 if ((slave_header == spiRxFrameBuffer[1]) && (slave_header == spiRxFrameBuffer[2]) &&
616 (slave_header == spiRxFrameBuffer[3]) && (slave_header == spiRxFrameBuffer[4]))
617 {
618 // Device is off or in a bad state.
619 // In some cases may be induced by flow control.
620 syslog(slave_data_len == 0 ? LOG_DEBUG : LOG_WARNING,
621 "Slave did not respond to frame. (Header was all 0x%02X)", slave_header);
622 sSpiUnresponsiveFrameCount++;
623 }
624 else
625 {
626 // Header is full of garbage
627 syslog(LOG_WARNING, "Garbage in header : %02X %02X %02X %02X %02X", spiRxFrameBuffer[0],
628 spiRxFrameBuffer[1], spiRxFrameBuffer[2], spiRxFrameBuffer[3], spiRxFrameBuffer[4]);
629 sSpiGarbageFrameCount++;
630 if (sLogLevel < LOG_DEBUG)
631 {
632 log_debug_buffer("SPI-TX", sSpiTxFrameBuffer, (int)spi_xfer_bytes + HEADER_LEN + sSpiRxAlignAllowance,
633 true);
634 log_debug_buffer("SPI-RX", sSpiRxFrameBuffer, (int)spi_xfer_bytes + HEADER_LEN + sSpiRxAlignAllowance,
635 true);
636 }
637 }
638 sSpiTxRefusedCount++;
639 goto bail;
640 }
641
642 slave_max_rx = spi_header_get_accept_len(spiRxFrameBuffer);
643 slave_data_len = spi_header_get_data_len(spiRxFrameBuffer);
644
645 if (((slave_header & SPI_HEADER_PATTERN_MASK) != SPI_HEADER_PATTERN_VALUE) || (slave_max_rx > MAX_FRAME_SIZE) ||
646 (slave_data_len > MAX_FRAME_SIZE))
647 {
648 sSpiGarbageFrameCount++;
649 sSpiTxRefusedCount++;
650 slave_data_len = 0;
651 syslog(LOG_WARNING, "Garbage in header : %02X %02X %02X %02X %02X", spiRxFrameBuffer[0], spiRxFrameBuffer[1],
652 spiRxFrameBuffer[2], spiRxFrameBuffer[3], spiRxFrameBuffer[4]);
653 if (sLogLevel < LOG_DEBUG)
654 {
655 log_debug_buffer("SPI-TX", sSpiTxFrameBuffer, (int)spi_xfer_bytes + HEADER_LEN + sSpiRxAlignAllowance,
656 true);
657 log_debug_buffer("SPI-RX", sSpiRxFrameBuffer, (int)spi_xfer_bytes + HEADER_LEN + sSpiRxAlignAllowance,
658 true);
659 }
660 goto bail;
661 }
662
663 sSpiValidFrameCount++;
664
665 if ((slave_header & SPI_HEADER_RESET_FLAG) == SPI_HEADER_RESET_FLAG)
666 {
667 sSlaveResetCount++;
668 syslog(LOG_NOTICE, "Slave did reset (%llu resets so far)", (unsigned long long)sSlaveResetCount);
669 sSlaveDidReset = true;
670 sDumpStats = true;
671 }
672
673 // Handle received packet, if any.
674 if ((sSpiRxPayloadSize == 0) && (slave_data_len != 0) &&
675 (slave_data_len <= spi_header_get_accept_len(sSpiTxFrameBuffer)))
676 {
677 // We have received a packet. Set sSpiRxPayloadSize so that
678 // the packet will eventually get queued up by push_hdlc().
679 sSpiRxPayloadSize = slave_data_len;
680
681 slave_data_len = 0;
682
683 successful_exchanges++;
684 }
685
686 // Handle transmitted packet, if any.
687 if (sSpiTxIsReady && (sSpiTxPayloadSize == spi_header_get_data_len(sSpiTxFrameBuffer)))
688 {
689 if (spi_header_get_data_len(sSpiTxFrameBuffer) <= slave_max_rx)
690 {
691 // Our outbound packet has been successfully transmitted. Clear
692 // sSpiTxPayloadSize and sSpiTxIsReady so that pull_hdlc() can
693 // pull another packet for us to send.
694 sSpiTxIsReady = false;
695 sSpiTxPayloadSize = 0;
696 sSpiTxRefusedCount = 0;
697 successful_exchanges++;
698 }
699 else
700 {
701 // The slave Wasn't ready for what we had to
702 // send them. Incrementing this counter will
703 // turn on rate limiting so that we
704 // don't waste a ton of CPU bombarding them
705 // with useless SPI transfers.
706 sSpiTxRefusedCount++;
707 }
708 }
709
710 if (!sSpiTxIsReady)
711 {
712 sSpiTxRefusedCount = 0;
713 }
714
715 if (successful_exchanges == 2)
716 {
717 sSpiDuplexFrameCount++;
718 }
719 bail:
720 return ret;
721 }
722
check_and_clear_interrupt(void)723 static bool check_and_clear_interrupt(void)
724 {
725 if (sIntGpioValueFd >= 0)
726 {
727 char value[5] = "";
728 ssize_t len;
729
730 lseek(sIntGpioValueFd, 0, SEEK_SET);
731
732 len = read(sIntGpioValueFd, value, sizeof(value) - 1);
733
734 if (len < 0)
735 {
736 perror("check_and_clear_interrupt");
737 sRet = EXIT_FAILURE;
738 }
739
740 // The interrupt pin is active low.
741 return GPIO_INT_ASSERT_STATE == atoi(value);
742 }
743
744 return true;
745 }
746
747 /* ------------------------------------------------------------------------- */
748 /* MARK: HDLC Transfer Functions */
749
750 #define HDLC_BYTE_FLAG 0x7E
751 #define HDLC_BYTE_ESC 0x7D
752 #define HDLC_BYTE_XON 0x11
753 #define HDLC_BYTE_XOFF 0x13
754 #define HDLC_BYTE_SPECIAL 0xF8
755 #define HDLC_ESCAPE_XFORM 0x20
756
hdlc_crc16(uint16_t aFcs,uint8_t aByte)757 static uint16_t hdlc_crc16(uint16_t aFcs, uint8_t aByte)
758 {
759 #if 1
760 // CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
761 // width=16 poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 name="KERMIT"
762 // http://reveng.sourceforge.net/crc-catalogue/16.htm#crc.cat.kermit
763 static const uint16_t sFcsTable[256] = {
764 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5,
765 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52,
766 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3,
767 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
768 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9,
769 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e,
770 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f,
771 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
772 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862,
773 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb,
774 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948,
775 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
776 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226,
777 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497,
778 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704,
779 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
780 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb,
781 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c,
782 0x3de3, 0x2c6a, 0x1ef1, 0x0f78};
783 return (aFcs >> 8) ^ sFcsTable[(aFcs ^ aByte) & 0xff];
784 #else
785 // CRC-16/CCITT-FALSE, same CRC as 802.15.4
786 // width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 name="CRC-16/CCITT-FALSE"
787 // http://reveng.sourceforge.net/crc-catalogue/16.htm#crc.cat.crc-16-ccitt-false
788 aFcs = (uint16_t)((aFcs >> 8) | (aFcs << 8));
789 aFcs ^= aByte;
790 aFcs ^= ((aFcs & 0xff) >> 4);
791 aFcs ^= (aFcs << 12);
792 aFcs ^= ((aFcs & 0xff) << 5);
793 return aFcs;
794 #endif
795 }
796
hdlc_byte_needs_escape(uint8_t byte)797 static bool hdlc_byte_needs_escape(uint8_t byte)
798 {
799 switch (byte)
800 {
801 case HDLC_BYTE_SPECIAL:
802 case HDLC_BYTE_ESC:
803 case HDLC_BYTE_FLAG:
804 case HDLC_BYTE_XOFF:
805 case HDLC_BYTE_XON:
806 return true;
807
808 default:
809 return false;
810 }
811 }
812
push_hdlc(void)813 static int push_hdlc(void)
814 {
815 int ret = 0;
816 const uint8_t * spiRxFrameBuffer = get_real_rx_frame_start();
817 static uint8_t escaped_frame_buffer[MAX_FRAME_SIZE * 2];
818 static uint16_t unescaped_frame_len;
819 static uint16_t escaped_frame_len;
820 static uint16_t escaped_frame_sent;
821
822 if (escaped_frame_len == 0)
823 {
824 if (sSlaveDidReset)
825 {
826 // Indicate an MCU reset.
827 memcpy(escaped_frame_buffer, kHdlcResetSignal, sizeof(kHdlcResetSignal));
828 escaped_frame_len = sizeof(kHdlcResetSignal);
829 sSlaveDidReset = false;
830
831 // Set this to zero, since this isn't a real frame.
832 unescaped_frame_len = 0;
833 }
834 else if (sSpiRxPayloadSize != 0)
835 {
836 // Escape the frame.
837 uint8_t c;
838 uint16_t fcs = kHdlcCrcResetValue;
839 uint16_t i;
840
841 unescaped_frame_len = sSpiRxPayloadSize;
842
843 for (i = 0; i < sSpiRxPayloadSize; i++)
844 {
845 c = spiRxFrameBuffer[i + HEADER_LEN];
846 fcs = hdlc_crc16(fcs, c);
847 if (hdlc_byte_needs_escape(c))
848 {
849 escaped_frame_buffer[escaped_frame_len++] = HDLC_BYTE_ESC;
850 escaped_frame_buffer[escaped_frame_len++] = c ^ HDLC_ESCAPE_XFORM;
851 }
852 else
853 {
854 escaped_frame_buffer[escaped_frame_len++] = c;
855 }
856 }
857
858 fcs ^= 0xFFFF;
859
860 c = fcs & 0xFF;
861 if (hdlc_byte_needs_escape(c))
862 {
863 escaped_frame_buffer[escaped_frame_len++] = HDLC_BYTE_ESC;
864 escaped_frame_buffer[escaped_frame_len++] = c ^ HDLC_ESCAPE_XFORM;
865 }
866 else
867 {
868 escaped_frame_buffer[escaped_frame_len++] = c;
869 }
870
871 c = (fcs >> 8) & 0xFF;
872 if (hdlc_byte_needs_escape(c))
873 {
874 escaped_frame_buffer[escaped_frame_len++] = HDLC_BYTE_ESC;
875 escaped_frame_buffer[escaped_frame_len++] = c ^ HDLC_ESCAPE_XFORM;
876 }
877 else
878 {
879 escaped_frame_buffer[escaped_frame_len++] = c;
880 }
881
882 escaped_frame_buffer[escaped_frame_len++] = HDLC_BYTE_FLAG;
883 escaped_frame_sent = 0;
884 sSpiRxPayloadSize = 0;
885 }
886 else
887 {
888 // Nothing to do.
889 goto bail;
890 }
891 }
892
893 ret = (int)write(sHdlcOutputFd, escaped_frame_buffer + escaped_frame_sent, escaped_frame_len - escaped_frame_sent);
894
895 if (ret < 0)
896 {
897 if (errno == EAGAIN)
898 {
899 ret = 0;
900 }
901 else
902 {
903 perror("push_hdlc:write");
904 syslog(LOG_ERR, "push_hdlc:write: errno=%d (%s)", errno, strerror(errno));
905 }
906 goto bail;
907 }
908
909 escaped_frame_sent += ret;
910
911 // Reset state once we have sent the entire frame.
912 if (escaped_frame_len == escaped_frame_sent)
913 {
914 escaped_frame_len = escaped_frame_sent = 0;
915
916 // Increment counter for statistics
917 sHdlcTxFrameCount++;
918 sHdlcTxFrameByteCount += unescaped_frame_len;
919 }
920
921 ret = 0;
922
923 bail:
924 return ret;
925 }
926
pull_hdlc(void)927 static int pull_hdlc(void)
928 {
929 int ret = 0;
930 static uint16_t fcs;
931 static bool unescape_next_byte = false;
932
933 if (!sSpiTxIsReady)
934 {
935 uint8_t byte;
936 while ((ret = (int)read(sHdlcInputFd, &byte, 1)) == 1)
937 {
938 if (sSpiTxPayloadSize >= (MAX_FRAME_SIZE - HEADER_LEN))
939 {
940 syslog(LOG_WARNING, "HDLC frame was too big");
941 unescape_next_byte = false;
942 sSpiTxPayloadSize = 0;
943 fcs = kHdlcCrcResetValue;
944 }
945 else if (byte == HDLC_BYTE_FLAG)
946 {
947 if (sSpiTxPayloadSize <= 2)
948 {
949 unescape_next_byte = false;
950 sSpiTxPayloadSize = 0;
951 fcs = kHdlcCrcResetValue;
952 continue;
953 }
954 else if (fcs != kHdlcCrcCheckValue)
955 {
956 syslog(LOG_WARNING, "HDLC frame with bad CRC (LEN:%d, FCS:0x%04X)", sSpiTxPayloadSize, fcs);
957 sHdlcRxBadCrcCount++;
958 unescape_next_byte = false;
959 sSpiTxPayloadSize = 0;
960 fcs = kHdlcCrcResetValue;
961 continue;
962 }
963
964 // Clip off the CRC
965 sSpiTxPayloadSize -= 2;
966
967 // Indicate that a frame is ready to go out
968 sSpiTxIsReady = true;
969
970 // Increment counters for statistics
971 sHdlcRxFrameCount++;
972 sHdlcRxFrameByteCount += sSpiTxPayloadSize;
973
974 // Clean up for the next frame
975 unescape_next_byte = false;
976 fcs = kHdlcCrcResetValue;
977 break;
978 }
979 else if (byte == HDLC_BYTE_ESC)
980 {
981 unescape_next_byte = true;
982 continue;
983 }
984 else if (hdlc_byte_needs_escape(byte))
985 {
986 // Skip all other control codes.
987 continue;
988 }
989 else if (unescape_next_byte)
990 {
991 byte = byte ^ HDLC_ESCAPE_XFORM;
992 unescape_next_byte = false;
993 }
994
995 fcs = hdlc_crc16(fcs, byte);
996 sSpiTxFrameBuffer[HEADER_LEN + sSpiTxPayloadSize++] = byte;
997 }
998 }
999
1000 if (ret < 0)
1001 {
1002 if (errno == EAGAIN)
1003 {
1004 ret = 0;
1005 }
1006 else
1007 {
1008 perror("pull_hdlc:read");
1009 syslog(LOG_ERR, "pull_hdlc:read: errno=%d (%s)", errno, strerror(errno));
1010 }
1011 }
1012
1013 return ret < 0 ? ret : 0;
1014 }
1015
1016 /* ------------------------------------------------------------------------- */
1017 /* MARK: Raw Transfer Functions */
1018
push_raw(void)1019 static int push_raw(void)
1020 {
1021 int ret = 0;
1022 const uint8_t * spiRxFrameBuffer = get_real_rx_frame_start();
1023 static uint8_t raw_frame_buffer[MAX_FRAME_SIZE];
1024 static uint16_t raw_frame_len;
1025 static uint16_t raw_frame_sent;
1026
1027 if (raw_frame_len == 0)
1028 {
1029 if (sSlaveDidReset)
1030 {
1031 // Indicates an MCU reset.
1032 // We don't have anything to do here because
1033 // raw mode doesn't have any way to signal
1034 // resets out-of-band.
1035 sSlaveDidReset = false;
1036 }
1037 else if (sSpiRxPayloadSize > 0)
1038 {
1039 // Read the frame into raw_frame_buffer
1040 assert(sSpiRxPayloadSize <= sizeof(raw_frame_buffer));
1041 memcpy(raw_frame_buffer, &spiRxFrameBuffer[HEADER_LEN], sSpiRxPayloadSize);
1042 raw_frame_len = sSpiRxPayloadSize;
1043 raw_frame_sent = 0;
1044 sSpiRxPayloadSize = 0;
1045 }
1046 else
1047 {
1048 // Nothing to do.
1049 goto bail;
1050 }
1051 }
1052
1053 ret = (int)write(sHdlcOutputFd, raw_frame_buffer + raw_frame_sent, raw_frame_len - raw_frame_sent);
1054
1055 if (ret < 0)
1056 {
1057 if (errno == EAGAIN)
1058 {
1059 ret = 0;
1060 }
1061 else
1062 {
1063 perror("push_raw:write");
1064 syslog(LOG_ERR, "push_raw:write: errno=%d (%s)", errno, strerror(errno));
1065 }
1066 goto bail;
1067 }
1068
1069 raw_frame_sent += ret;
1070
1071 // Reset state once we have sent the entire frame.
1072 if (raw_frame_len == raw_frame_sent)
1073 {
1074 // Increment counter for statistics
1075 sHdlcTxFrameCount++;
1076 sHdlcTxFrameByteCount += raw_frame_len;
1077
1078 raw_frame_len = raw_frame_sent = 0;
1079 }
1080
1081 ret = 0;
1082
1083 bail:
1084 return ret;
1085 }
1086
pull_raw(void)1087 static int pull_raw(void)
1088 {
1089 int ret = 0;
1090
1091 if (!sSpiTxIsReady)
1092 {
1093 ret = (int)read(sHdlcInputFd, &sSpiTxFrameBuffer[HEADER_LEN], (size_t)sMTU);
1094
1095 if (ret < 0)
1096 {
1097 if (errno == EAGAIN)
1098 {
1099 ret = 0;
1100 }
1101 else
1102 {
1103 perror("pull_raw:read");
1104 syslog(LOG_ERR, "pull_raw:read: errno=%d (%s)", errno, strerror(errno));
1105 }
1106 }
1107 else if (ret > 0)
1108 {
1109 sSpiTxPayloadSize = (uint16_t)ret;
1110 sSpiTxIsReady = true;
1111
1112 // Increment counters for statistics
1113 sHdlcRxFrameCount++;
1114 sHdlcRxFrameByteCount += sSpiTxPayloadSize;
1115 }
1116 }
1117
1118 return ret < 0 ? ret : 0;
1119 }
1120
1121 /* ------------------------------------------------------------------------- */
1122 /* MARK: Setup Functions */
1123
update_spi_mode(int x)1124 static bool update_spi_mode(int x)
1125 {
1126 sSpiMode = (uint8_t)x;
1127
1128 if ((sSpiDevFd >= 0) && (ioctl(sSpiDevFd, SPI_IOC_WR_MODE, &sSpiMode) < 0))
1129 {
1130 perror("ioctl(SPI_IOC_WR_MODE)");
1131 return false;
1132 }
1133
1134 return true;
1135 }
1136
update_spi_speed(int x)1137 static bool update_spi_speed(int x)
1138 {
1139 sSpiSpeed = x;
1140
1141 if ((sSpiDevFd >= 0) && (ioctl(sSpiDevFd, SPI_IOC_WR_MAX_SPEED_HZ, &sSpiSpeed) < 0))
1142 {
1143 perror("ioctl(SPI_IOC_WR_MAX_SPEED_HZ)");
1144 return false;
1145 }
1146
1147 return true;
1148 }
1149
setup_spi_dev(const char * path)1150 static bool setup_spi_dev(const char *path)
1151 {
1152 int fd = -1;
1153 const uint8_t spi_word_bits = 8;
1154 int ret;
1155
1156 syslog(LOG_DEBUG, "SPI device path: %s", path);
1157
1158 fd = open(path, O_RDWR | O_CLOEXEC);
1159 if (fd < 0)
1160 {
1161 perror("open");
1162 goto bail;
1163 }
1164
1165 // Set the SPI mode.
1166 ret = ioctl(fd, SPI_IOC_WR_MODE, &sSpiMode);
1167 if (ret < 0)
1168 {
1169 perror("ioctl(SPI_IOC_WR_MODE)");
1170 goto bail;
1171 }
1172
1173 // Set the SPI clock speed.
1174 ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &sSpiSpeed);
1175 if (ret < 0)
1176 {
1177 perror("ioctl(SPI_IOC_WR_MAX_SPEED_HZ)");
1178 goto bail;
1179 }
1180
1181 // Set the SPI word size.
1182 ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi_word_bits);
1183 if (ret < 0)
1184 {
1185 perror("ioctl(SPI_IOC_WR_BITS_PER_WORD)");
1186 goto bail;
1187 }
1188
1189 // Lock the file descriptor
1190 if (flock(fd, LOCK_EX | LOCK_NB) < 0)
1191 {
1192 perror("flock");
1193 goto bail;
1194 }
1195
1196 sSpiDevFd = fd;
1197 fd = -1;
1198
1199 bail:
1200 if (fd >= 0)
1201 {
1202 close(fd);
1203 }
1204 return sSpiDevFd >= 0;
1205 }
1206
setup_res_gpio(const char * path)1207 static bool setup_res_gpio(const char *path)
1208 {
1209 int setup_fd = -1;
1210 char *dir_path = NULL;
1211 char *value_path = NULL;
1212 int len;
1213
1214 syslog(LOG_DEBUG, "Reset gpio path: %s", path);
1215
1216 len = asprintf(&dir_path, "%s/direction", path);
1217
1218 if (len < 0)
1219 {
1220 perror("asprintf");
1221 goto bail;
1222 }
1223
1224 len = asprintf(&value_path, "%s/value", path);
1225
1226 if (len < 0)
1227 {
1228 perror("asprintf");
1229 goto bail;
1230 }
1231
1232 setup_fd = open(dir_path, O_WRONLY | O_CLOEXEC);
1233
1234 if (setup_fd >= 0)
1235 {
1236 if (-1 == write(setup_fd, "high\n", 5))
1237 {
1238 perror("set_res_direction");
1239 goto bail;
1240 }
1241 }
1242
1243 sResGpioValueFd = open(value_path, O_WRONLY | O_CLOEXEC);
1244
1245 bail:
1246
1247 if (setup_fd >= 0)
1248 {
1249 close(setup_fd);
1250 }
1251
1252 if (dir_path)
1253 {
1254 free(dir_path);
1255 }
1256
1257 if (value_path)
1258 {
1259 free(value_path);
1260 }
1261
1262 return sResGpioValueFd >= 0;
1263 }
1264
trigger_reset(void)1265 static void trigger_reset(void)
1266 {
1267 if (sResGpioValueFd >= 0)
1268 {
1269 char str[] = {'0' + GPIO_RES_ASSERT_STATE, '\n'};
1270
1271 lseek(sResGpioValueFd, 0, SEEK_SET);
1272 if (write(sResGpioValueFd, str, sizeof(str)) == -1)
1273 {
1274 syslog(LOG_ERR, "trigger_reset(): error on write: %d (%s)", errno, strerror(errno));
1275 }
1276
1277 usleep(10 * USEC_PER_MSEC);
1278
1279 // Set the string to switch to the not-asserted state.
1280 str[0] = '0' + !GPIO_RES_ASSERT_STATE;
1281
1282 lseek(sResGpioValueFd, 0, SEEK_SET);
1283 if (write(sResGpioValueFd, str, sizeof(str)) == -1)
1284 {
1285 syslog(LOG_ERR, "trigger_reset(): error on write: %d (%s)", errno, strerror(errno));
1286 }
1287
1288 syslog(LOG_NOTICE, "Triggered hardware reset");
1289 }
1290 }
1291
setup_int_gpio(const char * path)1292 static bool setup_int_gpio(const char *path)
1293 {
1294 char * edge_path = NULL;
1295 char * dir_path = NULL;
1296 char * value_path = NULL;
1297 ssize_t len;
1298 int setup_fd = -1;
1299
1300 sIntGpioValueFd = -1;
1301
1302 syslog(LOG_DEBUG, "Interrupt gpio path: %s", path);
1303
1304 len = asprintf(&dir_path, "%s/direction", path);
1305
1306 if (len < 0)
1307 {
1308 perror("asprintf");
1309 goto bail;
1310 }
1311
1312 len = asprintf(&edge_path, "%s/edge", path);
1313
1314 if (len < 0)
1315 {
1316 perror("asprintf");
1317 goto bail;
1318 }
1319
1320 len = asprintf(&value_path, "%s/value", path);
1321
1322 if (len < 0)
1323 {
1324 perror("asprintf");
1325 goto bail;
1326 }
1327
1328 setup_fd = open(dir_path, O_WRONLY | O_CLOEXEC);
1329
1330 if (setup_fd >= 0)
1331 {
1332 len = write(setup_fd, "in", 2);
1333 if (len < 0)
1334 {
1335 perror("write");
1336 goto bail;
1337 }
1338
1339 close(setup_fd);
1340 }
1341
1342 setup_fd = open(edge_path, O_WRONLY | O_CLOEXEC);
1343
1344 if (setup_fd >= 0)
1345 {
1346 len = write(setup_fd, "falling", 7);
1347
1348 if (len < 0)
1349 {
1350 perror("write");
1351 goto bail;
1352 }
1353
1354 close(setup_fd);
1355
1356 setup_fd = -1;
1357 }
1358
1359 sIntGpioValueFd = open(value_path, O_RDONLY | O_CLOEXEC);
1360
1361 bail:
1362
1363 if (setup_fd >= 0)
1364 {
1365 close(setup_fd);
1366 }
1367
1368 if (edge_path)
1369 {
1370 free(edge_path);
1371 }
1372
1373 if (dir_path)
1374 {
1375 free(dir_path);
1376 }
1377
1378 if (value_path)
1379 {
1380 free(value_path);
1381 }
1382
1383 return sIntGpioValueFd >= 0;
1384 }
1385
1386 /* ------------------------------------------------------------------------- */
1387 /* MARK: Help */
1388
print_version(void)1389 static void print_version(void)
1390 {
1391 printf("spi-hdlc-adapter " SPI_HDLC_VERSION " (" __TIME__ " " __DATE__ ")\n");
1392 printf("Copyright (c) 2017 The OpenThread Authors, All Rights Reserved\n");
1393 }
1394
print_help(void)1395 static void print_help(void)
1396 {
1397 print_version();
1398 const char *help = "\n"
1399 "Syntax:\n"
1400 "\n"
1401 " spi-hdlc [options] <spi-device-path>\n"
1402 "\n"
1403 "Options:\n"
1404 "\n"
1405 " --stdio ...................... Use `stdin` and `stdout` for HDLC input and\n"
1406 " output. Useful when directly started by the\n"
1407 " program that will be using it.\n"
1408 #if HAVE_OPENPTY
1409 " --pty ........................ Create a pseudoterminal for HDLC input and\n"
1410 " output. The path of the newly-created PTY\n"
1411 " will be written to `stdout`, followed by a\n"
1412 " newline.\n"
1413 #endif // HAVE_OPENPTY
1414 " --raw ........................ Do not encode/decode packets using HDLC.\n"
1415 " Instead, write whole, raw frames to the\n"
1416 " specified input and output FDs. This is useful\n"
1417 " for emulating a serial port, or when datagram-\n"
1418 " based sockets are supplied for stdin and\n"
1419 " stdout` (when used with --stdio).\n"
1420 " --mtu=[MTU] .................. Specify the MTU. Currently only used in raw mode.\n"
1421 " Default and maximum value is 2043.\n"
1422 " -i/--gpio-int[=gpio-path] .... Specify a path to the Linux sysfs-exported\n"
1423 " GPIO directory for the `I̅N̅T̅` pin. If not\n"
1424 " specified, `spi-hdlc` will fall back to\n"
1425 " polling, which is inefficient.\n"
1426 " -r/--gpio-reset[=gpio-path] .. Specify a path to the Linux sysfs-exported\n"
1427 " GPIO directory for the `R̅E̅S̅` pin.\n"
1428 " --spi-mode[=mode] ............ Specify the SPI mode to use (0-3).\n"
1429 " --spi-speed[=hertz] .......... Specify the SPI speed in hertz.\n"
1430 " --spi-cs-delay[=usec] ........ Specify the delay after C̅S̅ assertion, in µsec\n"
1431 " --spi-reset-delay[=ms] ....... Specify the delay after R̅E̅S̅E̅T̅ assertion, in miliseconds\n"
1432 " --spi-align-allowance[=n] .... Specify the maximum number of 0xFF bytes to\n"
1433 " clip from start of MISO frame. Max value is 16.\n"
1434 " --spi-small-packet=[n] ....... Specify the smallest packet we can receive\n"
1435 " in a single transaction(larger packets will\n"
1436 " require two transactions). Default value is 32.\n"
1437 " -v/--verbose[=num] ............Change log verbosity level. (Repeatable)\n"
1438 " num argument is optional and value 1 is default\n"
1439 " when not specified. Every instance of this option\n"
1440 " will increment or decrement (when num is negative)\n"
1441 " the syslog log level accordingly. Starting default\n"
1442 " log level is LOG_NOTICE (5).\n"
1443 " -h/-?/--help ................. Print out usage information and exit.\n"
1444 "\n";
1445
1446 printf("%s", help);
1447 }
1448
log_level_to_str(int log_level)1449 static const char *log_level_to_str(int log_level)
1450 {
1451 const char *str;
1452
1453 switch (log_level)
1454 {
1455 case LOG_EMERG:
1456 str = "EMERG";
1457 break;
1458 case LOG_ALERT:
1459 str = "ALERT";
1460 break;
1461 case LOG_CRIT:
1462 str = "CRIT";
1463 break;
1464 case LOG_ERR:
1465 str = "ERR";
1466 break;
1467 case LOG_WARNING:
1468 str = "WARNING";
1469 break;
1470 case LOG_NOTICE:
1471 str = "NOTICE";
1472 break;
1473 case LOG_INFO:
1474 str = "INFO";
1475 break;
1476 case LOG_DEBUG:
1477 str = "DEBUG";
1478 break;
1479 default:
1480 str = "-unknown-";
1481 break;
1482 }
1483
1484 return str;
1485 }
1486
1487 /* ------------------------------------------------------------------------- */
1488 /* MARK: Main Loop */
1489
main(int argc,char * argv[])1490 int main(int argc, char *argv[])
1491 {
1492 int i = 0;
1493 char prog[32];
1494 static fd_set read_set;
1495 static fd_set write_set;
1496 static fd_set error_set;
1497 struct timeval timeout;
1498 int max_fd = -1;
1499 bool did_print_rate_limit_log = false;
1500
1501 #if AUTO_PRINT_BACKTRACE
1502 struct sigaction sigact;
1503 #endif // if AUTO_PRINT_BACKTRACE
1504
1505 enum
1506 {
1507 ARG_SPI_MODE = 1001,
1508 ARG_SPI_SPEED = 1002,
1509 ARG_VERBOSE = 1003,
1510 ARG_SPI_CS_DELAY = 1004,
1511 ARG_SPI_ALIGN_ALLOWANCE = 1005,
1512 ARG_RAW = 1006,
1513 ARG_MTU = 1007,
1514 ARG_SPI_SMALL_PACKET = 1008,
1515 ARG_SPI_RESET_DELAY = 1009,
1516 };
1517
1518 static struct option options[] = {
1519 {"stdio", no_argument, &sMode, MODE_STDIO},
1520 {"pty", no_argument, &sMode, MODE_PTY},
1521 {"gpio-int", required_argument, NULL, 'i'},
1522 {"gpio-res", required_argument, NULL, 'r'},
1523 {"verbose", optional_argument, NULL, ARG_VERBOSE},
1524 {"version", no_argument, NULL, 'V'},
1525 {"raw", no_argument, NULL, ARG_RAW},
1526 {"mtu", required_argument, NULL, ARG_MTU},
1527 {"help", no_argument, NULL, 'h'},
1528 {"spi-mode", required_argument, NULL, ARG_SPI_MODE},
1529 {"spi-speed", required_argument, NULL, ARG_SPI_SPEED},
1530 {"spi-cs-delay", required_argument, NULL, ARG_SPI_CS_DELAY},
1531 {"spi-align-allowance", required_argument, NULL, ARG_SPI_ALIGN_ALLOWANCE},
1532 {"spi-small-packet", required_argument, NULL, ARG_SPI_SMALL_PACKET},
1533 {"spi-reset-delay", required_argument, NULL, ARG_SPI_RESET_DELAY},
1534 {NULL, 0, NULL, 0},
1535 };
1536
1537 strncpy(prog, argv[0], sizeof(prog) - 1);
1538 prog[sizeof(prog) - 1] = 0;
1539
1540 if (argc < 2)
1541 {
1542 print_help();
1543 exit(EXIT_FAILURE);
1544 }
1545
1546 // ========================================================================
1547 // INITIALIZATION
1548
1549 sPreviousHandlerForSIGINT = signal(SIGINT, &signal_SIGINT);
1550 sPreviousHandlerForSIGTERM = signal(SIGTERM, &signal_SIGTERM);
1551 signal(SIGHUP, &signal_SIGHUP);
1552 signal(SIGUSR1, &signal_dumpstats);
1553 signal(SIGUSR2, &signal_clearstats);
1554
1555 #if AUTO_PRINT_BACKTRACE
1556 sigact.sa_sigaction = &signal_critical;
1557 sigact.sa_flags = SA_RESTART | SA_SIGINFO | SA_NOCLDWAIT;
1558
1559 sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL);
1560 sigaction(SIGBUS, &sigact, (struct sigaction *)NULL);
1561 sigaction(SIGILL, &sigact, (struct sigaction *)NULL);
1562 sigaction(SIGABRT, &sigact, (struct sigaction *)NULL);
1563 #endif // if AUTO_PRINT_BACKTRACE
1564
1565 // ========================================================================
1566 // ARGUMENT PARSING
1567
1568 openlog(basename(prog), LOG_PERROR | LOG_PID | LOG_CONS, LOG_DAEMON);
1569
1570 setlogmask(LOG_UPTO(sLogLevel));
1571
1572 while (1)
1573 {
1574 int c = getopt_long(argc, argv, "i:r:vVh?", options, NULL);
1575 if (c == -1)
1576 {
1577 break;
1578 }
1579 else
1580 {
1581 switch (c)
1582 {
1583 case 'i':
1584 if (!setup_int_gpio(optarg))
1585 {
1586 syslog(LOG_ERR, "Unable to setup INT GPIO \"%s\", %s", optarg, strerror(errno));
1587 exit(EXIT_FAILURE);
1588 }
1589 break;
1590
1591 case ARG_SPI_ALIGN_ALLOWANCE:
1592 assert(optarg);
1593
1594 errno = 0;
1595 sSpiRxAlignAllowance = atoi(optarg);
1596
1597 if (errno != 0 || (sSpiRxAlignAllowance < 0))
1598 {
1599 syslog(LOG_ERR, "Invalid SPI RX Align Allowance \"%s\"", optarg);
1600 exit(EXIT_FAILURE);
1601 }
1602
1603 if (sSpiRxAlignAllowance > SPI_RX_ALIGN_ALLOWANCE_MAX)
1604 {
1605 syslog(LOG_WARNING, "Reducing SPI RX Align Allowance from %s to %d", optarg,
1606 SPI_RX_ALIGN_ALLOWANCE_MAX);
1607 sSpiRxAlignAllowance = SPI_RX_ALIGN_ALLOWANCE_MAX;
1608 }
1609
1610 break;
1611
1612 case ARG_SPI_MODE:
1613 assert(optarg);
1614
1615 if (!update_spi_mode(atoi(optarg)))
1616 {
1617 syslog(LOG_ERR, "Unable to set SPI mode to \"%s\", %s", optarg, strerror(errno));
1618 exit(EXIT_FAILURE);
1619 }
1620 break;
1621
1622 case ARG_SPI_SPEED:
1623 assert(optarg);
1624
1625 if (!update_spi_speed(atoi(optarg)))
1626 {
1627 syslog(LOG_ERR, "Unable to set SPI speed to \"%s\", %s", optarg, strerror(errno));
1628 exit(EXIT_FAILURE);
1629 }
1630 break;
1631
1632 case ARG_SPI_SMALL_PACKET:
1633 assert(optarg);
1634
1635 sSpiSmallPacketSize = atoi(optarg);
1636 if (sSpiSmallPacketSize > MAX_FRAME_SIZE - HEADER_LEN)
1637 {
1638 syslog(LOG_WARNING, "Reducing SPI small-packet size from %s to %d", optarg,
1639 MAX_FRAME_SIZE - HEADER_LEN);
1640 sSpiSmallPacketSize = MAX_FRAME_SIZE - HEADER_LEN;
1641 }
1642 if (sSpiSmallPacketSize < 0)
1643 {
1644 syslog(LOG_ERR, "The argument to --spi-small-packet cannot be negative. (Given: \"%s\")", optarg);
1645 exit(EXIT_FAILURE);
1646 }
1647 syslog(LOG_NOTICE, "SPI small-packet size set to %d bytes.", sSpiSmallPacketSize);
1648 break;
1649
1650 case ARG_SPI_CS_DELAY:
1651 assert(optarg);
1652
1653 sSpiCsDelay = atoi(optarg);
1654 if (sSpiCsDelay < 0)
1655 {
1656 syslog(LOG_ERR, "Negative values (%d) for --spi-cs-delay are invalid.", sSpiCsDelay);
1657 exit(EXIT_FAILURE);
1658 }
1659 syslog(LOG_NOTICE, "SPI CS Delay set to %d usec", sSpiCsDelay);
1660 break;
1661
1662 case ARG_SPI_RESET_DELAY:
1663 assert(optarg);
1664
1665 sSpiResetDelay = atoi(optarg);
1666 if (sSpiResetDelay < 0)
1667 {
1668 syslog(LOG_ERR, "Negative value (%d) for --spi-reset-delay is invalid.", sSpiResetDelay);
1669 exit(EXIT_FAILURE);
1670 }
1671 syslog(LOG_NOTICE, "SPI RESET Delay set to %d ms", sSpiResetDelay);
1672 break;
1673
1674 case ARG_RAW:
1675 sUseRawFrames = true;
1676 syslog(LOG_NOTICE, "HDLC encoding/decoding disabled. Will use raw frames for input/output.");
1677 break;
1678
1679 case ARG_MTU:
1680 assert(optarg);
1681
1682 sMTU = atoi(optarg);
1683 if (sMTU > MAX_FRAME_SIZE - HEADER_LEN)
1684 {
1685 syslog(LOG_ERR, "Specified MTU of %d is too large, maximum is %d bytes.", sMTU,
1686 MAX_FRAME_SIZE - HEADER_LEN);
1687 exit(EXIT_FAILURE);
1688 }
1689 if (sMTU < 1)
1690 {
1691 syslog(LOG_ERR, "Specified MTU of %d is too small, minimum is 1 byte.", sMTU);
1692 exit(EXIT_FAILURE);
1693 }
1694 syslog(LOG_NOTICE, "MTU set to %d bytes", sMTU);
1695 break;
1696
1697 case 'r':
1698 if (!setup_res_gpio(optarg))
1699 {
1700 syslog(LOG_ERR, "Unable to setup RES GPIO \"%s\", %s", optarg, strerror(errno));
1701 exit(EXIT_FAILURE);
1702 }
1703 break;
1704
1705 case 'v':
1706 case ARG_VERBOSE:
1707 sLogLevel += (optarg != NULL) ? atoi(optarg) : 1;
1708
1709 if (sLogLevel > LOG_DEBUG)
1710 {
1711 sLogLevel = LOG_DEBUG;
1712 }
1713
1714 if (sLogLevel < LOG_EMERG)
1715 {
1716 sLogLevel = LOG_EMERG;
1717 }
1718
1719 setlogmask(LOG_UPTO(sLogLevel));
1720 syslog(sLogLevel, "Verbosity set to log level %s (%d)", log_level_to_str(sLogLevel), sLogLevel);
1721 break;
1722
1723 case 'V':
1724 print_version();
1725 exit(EXIT_SUCCESS);
1726 break;
1727
1728 case 'h':
1729 case '?':
1730 print_help();
1731 exit(EXIT_SUCCESS);
1732 break;
1733 }
1734 }
1735 }
1736
1737 syslog(LOG_NOTICE, "spi-hdlc-adapter " SPI_HDLC_VERSION " (" __TIME__ " " __DATE__ ")\n");
1738
1739 if (optind == argc)
1740 {
1741 fprintf(stderr, "%s: Missing SPI device path\n", prog);
1742 exit(EXIT_FAILURE);
1743 }
1744 else if (optind + 1 == argc)
1745 {
1746 if (!setup_spi_dev(argv[optind]))
1747 {
1748 char spi_path[64];
1749
1750 strncpy(spi_path, argv[optind], sizeof(spi_path) - 1);
1751 spi_path[sizeof(spi_path) - 1] = 0;
1752 syslog(LOG_ERR, "%s: Unable to open SPI device \"%s\", %s", prog, spi_path, strerror(errno));
1753 exit(EXIT_FAILURE);
1754 }
1755 }
1756 else
1757 {
1758 fprintf(stderr, "%s: Unexpected argument \"%s\"\n", prog, argv[optind + 1]);
1759 exit(EXIT_FAILURE);
1760 }
1761
1762 if (sMode == MODE_STDIO)
1763 {
1764 sHdlcInputFd = dup(STDIN_FILENO);
1765 sHdlcOutputFd = dup(STDOUT_FILENO);
1766 close(STDIN_FILENO);
1767 close(STDOUT_FILENO);
1768 }
1769 else if (sMode == MODE_PTY)
1770 {
1771 #if HAVE_OPENPTY
1772
1773 static int pty_slave_fd = -1;
1774 char pty_name[1024];
1775 sRet = openpty(&sHdlcInputFd, &pty_slave_fd, pty_name, NULL, NULL);
1776
1777 if (sRet != 0)
1778 {
1779 perror("openpty");
1780 goto bail;
1781 }
1782
1783 sHdlcOutputFd = dup(sHdlcInputFd);
1784
1785 printf("%s\n", pty_name);
1786
1787 close(STDOUT_FILENO);
1788
1789 #else // if HAVE_OPENPTY
1790
1791 syslog(LOG_ERR, "Not built with support for `--pty`.");
1792 sRet = EXIT_FAILURE;
1793 goto bail;
1794
1795 #endif // else HAVE_OPENPTY
1796 }
1797 else
1798 {
1799 sRet = EXIT_FAILURE;
1800 goto bail;
1801 }
1802
1803 if ((sHdlcInputFd < 0) || (sHdlcOutputFd < 0))
1804 {
1805 sRet = EXIT_FAILURE;
1806 goto bail;
1807 }
1808
1809 // Set up sHdlcInputFd for non-blocking I/O
1810 if (-1 == (i = fcntl(sHdlcInputFd, F_GETFL, 0)))
1811 {
1812 i = 0;
1813 }
1814 IGNORE_RETURN_VALUE(fcntl(sHdlcInputFd, F_SETFL, i | O_NONBLOCK));
1815
1816 // Since there are so few file descriptors in
1817 // this program, we calculate `max_fd` once
1818 // instead of trying to optimize its value
1819 // at every iteration.
1820 max_fd = sHdlcInputFd;
1821
1822 if (max_fd < sHdlcOutputFd)
1823 {
1824 max_fd = sHdlcOutputFd;
1825 }
1826
1827 if (max_fd < sIntGpioValueFd)
1828 {
1829 max_fd = sIntGpioValueFd;
1830 }
1831
1832 if (sIntGpioValueFd < 0)
1833 {
1834 syslog(LOG_WARNING, "Interrupt pin was not set, must poll SPI. Performance will suffer.");
1835 }
1836
1837 trigger_reset();
1838
1839 usleep((useconds_t)sSpiResetDelay * USEC_PER_MSEC);
1840
1841 // ========================================================================
1842 // MAIN LOOP
1843
1844 while (sRet == 0)
1845 {
1846 int timeout_ms = MSEC_PER_SEC * 60 * 60 * 24; // 24 hours
1847
1848 FD_ZERO(&read_set);
1849 FD_ZERO(&write_set);
1850 FD_ZERO(&error_set);
1851
1852 if (!sSpiTxIsReady)
1853 {
1854 FD_SET(sHdlcInputFd, &read_set);
1855 }
1856 else
1857 {
1858 // We have data to send to the slave.
1859 timeout_ms = 0;
1860 }
1861
1862 if (sSpiRxPayloadSize != 0)
1863 {
1864 // We have data that we are waiting to send out
1865 // of the HDLC descriptor, so we need to wait
1866 // for that to clear out before we can do anything
1867 // else.
1868 FD_SET(sHdlcOutputFd, &write_set);
1869 }
1870 else if (sIntGpioValueFd >= 0)
1871 {
1872 if (check_and_clear_interrupt())
1873 {
1874 // Interrupt pin is asserted,
1875 // set the timeout to be 0.
1876 timeout_ms = 0;
1877
1878 syslog(LOG_DEBUG, "Interrupt.");
1879 }
1880 else
1881 {
1882 // The interrupt pin was not asserted,
1883 // so we wait for the interrupt pin to
1884 // be asserted by adding it to the error
1885 // set.
1886 FD_SET(sIntGpioValueFd, &error_set);
1887 }
1888 }
1889 else if (timeout_ms > SPI_POLL_PERIOD_MSEC)
1890 {
1891 // In this case we don't have an interrupt, so
1892 // we revert to SPI polling.
1893 timeout_ms = SPI_POLL_PERIOD_MSEC;
1894 }
1895
1896 if (sDumpStats)
1897 {
1898 timeout_ms = 0;
1899 }
1900
1901 if (sSpiTxRefusedCount)
1902 {
1903 int min_timeout = 0;
1904
1905 // We are being rate-limited by the slave. This is
1906 // fairly normal behavior. Based on number of times
1907 // slave has refused a transmission, we apply a
1908 // minimum timeout.
1909
1910 if (sSpiTxRefusedCount < IMMEDIATE_RETRY_COUNT)
1911 {
1912 min_timeout = IMMEDIATE_RETRY_TIMEOUT_MSEC;
1913 }
1914 else if (sSpiTxRefusedCount < FAST_RETRY_COUNT)
1915 {
1916 min_timeout = FAST_RETRY_TIMEOUT_MSEC;
1917 }
1918 else
1919 {
1920 min_timeout = SLOW_RETRY_TIMEOUT_MSEC;
1921 }
1922
1923 if (timeout_ms < min_timeout)
1924 {
1925 timeout_ms = min_timeout;
1926 }
1927
1928 if (sSpiTxIsReady && !did_print_rate_limit_log && (sSpiTxRefusedCount > 1))
1929 {
1930 // To avoid printing out this message over and over,
1931 // we only print it out once the refused count is at
1932 // two or higher when we actually have something to
1933 // send the slave. And then, we only print it once.
1934 syslog(LOG_INFO, "Slave is rate limiting transactions");
1935
1936 did_print_rate_limit_log = true;
1937 }
1938
1939 if (sSpiTxRefusedCount == 30)
1940 {
1941 // Ua-oh. The slave hasn't given us a chance to send
1942 // it anything for over thirty frames. If this ever
1943 // happens, print out a warning to the logs.
1944 syslog(LOG_WARNING, "Slave seems stuck.");
1945 }
1946
1947 if (sSpiTxRefusedCount == 100)
1948 {
1949 // Double ua-oh. The slave hasn't given us a chance
1950 // to send it anything for over a hundred frames.
1951 // This almost certainly means that the slave has
1952 // locked up or gotten into an unrecoverable state.
1953 // It is not spi-hdlc-adapter's job to identify and
1954 // reset misbehaving devices (that is handled at a
1955 // higher level), but we go ahead and log the condition
1956 // for debugging purposes.
1957 syslog(LOG_ERR, "Slave seems REALLY stuck.");
1958 }
1959 }
1960 else
1961 {
1962 did_print_rate_limit_log = false;
1963 }
1964
1965 // Calculate the timeout value.
1966 timeout.tv_sec = timeout_ms / MSEC_PER_SEC;
1967 timeout.tv_usec = (timeout_ms % MSEC_PER_SEC) * USEC_PER_MSEC;
1968
1969 // Wait for something to happen.
1970 IGNORE_RETURN_VALUE(select(max_fd + 1, &read_set, &write_set, &error_set, &timeout));
1971
1972 if (sDumpStats || sRet != 0)
1973 {
1974 sDumpStats = false;
1975 syslog(LOG_NOTICE, "INFO: sSlaveResetCount=%llu", (unsigned long long)sSlaveResetCount);
1976 syslog(LOG_NOTICE, "INFO: sSpiFrameCount=%llu", (unsigned long long)sSpiFrameCount);
1977 syslog(LOG_NOTICE, "INFO: sSpiValidFrameCount=%llu", (unsigned long long)sSpiValidFrameCount);
1978 syslog(LOG_NOTICE, "INFO: sSpiDuplexFrameCount=%llu", (unsigned long long)sSpiDuplexFrameCount);
1979 syslog(LOG_NOTICE, "INFO: sSpiUnresponsiveFrameCount=%llu", (unsigned long long)sSpiUnresponsiveFrameCount);
1980 syslog(LOG_NOTICE, "INFO: sSpiGarbageFrameCount=%llu", (unsigned long long)sSpiGarbageFrameCount);
1981 syslog(LOG_NOTICE, "INFO: sHdlcTxFrameCount=%llu", (unsigned long long)sHdlcTxFrameCount);
1982 syslog(LOG_NOTICE, "INFO: sHdlcTxFrameByteCount=%llu", (unsigned long long)sHdlcTxFrameByteCount);
1983 syslog(LOG_NOTICE, "INFO: sHdlcRxFrameCount=%llu", (unsigned long long)sHdlcRxFrameCount);
1984 syslog(LOG_NOTICE, "INFO: sHdlcRxFrameByteCount=%llu", (unsigned long long)sHdlcRxFrameByteCount);
1985 syslog(LOG_NOTICE, "INFO: sHdlcRxBadCrcCount=%llu", (unsigned long long)sHdlcRxBadCrcCount);
1986 }
1987
1988 // Handle serial input.
1989 if (FD_ISSET(sHdlcInputFd, &read_set))
1990 {
1991 // Read in the data.
1992 if ((sUseRawFrames ? pull_raw() : pull_hdlc()) < 0)
1993 {
1994 sRet = EXIT_FAILURE;
1995 break;
1996 }
1997 }
1998
1999 // Handle serial output.
2000 if (FD_ISSET(sHdlcOutputFd, &write_set))
2001 {
2002 // Write out the data.
2003 if ((sUseRawFrames ? push_raw() : push_hdlc()) < 0)
2004 {
2005 sRet = EXIT_FAILURE;
2006 break;
2007 }
2008
2009 continue;
2010 }
2011
2012 // Service the SPI port if we can receive
2013 // a packet or we have a packet to be sent.
2014 if ((sSpiRxPayloadSize == 0) && (sSpiTxIsReady || check_and_clear_interrupt()))
2015 {
2016 // We guard this with the above check because we don't
2017 // want to overwrite any previously received (but not
2018 // yet pushed out) frames.
2019 if (push_pull_spi() < 0)
2020 {
2021 sRet = EXIT_FAILURE;
2022 }
2023 }
2024 }
2025
2026 // ========================================================================
2027 // SHUTDOWN
2028
2029 bail:
2030 if (sCaughtSignal != -1)
2031 {
2032 syslog(LOG_ERR, "Caught %s", strsignal(sCaughtSignal));
2033 }
2034
2035 syslog(LOG_NOTICE, "Shutdown. (sRet = %d)", sRet);
2036
2037 syslog(LOG_NOTICE, "Reset NCP/RCP");
2038 trigger_reset();
2039
2040 if (sRet == EXIT_QUIT)
2041 {
2042 sRet = EXIT_SUCCESS;
2043 }
2044 else if (sRet == -1)
2045 {
2046 sRet = EXIT_FAILURE;
2047 }
2048
2049 return sRet;
2050 }
2051