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

📄 tclwinserial.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 5 页
字号:
        }    }    if (!block) {        SerialBlockTime(msec);    }}/* *---------------------------------------------------------------------- * * SerialCheckProc -- * *  This procedure is called by Tcl_DoOneEvent to check the serial *  event source for events. * * Results: *  None. * * Side effects: *  May queue an event. * *---------------------------------------------------------------------- */static voidSerialCheckProc(    ClientData data,    /* Not used. */    int flags)          /* Event flags as passed to Tcl_DoOneEvent. */{    SerialInfo *infoPtr;    SerialEvent *evPtr;    int needEvent;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    COMSTAT cStat;    unsigned int time;    if (!(flags & TCL_FILE_EVENTS)) {        return;    }    /*     * Queue events for any ready serials that don't already have events     * queued.     */    for (infoPtr = tsdPtr->firstSerialPtr; infoPtr != NULL;            infoPtr = infoPtr->nextPtr) {        if (infoPtr->flags & SERIAL_PENDING) {            continue;        }        needEvent = 0;        /*         * If WRITABLE watch mask is set         * look for infoPtr->evWritable object         */        if (infoPtr->watchMask & TCL_WRITABLE) {            if (WaitForSingleObject(infoPtr->evWritable, 0) != WAIT_TIMEOUT) {                infoPtr->writable = 1;                needEvent = 1;            }        }                /*         * If READABLE watch mask is set         * call ClearCommError to poll cbInQue         * Window errors are ignored here         */        if( infoPtr->watchMask & TCL_READABLE ) {            if( ClearCommError( infoPtr->handle, &infoPtr->error, &cStat ) ) {                /*                 * Look for characters already pending in windows queue.                 * If they are, poll.                 */                if( infoPtr->watchMask & TCL_READABLE ) {                    /*                     * force fileevent after serial read error                     */                    if( (cStat.cbInQue > 0) ||                            (infoPtr->error & SERIAL_READ_ERRORS) ) {                        infoPtr->readable = 1;			time = SerialGetMilliseconds();			if ((unsigned int) (time - infoPtr->lastEventTime)				>= (unsigned int) infoPtr->blockTime) {			    needEvent = 1;			    infoPtr->lastEventTime = time;			}                    }                }            }        }        /*         * Queue an event if the serial is signaled for reading or writing.         */        if (needEvent) {            infoPtr->flags |= SERIAL_PENDING;            evPtr = (SerialEvent *) ckalloc(sizeof(SerialEvent));            evPtr->header.proc = SerialEventProc;            evPtr->infoPtr = infoPtr;            Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);        }    }}/* *---------------------------------------------------------------------- * * SerialBlockProc -- * *  Set blocking or non-blocking mode on channel. * * Results: *  0 if successful, errno when failed. * * Side effects: *  Sets the device into blocking or non-blocking mode. * *---------------------------------------------------------------------- */static intSerialBlockProc(    ClientData instanceData,    /* Instance data for channel. */    int mode)                   /* TCL_MODE_BLOCKING or                                 * TCL_MODE_NONBLOCKING. */{    int errorCode = 0;    SerialInfo *infoPtr = (SerialInfo *) instanceData;    /*     * Only serial READ can be switched between blocking & nonblocking     * using COMMTIMEOUTS.     * Serial write emulates blocking & nonblocking by the SerialWriterThread.     */    if (mode == TCL_MODE_NONBLOCKING) {        infoPtr->flags |= SERIAL_ASYNC;    } else {        infoPtr->flags &= ~(SERIAL_ASYNC);    }    return errorCode;}/* *---------------------------------------------------------------------- * * SerialCloseProc -- * *  Closes a serial based IO channel. * * Results: *  0 on success, errno otherwise. * * Side effects: *  Closes the physical channel. * *---------------------------------------------------------------------- */static intSerialCloseProc(    ClientData instanceData,    /* Pointer to SerialInfo structure. */    Tcl_Interp *interp)         /* For error reporting. */{    SerialInfo *serialPtr = (SerialInfo *) instanceData;    int errorCode, result = 0;    SerialInfo *infoPtr, **nextPtrPtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    errorCode = 0;    if (serialPtr->validMask & TCL_READABLE) {        PurgeComm(serialPtr->handle, PURGE_RXABORT | PURGE_RXCLEAR);        CloseHandle(serialPtr->osRead.hEvent);    }    serialPtr->validMask &= ~TCL_READABLE;     if (serialPtr->validMask & TCL_WRITABLE) {        /*         * Generally we cannot wait for a pending write operation         * because it may hang due to handshake         *    WaitForSingleObject(serialPtr->evWritable, INFINITE);         */         /*         * Forcibly terminate the background thread.  We cannot rely on the         * thread to cleanly terminate itself because we have no way of         * closing the handle without blocking in the case where the         * thread is in the middle of an I/O operation.  Note that we need         * to guard against terminating the thread while it is in the         * middle of Tcl_ThreadAlert because it won't be able to release         * the notifier lock.         */        Tcl_MutexLock(&serialMutex);        TerminateThread(serialPtr->writeThread, 0);        Tcl_MutexUnlock(&serialMutex);        /*         * Wait for the thread to terminate.  This ensures that we are         * completely cleaned up before we leave this function.          */        WaitForSingleObject(serialPtr->writeThread, INFINITE);        CloseHandle(serialPtr->writeThread);        CloseHandle(serialPtr->evWritable);        CloseHandle(serialPtr->evStartWriter);        serialPtr->writeThread = NULL;        PurgeComm(serialPtr->handle, PURGE_TXABORT | PURGE_TXCLEAR);    }    serialPtr->validMask &= ~TCL_WRITABLE;    /*     * Don't close the Win32 handle if the handle is a standard channel     * during the exit process.  Otherwise, one thread may kill the stdio     * of another.     */    if (!TclInExit()        || ((GetStdHandle(STD_INPUT_HANDLE) != serialPtr->handle)        && (GetStdHandle(STD_OUTPUT_HANDLE) != serialPtr->handle)        && (GetStdHandle(STD_ERROR_HANDLE) != serialPtr->handle))) {           if (CloseHandle(serialPtr->handle) == FALSE) {                TclWinConvertError(GetLastError());                errorCode = errno;            }    }    serialPtr->watchMask &= serialPtr->validMask;    /*     * Remove the file from the list of watched files.     */    for (nextPtrPtr = &(tsdPtr->firstSerialPtr), infoPtr = *nextPtrPtr;            infoPtr != NULL;                    nextPtrPtr = &infoPtr->nextPtr, infoPtr = *nextPtrPtr) {        if (infoPtr == (SerialInfo *)serialPtr) {            *nextPtrPtr = infoPtr->nextPtr;            break;        }    }    /*     * Wrap the error file into a channel and give it to the cleanup     * routine.     */    if (serialPtr->writeBuf != NULL) {        ckfree(serialPtr->writeBuf);        serialPtr->writeBuf = NULL;    }    ckfree((char*) serialPtr);    if (errorCode == 0) {        return result;    }    return errorCode;}/* *---------------------------------------------------------------------- * * blockingRead -- * *  Perform a blocking read into the buffer given. Returns *  count of how many bytes were actually read, and an error indication. * * Results: *  A count of how many bytes were read is returned and an error *  indication is returned. * * Side effects: *  Reads input from the actual channel. * *---------------------------------------------------------------------- */static intblockingRead(     SerialInfo *infoPtr,    /* Serial info structure */    LPVOID buf,             /* The input buffer pointer */    DWORD  bufSize,         /* The number of bytes to read */    LPDWORD  lpRead,        /* Returns number of bytes read */     LPOVERLAPPED osPtr )    /* OVERLAPPED structure */{    /*    *  Perform overlapped blocking read.     *  1. Reset the overlapped event    *  2. Start overlapped read operation    *  3. Wait for completion    */	/* 	* Set Offset to ZERO, otherwise NT4.0 may report an error 	*/	osPtr->Offset = osPtr->OffsetHigh = 0;    ResetEvent(osPtr->hEvent);    if (! ReadFile(infoPtr->handle, buf, bufSize, lpRead, osPtr) ) {        if (GetLastError() != ERROR_IO_PENDING) {            /* ReadFile failed, but it isn't delayed. Report error */            return FALSE;        } else {               /* Read is pending, wait for completion, timeout ? */            if (! GetOverlappedResult(infoPtr->handle, osPtr, lpRead, TRUE) ) {                return FALSE;            }        }    } else {        /* ReadFile completed immediately. */    }    return TRUE;}/* *---------------------------------------------------------------------- * * blockingWrite -- * *  Perform a blocking write from the buffer given. Returns *  count of how many bytes were actually written, and an error indication. * * Results: *  A count of how many bytes were written is returned and an error *  indication is returned. * * Side effects: *  Writes output to the actual channel. * *---------------------------------------------------------------------- */static intblockingWrite(    SerialInfo *infoPtr,    /* Serial info structure */    LPVOID  buf,            /* The output buffer pointer */    DWORD   bufSize,        /* The number of bytes to write */    LPDWORD lpWritten,      /* Returns number of bytes written */     LPOVERLAPPED osPtr )    /* OVERLAPPED structure */{    int result;    /*    *  Perform overlapped blocking write.     *  1. Reset the overlapped event    *  2. Remove these bytes from the output queue counter    *  3. Start overlapped write operation    *  3. Remove these bytes from the output queue counter    *  4. Wait for completion    *  5. Adjust the output queue counter    */    ResetEvent(osPtr->hEvent);    EnterCriticalSection(&infoPtr->csWrite);    infoPtr->writeQueue -= bufSize;	/* 	* Set Offset to ZERO, otherwise NT4.0 may report an error 	*/	osPtr->Offset = osPtr->OffsetHigh = 0;    result = WriteFile(infoPtr->handle, buf, bufSize, lpWritten, osPtr);    LeaveCriticalSection(&infoPtr->csWrite);    if (result == FALSE ) {        int err = GetLastError();        switch (err) {        case ERROR_IO_PENDING:            /* Write is pending, wait for completion */            if (! GetOverlappedResult(infoPtr->handle, osPtr, lpWritten, TRUE) ) {                return FALSE;            }            break;        case ERROR_COUNTER_TIMEOUT:            /* Write timeout handled in SerialOutputProc */            break;        default:            /* WriteFile failed, but it isn't delayed. Report error */            return FALSE;        }    } else {        /* WriteFile completed immediately. */    }    EnterCriticalSection(&infoPtr->csWrite);    infoPtr->writeQueue += (*lpWritten - bufSize);    LeaveCriticalSection(&infoPtr->csWrite);    return TRUE;}/* *---------------------------------------------------------------------- * * SerialInputProc -- * *  Reads input from the IO channel into the buffer given. Returns *  count of how many bytes were actually read, and an error indication. * * Results: *  A count of how many bytes were read is returned and an error *  indication is returned in an output argument. * * Side effects: *  Reads input from the actual channel. * *---------------------------------------------------------------------- */static intSerialInputProc(    ClientData instanceData,    /* Serial state. */    char *buf,                  /* Where to store data read. */

⌨️ 快捷键说明

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