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

📄 comport.c

📁 Open DMT Client C Source code
💻 C
📖 第 1 页 / 共 5 页
字号:
    FD_ZERO(&rfds);    FD_SET(com->read_fd, &rfds);    tv.tv_sec  = timeoutMS / 1000L;    tv.tv_usec = (timeoutMS % 1000L) * 1000L;    select(com->read_fd + 1, &rfds, 0, 0, &tv);    if (!FD_ISSET(com->read_fd, &rfds)) { return 0; } // timeout    /* return number of available bytes */    // since the above did not timeout, we will have at least 1 byte available.#ifdef BYTES_AVAIL_IOCTL    int nBytesAvail;    int request = BYTES_AVAIL_IOCTIL_REQUEST;    int status = ioctl(com->read_fd, request, &nBytesAvail);    return (status >= 0)? nBytesAvail : 1;#else    return 1;#endif            }#endif // defined(TARGET_WINCE)// ----------------------------------------------------------------------------/* read specified number of bytes from ComPort */#if defined(TARGET_WINCE)// not yet implemented#else#define MAX_VTIME_MS   25500Lint comPortRead(ComPort_t *com, UInt8 *buf, int len, long timeoutMS){    // Possible (non-exclusive) 'errno' values:    //   EIO    [ 5]  input/output error    //   ENODEV [19]  no such device    //   ETIME  [63]  timeout        /* read nothing? */    if (len <= 0) {        logINFO(LOGSRC,"Empty read buffer");        return 0;    }         /* valid com port? */    if (!comPortIsOpen(com)) {        if (buf) { buf[0] = 0; }        errno = ENODEV;        logINFO(LOGSRC,"ComPort not open");        return -1;    }    /* starting timestamp */    struct timeval startTime;    utcGetTimestamp(&startTime);    /* read bytes */    int n = 0;    for (;n < len;) {                /* timeout? */        long tms = timeoutMS;        if (tms >= 0L) {            tms -= utcGetDeltaMillis(0, &startTime); // subtract elapsed time            if ((tms <= 0L) && (com->push <= 0) && (com->avail <= 0)) { // timeout                if (buf) { buf[n] = 0; }                errno = ETIME; // not necessary, since we're returning a value >= 0                com->error = COMERR_TIMEOUT;                return n;            }        }        /* poll/read */        if (com->push > 0) {                        /* use previously pushed char */            com->last = (UInt8)com->push;            com->push = -1; // clear push            if (buf) { buf[n] = com->last; }            n++;                    } else {                        /* poll (check for available data) */            //logDEBUG(LOGSRC,FTN, "avail=%d, tms=%ld", com->avail, tms);            if ((com->avail <= 0) && (tms > 0L)) {                if (COMOPT_IsVTimeout(com)) {                    // Note: 'tms' will be rounded up to the next highest 100ms, and                    // will be clipped at 25500 ms (max value for VTIME).                    if (!_comPortSetVtimeMS(com, tms)) {                        // ENODEV/EIO is likely here (for 'rfcomm0')                        int sv_errno = errno;                        logWARNING(LOGSRC,"ComPort error %s : [%d] %s", com->dev, sv_errno, strerror(sv_errno));                        if (buf) { buf[n] = 0; }                        errno = sv_errno;                        return -1;                    }                } else {                    // wait for available data                    int avail = comPortGetAvail(com, tms);                    if (avail <= 0) {                        // timeout/error                        if (buf) { buf[n] = 0; }                        errno = ETIME;                        com->error = COMERR_TIMEOUT; // may be EOF                        return n;                    }                    com->avail = avail;                }            } else {                if (COMOPT_IsVTimeout(com)) {                    // Either data is available for reading (without blocking), or the                    // caller wishes this function to block forever (ie. no timeout)                    // However, set a minimum timeout anyway to allow us to keep track                    // of when the port is closed (externally). We'll still not return                    // until the number of requested bytes have been read.                    if (!_comPortSetVtimeMS(com, MAX_VTIME_MS)) {                        // ENODEV/EIO is likely here (for 'rfcomm0')                        int sv_errno = errno;                        logWARNING(LOGSRC,"ComPort error %s : [%d] %s", com->dev, sv_errno, strerror(sv_errno));                        if (buf) { buf[n] = 0; }                        errno = sv_errno;                        return -1;                    }                } else {                    //logDEBUG(LOGSRC,FTN, "blocking wait (avail = %d)", com->avail);                }            }                        /* read 1 byte */            // Either ...            // - VTIME is in effect and we'll possibly be timing out, or            // - a character available (avail > 0) and it will be returned, or            // - we will be blocking here until a character becomes available, or            // - we will get an error.            struct timeval readTS;            utcGetTimestamp(&readTS);            errno = 0; // clear 'errno'            int r = read(com->read_fd, &com->last, 1); // VTIME may be in effect            if (r < 0) {                // error: com port closed?                if (buf) { buf[n] = 0; } // terminate buffer                com->avail = 0;                com->error = COMERR_EOF;                // error already in 'errno'                logWARNING(LOGSRC,"ComPort error %s : [%d] %s", com->dev, com->error, strerror(com->error));                return -1;            } else            if (r == 0) {                // A read length of 0 can mean an EOF, or a TIMEOUT if VTIME is in effect.                //int readErrno = errno;                //logDEBUG(LOGSRC,"Read EOF/TIMEOUT? %s: [%d]%s", com->dev, readErrno, strerror(readErrno));                com->avail = 0; // in any case nothing is available                if (COMOPT_IsVTimeout(com)) {                    long vtimeMS = _comPortGetVtimeMS(com);                    long deltaMS = utcGetDeltaMillis(0, &readTS) + 50L; // allow 50ms window                    // Allow a margin on the timeout window when checking for EOF.                    // If the elapsed time is less than what the timeout was set for, then                    // an EOF is likely, but lets be sure of it by setting a wide enough                    // time window.  The worst case is that the EOF occurred close enough                    // to the expired timeout that we may try to read of a closed file                    // descriptor again.  Hopefully, however, the next time around we will                    // again get an EOF error right away and return accordingly.                    if (deltaMS < vtimeMS) {                        // this means that we were interrupted before timeout occured, EOF likely.                        //logDEBUG(LOGSRC,"VTIME (%ld<%ld) ... [%s]", deltaMS, vtimeMS, com->dev);                        if (buf) { buf[n] = 0; }                        com->error = COMERR_EOF;                        errno = ENODEV;                        return -1;                    } else {                        // assume timeout, continue loop                    }                } else {                    // assume an EOF                    if (buf) { buf[n] = 0; }                    com->error = COMERR_EOF;                    errno = ENODEV;                    logWARNING(LOGSRC,"ComPort error %s (EOF?) : [%d] %s", com->dev, com->error, strerror(com->error));                    return -1;                }            } else            if (r == 1) {                if (buf) { buf[n] = com->last; }                n++;                if (com->avail > 0) { com->avail--; } // decrement available                if (COMOPT_IsEcho(com)) {                    // perform the following iff ECHO is on                    if (com->last == KEY_RETURN) {                        // follow CR with LF                        comPortWrite(com, "\r\n", 2);                    } else                    if (KEY_IsBackspace(com->last) && COMOPT_IsBackspace(com)) {                        // single character backspace                        comPortWrite(com, "\b \b", 3);                    } else                    if ((com->last == KEY_CONTROL_D) && COMOPT_IsBackspace(com)) {                        // backspace over all that we've just entered                        for (; n > 1; n--) { comPortWrite(com, "\b \b", 3); }                        if (buf) { buf[0] = com->last; }                        n = 1;                    } else                    if (com->last == KEY_ESCAPE) {                        if (!COMOPT_IgnoreEscape(com)) {                            // echo escape character                            comPortWrite(com, &com->last, 1);                        }                    } else {                        // echo simple character                        comPortWrite(com, &com->last, 1);                    }                }                if (COMOPT_IsLogDebug(com) && com->logger) {                     (*com->logger)(&com->last,1);                 }            }                    }           }        // 'len' bytes read    return n;}#endif // defined(TARGET_WINCE)/* read single character */#if defined(TARGET_WINCE)int comPortReadChar(ComPort_t *com, long timeoutMS){    // currently, 'timeoutMS' is ignored    if (com) {        if (com->push >= 0) {            int ch = com->push;            com->push = -1;            return ch;        } else {            DWORD readCnt;            unsigned char ch;            BOOL ok = ReadFile(com->portId, &ch, 1, &readCnt, NULL);            if (!ok) {                // error/timeout?                errno = GetLastError();                com->error = COMERR_EOF;                logERROR(LOGSRC,"ReadFile error[timeout?]: %d", errno);                return -1;            } else            if (readCnt != 1) {                // eof/timeout?                errno = GetLastError(); // will probably always be ERROR_SUCCESS                if (errno == ERROR_SUCCESS) {                    // assume timeout                    com->error = COMERR_TIMEOUT;                    return -1;                } else                if (errno == ERROR_INVALID_PARAMETER) {                    logWARNING(LOGSRC,"ReadFile error[ERROR_INVALID_PARAMETER]: %d", errno);                    com->error = COMERR_GENERAL;                    return -1;                } else {                    // assume eof                    logWARNING(LOGSRC,"ReadFile error: %d", errno);                    com->error = COMERR_EOF;                    return -1;                }            } else {                return (int)ch & 0xFF;            }        }    } else {        return -1;    }}#else// Use of this function is discouraged because examination of 'errno' is// required to differentiate between an EOF and TIMEOUT.int comPortReadChar(ComPort_t *com, long timeoutMS){    UInt8 ch;    int len = comPortRead(com, &ch, 1, timeoutMS);    if (len < 0) {        // error (error in 'errno')        return -1;    } else    if (len == 0) {        // timeout        errno = ETIME;        return -1;    } else {        return (int)ch;    }}#endif // defined(TARGET_WINCE)/* read a single byte (return '0' if error) */UInt8 comPortGetByte(ComPort_t *com, long timeoutMS){    int ch = comPortReadChar(com, timeoutMS);    return (ch < 0)? 0 : (UInt8)ch;}// ----------------------------------------------------------------------------/* read bytes from ComPort until '\n', '\r', or until 'maxLen' reached */#if defined(TARGET_WINCE)int comPortReadLine(ComPort_t *com, char *buf, int maxLen, long timeoutMS){    if (maxLen <= 0) {        return 0;    } else    if (comPortIsOpen(com)) {        int i;        errno = ERROR_SUCCESS;        com->error = COMERR_NONE;        for (i = 0; i < (maxLen - 1);) {            DWORD readCnt;            char ch = 0;            BOOL ok;            if (com->push >= 0) {                ch = (char)com->push;                com->push = -1;                readCnt = 1;                ok = TRUE;            } else {                ok = ReadFile(com->portId, &ch, 1, &readCnt, NULL);            }            if (!ok) {                // error/timeout?                errno = GetLastError();                com->error = COMERR_EOF;                logERROR(LOGSRC,"ReadFile error(timeout?): %d", errno);                if (buf) { buf[i] = 0; }                return -1;            } else            if (readCnt == 1) {                ch &= 0x7F; // mask to ASCII                //*DEBUG*/fprintf(stderr, "%c", (char)ch); // logging: ignore returned error code                if ((ch == '\n') || (ch == '\r')) {                    if (i > 0) {                        if (buf) { buf[i] = 0; }                        return i;                    } else {                        // The buffer is curently empty                        // just ignore this character and continue                    }                } else                if (ch > ' ') {                    if (buf) { buf[i] = ch; }                    i++;                } else                if (ch == ' ') {                    // special handling for spaces?                    if (buf) { buf[i] = ch; }                    i++;                } else {                    // everything else is ignore for readLine                }            } else {                // eof/timeout?                if (buf) { buf[i] = 0; }                errno = GetLastError(); // will probably always be ERROR_SUCCESS                if (errno == ERROR_SUCCESS) {                    // assume timeout                    com->error = COMERR_TIMEOUT;                    return 0;                } else {                    // assume eof                    logWARNING(LOGSRC,"ReadFile error: %d", errno);                    com->error = COMERR_EOF;                    return -1;                }            }        }        // should not reach here        if (buf) { buf[maxLen - 1] = 0; }        return maxLen - 1;    } else {        if (buf) { buf[0] = 0; }        com->error = COMERR_GENERAL;        return -1;    }}#elseint comPortReadLine(ComPort_t *com, char *buf, int maxLen, long timeoutMS){    return _comPortReadLine(com, buf, 0, maxLen, timeoutMS);}#endif // defined(TARGET_WINCE)#if defined(TARGET_WINCE)// not sup

⌨️ 快捷键说明

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