51#define BUFMASK (BUFLEN-1)
52#define hasSpace(dir) (((dir##Write + 1) & BUFMASK) != dir##Read)
53#define hasData(dir) (dir##Write != dir##Read)
54#define inca(idx,amount) do { \
55 idx = (idx + amount) & BUFMASK; \
57#define inc1(idx) inca(idx, 1)
58#define normalize(idx) do { idx &= BUFMASK; } while (0)
71 unsigned short category,
72 std::string description,
73 unsigned char *buffer,
int length) {
74 if (!(options & category)) {
77 printf(
"pump: %s %d bytes: (", description.c_str(), length);
78 for (
int i = 0; i<length; i++) {
79 printf(
"%02x ", buffer[i]);
91 std::lock_guard<std::mutex> lock(dataLink->
serialMutex_);
92 serialFd = dataLink->
fd;
98 if (cancellationWatch.
watch(1, 0)) {
113 std::lock_guard<std::mutex> inputLock(dataLink->
inputMutex_);
115 FD_SET(serialFd, &r_set);
119 std::lock_guard<std::mutex> outputLock(dataLink->
outputMutex_);
121 FD_SET(serialFd, &w_set);
125 struct timeval tv = {1, 0};
126 int res = select(MAX(serialFd, dataLink->
cancellationFd_) + 1, &r_set, &w_set, NULL, &tv);
139 if (FD_ISSET(serialFd, &w_set)) {
140 std::lock_guard<std::mutex> serialLock(dataLink->
serialMutex_);
141 std::lock_guard<std::mutex> outputLock(dataLink->
outputMutex_);
159 if (FD_ISSET(serialFd, &r_set)) {
160 std::lock_guard<std::mutex> serialLock(dataLink->
serialMutex_);
161 std::lock_guard<std::mutex> inputLock(dataLink->
inputMutex_);
178 std::vector<BufferStore> receivedData;
179 bool isLinkStable =
true;
181 bool hasInputData =
false;
183 std::lock_guard<std::mutex> inputLock(dataLink->
inputMutex_);
184 hasInputData =
hasData(dataLink->in);
214#define BAUD_RATES_TABLE_SIZE (sizeof(kBaudRatesTable) / sizeof(int))
222 const int cancellationFd)
224, requestedBaudRate_(baud)
227, cancellationFd_(cancellationFd) {
231 for (
int i = 0; i < 128; i++) {
232 unsigned int carry =
crc_table[i] & 0x8000;
233 unsigned int tmp = (
crc_table[i] << 1) & 0xffff;
234 crc_table[i * 2 + (carry ? 0 : 1)] = tmp ^ 0x1021;
235 crc_table[i * 2 + (carry ? 1 : 0)] = tmp;
249 <<
" baud, fd=" <<
fd << endl;
252 fcntl(
fd, F_SETFL, O_NONBLOCK);
293 std::lock_guard<std::mutex> inputLock(
inputMutex_);
297 lout <<
"resetting serial connection" << endl;
311 if (resetBaudRateIndex) {
325 <<
" baud, fd=" <<
fd << endl;
328 fcntl(
fd, F_SETFL, O_NONBLOCK);
349 lout <<
"packet: >> ";
353 lout <<
" len=" << dec << len;
357 unsigned short crcOut = 0;
358 for (
int i = 0; i < len; i++) {
359 unsigned char c = b.
getByte(i);
383 message.
addByte(crcOut & 0xff);
398 for (
unsigned long i = 0; i < message.
getLen(); i++) {
408 std::lock_guard<std::mutex> inputLock(
inputMutex_);
482 lout <<
"packet: BAD CRC" << endl;
485 lout <<
"packet: << ";
492 receivedData.push_back(
rcv);
498 bool hasOutputData =
false;
518 int rx_amount = (inw >
inRead) ?
520 if (rx_amount > 15) {
529 for (vector<BufferStore>::iterator i = receivedData.begin(); i != receivedData.end(); i++) {
543 res = ioctl(
fd, TIOCMGET, &arg);
548 lout <<
"packet: < DTR:" << ((arg & TIOCM_DTR)?1:0)
549 <<
" RTS:" << ((arg & TIOCM_RTS)?1:0)
550 <<
" DCD:" << ((arg & TIOCM_CAR)?1:0)
551 <<
" DSR:" << ((arg & TIOCM_DSR)?1:0)
552 <<
" CTS:" << ((arg & TIOCM_CTS)?1:0) << endl;
553 if (!((arg & TIOCM_RTS) && (arg & TIOCM_DTR))) {
554 arg |= (TIOCM_DTR | TIOCM_RTS);
555 res = ioctl(
fd, TIOCMSET, &arg);
559 lout <<
"packet: > DTR:" << ((arg & TIOCM_DTR)?1:0)
560 <<
" RTS:" << ((arg & TIOCM_RTS)?1:0)
561 <<
" DCD:" << ((arg & TIOCM_CAR)?1:0)
562 <<
" DSR:" << ((arg & TIOCM_DSR)?1:0)
563 <<
" CTS:" << ((arg & TIOCM_CTS)?1:0) << endl;
568 if ((arg & TIOCM_DSR) == 0) {
572 lout <<
"packet: linkFATAL\n";
574 lout <<
"packet: linkFAILED\n";
A generic container for an array of bytes.
void addByte(unsigned char c)
Appends a byte to the content of this instance.
unsigned long getLen() const
Retrieves the length of a BufferStore.
unsigned char getByte(long pos=0) const
Retrieves the byte at index pos.
void init()
Initializes the BufferStore.
Thread-safe class responsible for managing the underlying serial device and data link framing.
const int requestedBaudRate_
Requested baud rate; -1 indicates automatic.
void addToCrc(unsigned char a, unsigned short *crc)
void sendReceivedData(std::vector< BufferStore > &receivedData)
void internalReset(bool resetBaudRateIndex)
const std::string devname
unsigned short receivedCRC
unsigned int crc_table[256]
friend void * data_pump_thread(void *)
void send(BufferStore &b, bool isEPOC)
Send a buffer out to serial line.
bool processInputData(std::vector< BufferStore > &receivedData)
Reads the incoming data and processes data frames.
unsigned char * outBuffer
DataLink(const char *fname, int baud, Link *_link, unsigned short verbose, const int cancellationFd)
std::condition_variable outputCondition_
void shutdown()
Store a flag that we're shutting down and signal any waiting send calls.
unsigned short inCRCstate
const int cancellationFd_
Used to signal cancellation.
pthread_t dataPumpThreadId_
A simple thread-safe wrapper for select()
void addIO(const int fd)
Adds a file descriptor to the set of descriptors.
bool watch(const long secs, const long usecs)
Performs a select() call.
void receive(BufferStore buf)
Effectively a delegate method that accepts data from our DataLink instance.
static const int kBaudRatesTable[]
void log_data(unsigned short options, unsigned short category, std::string description, unsigned char *buffer, int length)
static void usr1handler(int sig)
Signal handler does nothing.
static void * data_pump_thread(void *arg)
#define inca(idx, amount)
#define BAUD_RATES_TABLE_SIZE
int init_serial(const char *dev, int speed, int debug)
#define PKT_DEBUG_HANDSHAKE