⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serialcomm.cpp

📁 tinyos-2.x.rar
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2007, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * @author Philipp Huppertz <huppertz@tkn.tu-berlin.de>
 */

#include "serialcomm.h"
#include "sharedinfo.h"

#include <ctime>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fcntl.h>
#include <termios.h>
#include <pthread.h>
#include <sstream>
#include <sys/time.h>
#include <errno.h>
#include <stdint.h>

using namespace std;

/* forward declarations of pthrad helper functions*/
void* readSerialThread(void*);
void* writeSerialThread(void*);

tcflag_t SerialComm::parseBaudrate(int requested)
{
    int baudrate;

    switch (requested)
    {
#ifdef B50
    case 50:
        baudrate = B50;
        break;
#endif
#ifdef B75

    case 75:
        baudrate = B75;
        break;
#endif
#ifdef B110

    case 110:
        baudrate = B110;
        break;
#endif
#ifdef B134

    case 134:
        baudrate = B134;
        break;
#endif
#ifdef B150

    case 150:
        baudrate = B150;
        break;
#endif
#ifdef B200

    case 200:
        baudrate = B200;
        break;
#endif
#ifdef B300

    case 300:
        baudrate = B300;
        break;
#endif
#ifdef B600

    case 600:
        baudrate = B600;
        break;
#endif
#ifdef B1200

    case 1200:
        baudrate = B1200;
        break;
#endif
#ifdef B1800

    case 1800:
        baudrate = B1800;
        break;
#endif
#ifdef B2400

    case 2400:
        baudrate = B2400;
        break;
#endif
#ifdef B4800

    case 4800:
        baudrate = B4800;
        break;
#endif
#ifdef B9600

    case 9600:
        baudrate = B9600;
        break;
#endif
#ifdef B19200

    case 19200:
        baudrate = B19200;
        break;
#endif
#ifdef B38400

    case 38400:
        baudrate = B38400;
        break;
#endif
#ifdef B57600

    case 57600:
        baudrate = B57600;
        break;
#endif
#ifdef B115200

    case 115200:
        baudrate = B115200;
        break;
#endif
#ifdef B230400

    case 230400:
        baudrate = B230400;
        break;
#endif
#ifdef B460800

    case 460800:
        baudrate = B460800;
        break;
#endif
#ifdef B500000

    case 500000:
        baudrate = B500000;
        break;
#endif
#ifdef B576000

    case 576000:
        baudrate = B576000;
        break;
#endif
#ifdef B921600

    case 921600:
        baudrate = B921600;
        break;
#endif
#ifdef B1000000

    case 1000000:
        baudrate = B1000000;
        break;
#endif
#ifdef B1152000

    case 1152000:
        baudrate = B1152000;
        break;
#endif
#ifdef B1500000

    case 1500000:
        baudrate = B1500000;
        break;
#endif
#ifdef B2000000

    case 2000000:
        baudrate = B2000000;
        break;
#endif
#ifdef B2500000

    case 2500000:
        baudrate = B2500000;
        break;
#endif
#ifdef B3000000

    case 3000000:
        baudrate = B3000000;
        break;
#endif
#ifdef B3500000

    case 3500000:
        baudrate = B3500000;
        break;
#endif
#ifdef B4000000

    case 4000000:
        baudrate = B4000000;
        break;
#endif

    default:
        baudrate = 0;
    }
    return baudrate;
}

SerialComm::SerialComm(const char* pDevice, int pBaudrate, PacketBuffer &pReadBuffer, PacketBuffer &pWriteBuffer, sharedControlInfo_t& pControl) : readBuffer(pReadBuffer), writeBuffer(pWriteBuffer), droppedReadPacketCount(0), droppedWritePacketCount(0), readPacketCount(0), writtenPacketCount(0), badPacketCount(0), sumRetries(0), device(pDevice), baudrate(pBaudrate), serialReadFD(-1), serialWriteFD(-1), errorReported(false), errorMsg(""), control(pControl)
{
    writerThreadRunning = false;
    readerThreadRunning = false;
    rawFifo.head = rawFifo.tail = 0;
    tcflag_t baudflag = parseBaudrate(pBaudrate);

    srand ( time(NULL) );
    seqno = rand();
    FD_ZERO(&rfds);
    FD_ZERO(&wfds);

    serialReadFD = open(device.c_str(), O_RDONLY | O_NOCTTY | O_NONBLOCK);
    serialWriteFD = open(device.c_str(), O_WRONLY | O_NOCTTY);

    if (((serialReadFD < 0) || (serialWriteFD < 0) || (!baudflag)) && !(errorReported == true))
    {
        ostringstream msg;
        msg << "could not open device = " << pDevice << " with baudrate = " << pBaudrate;
        reportError(msg.str().c_str() ,-1);
    }

    /* Serial port setting */
    struct termios newtio;
    memset(&newtio, 0, sizeof(newtio));
    newtio.c_cflag = CS8 | CLOCAL | CREAD;
    newtio.c_iflag = IGNPAR | IGNBRK;
    cfsetispeed(&newtio, baudflag);
    cfsetospeed(&newtio, baudflag);

    /* Raw output_file */
    newtio.c_oflag = 0;

    if ((tcflush(serialReadFD, TCIFLUSH) >= 0 && tcsetattr(serialReadFD, TCSANOW, &newtio) >= 0)
        && (tcflush(serialWriteFD, TCIFLUSH) >= 0 && tcsetattr(serialWriteFD, TCSANOW, &newtio) >= 0)
        && !errorReported)
    {
        DEBUG("SerialComm::SerialComm : opened device "<< pDevice << " with baudrate = " << pBaudrate)
            }
    else
    {
        close(serialReadFD);
        close(serialWriteFD);
        if (!errorReported)
        {
            ostringstream msg;
            msg << "could not set ioflags for opened device = " << pDevice;
            reportError(msg.str().c_str(),-1);
        }
    }

    pthread_mutex_init(&ack.lock, NULL);
    pthread_cond_init(&ack.received, NULL);

    if (!errorReported)
    {
        // start thread for reading from serial line
        if (reportError("SerialComm::SerialComm : pthread_create( &readerThread, NULL, readSerialThread, this)", pthread_create( &readerThread, NULL, readSerialThread, this)) == 0)
            readerThreadRunning = true;
        // start thread for writing to serial line
        if (reportError("SerialComm::SerialComm : pthread_create( &writerThread, NULL, writeSerialThread, this)", pthread_create( &writerThread, NULL, writeSerialThread, this)) == 0)
            writerThreadRunning = true;
    }
}


SerialComm::~SerialComm()
{
    cancel();

    pthread_mutex_destroy(&ack.lock);
    pthread_cond_destroy(&ack.received);

    if(serialReadFD > 2) close(serialReadFD);
    if(serialWriteFD > 2) close(serialWriteFD);
}

int SerialComm::hdlcEncode(int count, const char* from, char *to) {
    int offset = 0;
    for(int i = 0; i < count; i++) {
        if (from[i] == SYNC_BYTE || from[i] == ESCAPE_BYTE)
        {
            to[offset++] = ESCAPE_BYTE;
            to[offset++] = from[i] ^ 0x20;
        }
        else {
            to[offset++] = from[i];
        }
    }
    return offset;
}

int SerialComm::writeFD(int fd, const char *buffer, int count, int *err)
{
    int cnt = 0;
    /*
      FD_SET(serialWriteFD, &wfds);
      if(select(serialWriteFD + 1, NULL, &wfds, NULL, NULL) < 0) {
      return -1;
      }
      FD_CLR(serialWriteFD, &wfds);
    */
    int tmpCnt = BaseComm::writeFD(fd, buffer, count, err);
    if (tmpCnt < 0) {
        *err = errno;
        return tmpCnt;
    }
    else {
        cnt += tmpCnt;
    }
    return cnt;
}


/* Work around buggy usb serial driver (returns 0 when no data is
   available, independent of the blocking/non-blocking mode) */
int SerialComm::readFD(int fd, char *buffer, int count, int maxCount, int *err)
{
    int cnt = 0;
    timeval tvold;
    timeval tv;
    unsigned to = (10000000 / baudrate) * count; // time out in usec
    tvold.tv_sec = to / 1000000;
    tvold.tv_usec = to % 1000000;
    while (cnt == 0)
    {
        // no FD_ZERO here because of performance issues. It is done in constructor...
        FD_SET(serialReadFD, &rfds);
        if (select(serialReadFD + 1, &rfds, NULL, NULL, NULL) < 0) {
            return -1;
        }
        FD_CLR(serialReadFD, &rfds);
        tv = tvold;
        select(0, NULL, NULL, NULL, &tv);
        int tmpCnt = read(fd, buffer, maxCount);
        if (tmpCnt < 0) {
            *err = errno;
            return tmpCnt;
        }
        else {
            cnt += tmpCnt;
        }
    }
    return cnt;
}

char SerialComm::nextRaw() {
    char nextByte = 0;
    int err = 0;
    if(rawFifo.tail < rawFifo.head) {
        nextByte = rawFifo.queue[rawFifo.tail++];
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -