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