52#define BUFMASK (BUFLEN-1)
53#define hasSpace(dir) (((dir##Write + 1) & BUFMASK) != dir##Read)
54#define hasData(dir) (dir##Write != dir##Read)
55#define inca(idx,amount) do { \
56 idx = (idx + amount) & BUFMASK; \
58#define inc1(idx) inca(idx, 1)
59#define normalize(idx) do { idx &= BUFMASK; } while (0)
64 unsigned short category,
65 std::string description,
66 unsigned char *buffer,
int length) {
67 if (!(options & category)) {
70 printf(
"pump: %s %d bytes: (", description.c_str(), length);
71 for (
int i = 0; i<length; i++) {
72 printf(
"%02x ", buffer[i]);
84 std::lock_guard<std::mutex> lock(dataLink->
serialMutex_);
85 serialFd = dataLink->
fd;
91 if (cancellationWatch.
watch(1, 0)) {
106 std::lock_guard<std::mutex> inputLock(dataLink->
inputMutex_);
108 FD_SET(serialFd, &r_set);
112 std::lock_guard<std::mutex> outputLock(dataLink->
outputMutex_);
114 FD_SET(serialFd, &w_set);
121 struct timeval tv = {1, 0};
122 int res = select(nfds, &r_set, &w_set, NULL, &tv);
140 if (FD_ISSET(serialFd, &w_set)) {
141 std::lock_guard<std::mutex> serialLock(dataLink->
serialMutex_);
142 std::lock_guard<std::mutex> outputLock(dataLink->
outputMutex_);
160 if (FD_ISSET(serialFd, &r_set)) {
161 std::lock_guard<std::mutex> serialLock(dataLink->
serialMutex_);
162 std::lock_guard<std::mutex> inputLock(dataLink->
inputMutex_);
179 std::vector<BufferStore> receivedData;
180 bool isLinkStable =
true;
182 bool hasInputData =
false;
184 std::lock_guard<std::mutex> inputLock(dataLink->
inputMutex_);
185 hasInputData =
hasData(dataLink->in);
215#define BAUD_RATES_TABLE_SIZE (sizeof(kBaudRatesTable) / sizeof(int))
224 const int cancellationFd)
226, requestedBaudRate_(baud)
228, noDSRCheck_(noDSRCheck)
230, cancellationFd_(cancellationFd) {
234 for (
int i = 0; i < 128; i++) {
235 unsigned int carry =
crc_table[i] & 0x8000;
236 unsigned int tmp = (
crc_table[i] << 1) & 0xffff;
237 crc_table[i * 2 + (carry ? 0 : 1)] = tmp ^ 0x1021;
238 crc_table[i * 2 + (carry ? 1 : 0)] = tmp;
255 <<
" baud, fd=" <<
fd << endl;
258 fcntl(
fd, F_SETFL, O_NONBLOCK);
303 std::lock_guard<std::mutex> inputLock(
inputMutex_);
307 lout <<
"resetting serial connection" << endl;
321 if (resetBaudRateIndex) {
335 <<
" baud, fd=" <<
fd << endl;
338 fcntl(
fd, F_SETFL, O_NONBLOCK);
364 lout <<
"packet: >> ";
368 lout <<
" len=" << dec << len;
372 unsigned short crcOut = 0;
373 for (
int i = 0; i < len; i++) {
374 unsigned char c = b.
getByte(i);
398 message.
addByte(crcOut & 0xff);
413 for (
unsigned long i = 0; i < message.
getLen(); i++) {
423 std::lock_guard<std::mutex> inputLock(
inputMutex_);
497 lout <<
"packet: BAD CRC" << endl;
500 lout <<
"packet: << ";
507 receivedData.push_back(
rcv);
513 bool hasOutputData =
false;
533 int rx_amount = (inw >
inRead) ?
535 if (rx_amount > 15) {
544 for (vector<BufferStore>::iterator i = receivedData.begin(); i != receivedData.end(); i++) {
558 res = ioctl(
fd, TIOCMGET, &arg);
563 lout <<
"packet: < DTR:" << ((arg & TIOCM_DTR)?1:0)
564 <<
" RTS:" << ((arg & TIOCM_RTS)?1:0)
565 <<
" DCD:" << ((arg & TIOCM_CAR)?1:0)
566 <<
" DSR:" << ((arg & TIOCM_DSR)?1:0)
567 <<
" CTS:" << ((arg & TIOCM_CTS)?1:0) << endl;
568 if (!((arg & TIOCM_RTS) && (arg & TIOCM_DTR))) {
569 arg |= (TIOCM_DTR | TIOCM_RTS);
570 res = ioctl(
fd, TIOCMSET, &arg);
574 lout <<
"packet: > DTR:" << ((arg & TIOCM_DTR)?1:0)
575 <<
" RTS:" << ((arg & TIOCM_RTS)?1:0)
576 <<
" DCD:" << ((arg & TIOCM_CAR)?1:0)
577 <<
" DSR:" << ((arg & TIOCM_DSR)?1:0)
578 <<
" CTS:" << ((arg & TIOCM_CTS)?1:0) << endl;
587 lout <<
"packet: linkFATAL\n";
589 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, bool noDSRCheck, 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
int outputDataReadyPipe_[2]
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 * 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