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