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

📄 tclwinserial.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 5 页
字号:
    int bufSize,                /* How much space is available                                 * in the buffer? */    int *errorCode)             /* Where to store error code. */{    SerialInfo *infoPtr = (SerialInfo *) instanceData;    DWORD bytesRead = 0;    COMSTAT cStat;    *errorCode = 0;    /*     * Check if there is a CommError pending from SerialCheckProc     */    if( infoPtr->error & SERIAL_READ_ERRORS ){        goto commError;    }    /*     * Look for characters already pending in windows queue.     * This is the mainly restored good old code from Tcl8.0     */    if( ClearCommError( infoPtr->handle, &infoPtr->error, &cStat ) ) {        /*         * Check for errors here, but not in the evSetup/Check procedures         */        if( infoPtr->error & SERIAL_READ_ERRORS ) {            goto commError;        }        if( infoPtr->flags & SERIAL_ASYNC ) {            /*             * NON_BLOCKING mode:             * Avoid blocking by reading more bytes than available             * in input buffer             */            if( cStat.cbInQue > 0 ) {                if( (DWORD) bufSize > cStat.cbInQue ) {                    bufSize = cStat.cbInQue;                }            } else {                errno = *errorCode = EAGAIN;                return -1;            }        } else {            /*             * BLOCKING mode:             * Tcl trys to read a full buffer of 4 kBytes here             */            if( cStat.cbInQue > 0 ) {                if( (DWORD) bufSize > cStat.cbInQue ) {                    bufSize = cStat.cbInQue;                }            } else {                bufSize = 1;            }        }    }    if( bufSize == 0 ) {        return bytesRead = 0;    }    /*    *  Perform blocking read. Doesn't block in non-blocking mode,     *  because we checked the number of available bytes.    */    if (blockingRead(infoPtr, (LPVOID) buf, (DWORD) bufSize, &bytesRead,            &infoPtr->osRead) == FALSE) {        goto error;    }    return bytesRead;error:    TclWinConvertError(GetLastError());    *errorCode = errno;    return -1;commError:    infoPtr->lastError = infoPtr->error;  /* save last error code */    infoPtr->error = 0;                   /* reset error code */    *errorCode = EIO;                     /* to return read-error only once */    return -1;}/* *---------------------------------------------------------------------- * * SerialOutputProc -- * *  Writes the given output on the IO channel. Returns count of how *  many characters were actually written, and an error indication. * * Results: *  A count of how many characters were written is returned and an *  error indication is returned in an output argument. * * Side effects: *  Writes output on the actual channel. * *---------------------------------------------------------------------- */static intSerialOutputProc(    ClientData instanceData,    /* Serial state. */    CONST char *buf,            /* The data buffer. */    int toWrite,                /* How many bytes to write? */    int *errorCode)             /* Where to store error code. */{    SerialInfo *infoPtr = (SerialInfo *) instanceData;    int bytesWritten, timeout;    *errorCode = 0;    /*     * At EXIT Tcl trys to flush all open channels in blocking mode.     * We avoid blocking output after ExitProc or CloseHandler(chan)     * has been called by checking the corrresponding variables.     */    if( ! initialized || TclInExit() ) {        return toWrite;    }    /*     * Check if there is a CommError pending from SerialCheckProc     */    if( infoPtr->error & SERIAL_WRITE_ERRORS ){        infoPtr->lastError = infoPtr->error;  /* save last error code */        infoPtr->error = 0;                   /* reset error code */        errno = EIO;                    goto error;    }    timeout = (infoPtr->flags & SERIAL_ASYNC) ? 0 : INFINITE;    if (WaitForSingleObject(infoPtr->evWritable, timeout) == WAIT_TIMEOUT) {        /*         * The writer thread is blocked waiting for a write to complete         * and the channel is in non-blocking mode.         */        errno = EWOULDBLOCK;        goto error1;    }    /*     * Check for a background error on the last write.     */    if (infoPtr->writeError) {        TclWinConvertError(infoPtr->writeError);        infoPtr->writeError = 0;        goto error1;    }    /*     * Remember the number of bytes in output queue     */    EnterCriticalSection(&infoPtr->csWrite);    infoPtr->writeQueue += toWrite;    LeaveCriticalSection(&infoPtr->csWrite);    if (infoPtr->flags & SERIAL_ASYNC) {        /*         * The serial is non-blocking, so copy the data into the output         * buffer and restart the writer thread.         */        if (toWrite > infoPtr->writeBufLen) {            /*             * Reallocate the buffer to be large enough to hold the data.             */            if (infoPtr->writeBuf) {                ckfree(infoPtr->writeBuf);            }            infoPtr->writeBufLen = toWrite;            infoPtr->writeBuf = ckalloc(toWrite);        }        memcpy(infoPtr->writeBuf, buf, toWrite);        infoPtr->toWrite = toWrite;        ResetEvent(infoPtr->evWritable);        SetEvent(infoPtr->evStartWriter);        bytesWritten = toWrite;    } else {        /*        * In the blocking case, just try to write the buffer directly.        * This avoids an unnecessary copy.        */        if (! blockingWrite(infoPtr, (LPVOID) buf, (DWORD) toWrite,                &bytesWritten, &infoPtr->osWrite) ) {            goto writeError;        }        if (bytesWritten != toWrite) {            /* Write timeout */            infoPtr->lastError |= CE_PTO;            errno = EIO;            goto error;        }    }    return bytesWritten;writeError:    TclWinConvertError(GetLastError());error:    /*      * Reset the output queue counter on error during blocking output      *//*    EnterCriticalSection(&infoPtr->csWrite);    infoPtr->writeQueue = 0;    LeaveCriticalSection(&infoPtr->csWrite);*/  error1:     *errorCode = errno;    return -1;}/* *---------------------------------------------------------------------- * * SerialEventProc -- * *  This function is invoked by Tcl_ServiceEvent when a file event *  reaches the front of the event queue.  This procedure invokes *  Tcl_NotifyChannel on the serial. * * Results: *  Returns 1 if the event was handled, meaning it should be removed *  from the queue.  Returns 0 if the event was not handled, meaning *  it should stay on the queue.  The only time the event isn't *  handled is if the TCL_FILE_EVENTS flag bit isn't set. * * Side effects: *  Whatever the notifier callback does. * *---------------------------------------------------------------------- */static intSerialEventProc(    Tcl_Event *evPtr,   /* Event to service. */    int flags)          /* Flags that indicate what events to                         * handle, such as TCL_FILE_EVENTS. */{    SerialEvent *serialEvPtr = (SerialEvent *)evPtr;    SerialInfo *infoPtr;    int mask;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {        return 0;    }    /*     * Search through the list of watched serials for the one whose handle     * matches the event.  We do this rather than simply dereferencing     * the handle in the event so that serials can be deleted while the     * event is in the queue.     */    for (infoPtr = tsdPtr->firstSerialPtr; infoPtr != NULL;            infoPtr = infoPtr->nextPtr) {        if (serialEvPtr->infoPtr == infoPtr) {            infoPtr->flags &= ~(SERIAL_PENDING);            break;        }    }    /*     * Remove stale events.     */    if (!infoPtr) {        return 1;    }    /*     * Check to see if the serial is readable.  Note     * that we can't tell if a serial is writable, so we always report it     * as being writable unless we have detected EOF.     */    mask = 0;    if( infoPtr->watchMask & TCL_WRITABLE ) {        if( infoPtr->writable ) {            mask |= TCL_WRITABLE;            infoPtr->writable = 0;        }    }    if( infoPtr->watchMask & TCL_READABLE ) {        if( infoPtr->readable ) {            mask |= TCL_READABLE;            infoPtr->readable = 0;        }    }    /*     * Inform the channel of the events.     */    Tcl_NotifyChannel(infoPtr->channel, infoPtr->watchMask & mask);    return 1;}/* *---------------------------------------------------------------------- * * SerialWatchProc -- * *  Called by the notifier to set up to watch for events on this *  channel. * * Results: *  None. * * Side effects: *  None. * *---------------------------------------------------------------------- */static voidSerialWatchProc(    ClientData instanceData,     /* Serial state. */    int mask)                    /* What events to watch for, OR-ed                                  * combination of TCL_READABLE,                                  * TCL_WRITABLE and TCL_EXCEPTION. */{    SerialInfo **nextPtrPtr, *ptr;    SerialInfo *infoPtr = (SerialInfo *) instanceData;    int oldMask = infoPtr->watchMask;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    /*     * Since the file is always ready for events, we set the block time     * so we will poll.     */    infoPtr->watchMask = mask & infoPtr->validMask;    if (infoPtr->watchMask) {        if (!oldMask) {            infoPtr->nextPtr = tsdPtr->firstSerialPtr;            tsdPtr->firstSerialPtr = infoPtr;        }        SerialBlockTime(infoPtr->blockTime);    } else {        if (oldMask) {            /*             * Remove the serial port from the list of watched serial ports.             */            for (nextPtrPtr = &(tsdPtr->firstSerialPtr), ptr = *nextPtrPtr;                    ptr != NULL;                    nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) {                if (infoPtr == ptr) {                    *nextPtrPtr = ptr->nextPtr;                    break;                }            }        }    }}/* *---------------------------------------------------------------------- * * SerialGetHandleProc -- * *  Called from Tcl_GetChannelHandle to retrieve OS handles from *  inside a command serial port based channel. * * Results: *  Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if *  there is no handle for the specified direction. * * Side effects: *  None. * *---------------------------------------------------------------------- */static intSerialGetHandleProc(    ClientData instanceData,    /* The serial state. */    int direction,              /* TCL_READABLE or TCL_WRITABLE */    ClientData *handlePtr)      /* Where to store the handle.  */{    SerialInfo *infoPtr = (SerialInfo *) instanceData;    *handlePtr = (ClientData) infoPtr->handle;    return TCL_OK;}/* *---------------------------------------------------------------------- * * SerialWriterThread -- * *      This function runs in a separate thread and writes data *      onto a serial. * * Results: *      Always returns 0. * * Side effects: *      Signals the main thread when an output operation is completed. *      May cause the main thread to wake up by posting a message.  

⌨️ 快捷键说明

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