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

📄 tclwinserial.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * tclWinSerial.c -- * *  This file implements the Windows-specific serial port functions, *  and the "serial" channel driver. * * Copyright (c) 1999 by Scriptics Corp. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Serial functionality implemented by Rolf.Schroedter@dlr.de * * RCS: @(#) $Id: tclWinSerial.c,v 1.21 2002/07/19 13:59:10 dkf Exp $ */#include "tclWinInt.h"#include <fcntl.h>#include <io.h>#include <sys/stat.h>/* * The following variable is used to tell whether this module has been * initialized. */static int initialized = 0;/* * The serialMutex locks around access to the initialized variable, and it is * used to protect background threads from being terminated while they are * using APIs that hold locks. */TCL_DECLARE_MUTEX(serialMutex)/* * Bit masks used in the flags field of the SerialInfo structure below. */#define SERIAL_PENDING  (1<<0)  /* Message is pending in the queue. */#define SERIAL_ASYNC    (1<<1)  /* Channel is non-blocking. *//* * Bit masks used in the sharedFlags field of the SerialInfo structure below. */#define SERIAL_EOF      (1<<2)  /* Serial has reached EOF. */#define SERIAL_ERROR    (1<<4)/* * Default time to block between checking status on the serial port. */#define SERIAL_DEFAULT_BLOCKTIME    10  /* 10 msec *//* * Define Win32 read/write error masks returned by ClearCommError() */#define SERIAL_READ_ERRORS      ( CE_RXOVER | CE_OVERRUN | CE_RXPARITY \                                | CE_FRAME  | CE_BREAK )#define SERIAL_WRITE_ERRORS     ( CE_TXFULL | CE_PTO )/* * This structure describes per-instance data for a serial based channel. */typedef struct SerialInfo {    HANDLE handle;    struct SerialInfo *nextPtr; /* Pointer to next registered serial. */    Tcl_Channel channel;        /* Pointer to channel structure. */    int validMask;              /* OR'ed combination of TCL_READABLE,                                 * TCL_WRITABLE, or TCL_EXCEPTION: indicates                                 * which operations are valid on the file. */    int watchMask;              /* OR'ed combination of TCL_READABLE,                                 * TCL_WRITABLE, or TCL_EXCEPTION: indicates                                 * which events should be reported. */    int flags;                  /* State flags, see above for a list. */    int readable;               /* flag that the channel is readable */    int writable;               /* flag that the channel is writable */    int blockTime;              /* max. blocktime in msec */    unsigned int lastEventTime;	/* Time in milliseconds since last readable event */				/* Next readable event only after blockTime */    DWORD error;                /* pending error code returned by                                 * ClearCommError() */    DWORD lastError;            /* last error code, can be fetched with                                 * fconfigure chan -lasterror */    DWORD sysBufRead;           /* Win32 system buffer size for read ops,                                  * default=4096 */    DWORD sysBufWrite;          /* Win32 system buffer size for write ops,                                  * default=4096 */    Tcl_ThreadId threadId;      /* Thread to which events should be reported.                                 * This value is used by the reader/writer                                 * threads. */    OVERLAPPED osRead;          /* OVERLAPPED structure for read operations */    OVERLAPPED osWrite;         /* OVERLAPPED structure for write operations */    HANDLE writeThread;         /* Handle to writer thread. */    CRITICAL_SECTION csWrite;   /* Writer thread synchronisation */    HANDLE evWritable;          /* Manual-reset event to signal when the                                 * writer thread has finished waiting for                                 * the current buffer to be written. */    HANDLE evStartWriter;       /* Auto-reset event used by the main thread to                                 * signal when the writer thread should attempt                                 * to write to the serial. */    DWORD writeError;           /* An error caused by the last background                                 * write.  Set to 0 if no error has been                                 * detected.  This word is shared with the                                 * writer thread so access must be                                 * synchronized with the evWritable object.                                 */    char *writeBuf;             /* Current background output buffer.                                 * Access is synchronized with the evWritable                                 * object. */    int writeBufLen;            /* Size of write buffer.  Access is                                 * synchronized with the evWritable                                 * object. */    int toWrite;                /* Current amount to be written.  Access is                                 * synchronized with the evWritable object. */    int writeQueue;             /* Number of bytes pending in output queue.                                 * Offset to DCB.cbInQue.                                 * Used to query [fconfigure -queue] */} SerialInfo;typedef struct ThreadSpecificData {    /*     * The following pointer refers to the head of the list of serials     * that are being watched for file events.     */    SerialInfo *firstSerialPtr;} ThreadSpecificData;static Tcl_ThreadDataKey dataKey;/* * The following structure is what is added to the Tcl event queue when * serial events are generated. */typedef struct SerialEvent {    Tcl_Event header;       /* Information that is standard for                             * all events. */    SerialInfo *infoPtr;    /* Pointer to serial info structure.  Note                             * that we still have to verify that the                             * serial exists before dereferencing this                             * pointer. */} SerialEvent;/* * We don't use timeouts. */static COMMTIMEOUTS no_timeout = {    0,               /* ReadIntervalTimeout */    0,               /* ReadTotalTimeoutMultiplier */    0,               /* ReadTotalTimeoutConstant */    0,               /* WriteTotalTimeoutMultiplier */    0,               /* WriteTotalTimeoutConstant */};/* * Declarations for functions used only in this file. */static int      SerialBlockProc(ClientData instanceData, int mode);static void     SerialCheckProc(ClientData clientData, int flags);static int      SerialCloseProc(ClientData instanceData,                Tcl_Interp *interp);static int      SerialEventProc(Tcl_Event *evPtr, int flags);static void     SerialExitHandler(ClientData clientData);static int      SerialGetHandleProc(ClientData instanceData,                int direction, ClientData *handlePtr);static ThreadSpecificData *SerialInit(void);static int      SerialInputProc(ClientData instanceData, char *buf,                int toRead, int *errorCode);static int      SerialOutputProc(ClientData instanceData, CONST char *buf,                int toWrite, int *errorCode);static void     SerialSetupProc(ClientData clientData, int flags);static void     SerialWatchProc(ClientData instanceData, int mask);static void     ProcExitHandler(ClientData clientData);static int       SerialGetOptionProc _ANSI_ARGS_((ClientData instanceData,                Tcl_Interp *interp, CONST char *optionName,                Tcl_DString *dsPtr));static int       SerialSetOptionProc _ANSI_ARGS_((ClientData instanceData,                Tcl_Interp *interp, CONST char *optionName,                CONST char *value));static DWORD WINAPI     SerialWriterThread(LPVOID arg);/* * This structure describes the channel type structure for command serial * based IO. */static Tcl_ChannelType serialChannelType = {    "serial",                   /* Type name. */    TCL_CHANNEL_VERSION_2,      /* v2 channel */    SerialCloseProc,            /* Close proc. */    SerialInputProc,            /* Input proc. */    SerialOutputProc,           /* Output proc. */    NULL,                       /* Seek proc. */    SerialSetOptionProc,        /* Set option proc. */    SerialGetOptionProc,        /* Get option proc. */    SerialWatchProc,            /* Set up notifier to watch the channel. */    SerialGetHandleProc,        /* Get an OS handle from channel. */    NULL,                       /* close2proc. */    SerialBlockProc,            /* Set blocking or non-blocking mode.*/    NULL,                       /* flush proc. */    NULL,                       /* handler proc. */};/* *---------------------------------------------------------------------- * * SerialInit -- * *  This function initializes the static variables for this file. * * Results: *  None. * * Side effects: *  Creates a new event source. * *---------------------------------------------------------------------- */static ThreadSpecificData *SerialInit(){    ThreadSpecificData *tsdPtr;    /*     * Check the initialized flag first, then check it again in the mutex.     * This is a speed enhancement.     */    if (!initialized) {        Tcl_MutexLock(&serialMutex);        if (!initialized) {            initialized = 1;            Tcl_CreateExitHandler(ProcExitHandler, NULL);        }        Tcl_MutexUnlock(&serialMutex);    }    tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);    if (tsdPtr == NULL) {        tsdPtr = TCL_TSD_INIT(&dataKey);        tsdPtr->firstSerialPtr = NULL;        Tcl_CreateEventSource(SerialSetupProc, SerialCheckProc, NULL);        Tcl_CreateThreadExitHandler(SerialExitHandler, NULL);    }    return tsdPtr;}/* *---------------------------------------------------------------------- * * SerialExitHandler -- * *  This function is called to cleanup the serial module before *  Tcl is unloaded. * * Results: *  None. * * Side effects: *  Removes the serial event source. * *---------------------------------------------------------------------- */static voidSerialExitHandler(    ClientData clientData)  /* Old window proc */{    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    SerialInfo *infoPtr;    /*     * Clear all eventually pending output.     * Otherwise Tcl's exit could totally block,     * because it performs a blocking flush on all open channels.     * Note that serial write operations may be blocked due to handshake.     */    for (infoPtr = tsdPtr->firstSerialPtr; infoPtr != NULL;            infoPtr = infoPtr->nextPtr) {        PurgeComm(infoPtr->handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR             | PURGE_RXCLEAR);    }    Tcl_DeleteEventSource(SerialSetupProc, SerialCheckProc, NULL);}/* *---------------------------------------------------------------------- * * ProcExitHandler -- * *  This function is called to cleanup the process list before *  Tcl is unloaded. * * Results: *  None. * * Side effects: *  Resets the process list. * *---------------------------------------------------------------------- */static voidProcExitHandler(    ClientData clientData)  /* Old window proc */{    Tcl_MutexLock(&serialMutex);    initialized = 0;    Tcl_MutexUnlock(&serialMutex);}/* *---------------------------------------------------------------------- * * SerialBlockTime -- * *  Wrapper to set Tcl's block time in msec * * Results: *  None. *---------------------------------------------------------------------- */static voidSerialBlockTime(    int msec)          /* milli-seconds */{    Tcl_Time blockTime;    blockTime.sec  =  msec / 1000;    blockTime.usec = (msec % 1000) * 1000;    Tcl_SetMaxBlockTime(&blockTime);}/* *---------------------------------------------------------------------- * * SerialGetMilliseconds -- * *  Get current time in milliseconds, *  Don't care about integer overruns * * Results: *  None. *---------------------------------------------------------------------- */static unsigned intSerialGetMilliseconds(    void){    Tcl_Time time;    TclpGetTime(&time);    return (time.sec * 1000 + time.usec / 1000);}/* *---------------------------------------------------------------------- * * SerialSetupProc -- * *  This procedure is invoked before Tcl_DoOneEvent blocks waiting *  for an event. * * Results: *  None. * * Side effects: *  Adjusts the block time if needed. * *---------------------------------------------------------------------- */voidSerialSetupProc(    ClientData data,    /* Not used. */    int flags)          /* Event flags as passed to Tcl_DoOneEvent. */{    SerialInfo *infoPtr;    int block = 1;    int msec = INT_MAX; /* min. found block time */    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {        return;    }    /*     * Look to see if any events handlers installed. If they are, do not block.     */    for (infoPtr = tsdPtr->firstSerialPtr; infoPtr != NULL;            infoPtr = infoPtr->nextPtr) {        if (infoPtr->watchMask & TCL_WRITABLE) {            if (WaitForSingleObject(infoPtr->evWritable, 0) != WAIT_TIMEOUT) {                block = 0;                msec = min( msec, infoPtr->blockTime );            }        }        if( infoPtr->watchMask & TCL_READABLE ) {            block = 0;            msec = min( msec, infoPtr->blockTime );

⌨️ 快捷键说明

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