📄 tclwinserial.c
字号:
if (! GetCommState(infoPtr->handle, &dcb)) { if (interp) { Tcl_AppendResult(interp, "can't get comm state", (char *) NULL); } return TCL_ERROR; } if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } if (argc == 2) { dcb.XonChar = argv[0][0]; dcb.XoffChar = argv[1][0]; } else { if (interp) { Tcl_AppendResult(interp, "bad value for -xchar: should be a list of two elements", (char *) NULL); } return TCL_ERROR; } if (! SetCommState(infoPtr->handle, &dcb)) { if (interp) { Tcl_AppendResult(interp, "can't set comm state", (char *) NULL); } return TCL_ERROR; } return TCL_OK; } /* * Option -ttycontrol {DTR 1 RTS 0 BREAK 0} */ if ((len > 4) && (strncmp(optionName, "-ttycontrol", len) == 0)) { if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } if ((argc % 2) == 1) { if (interp) { Tcl_AppendResult(interp, "bad value for -ttycontrol: should be a list of signal,value pairs", (char *) NULL); } return TCL_ERROR; } while (argc > 1) { if (Tcl_GetBoolean(interp, argv[1], &flag) == TCL_ERROR) { return TCL_ERROR; } if (strnicmp(argv[0], "DTR", strlen(argv[0])) == 0) { if (! EscapeCommFunction(infoPtr->handle, flag ? SETDTR : CLRDTR)) { if (interp) { Tcl_AppendResult(interp, "can't set DTR signal", (char *) NULL); } return TCL_ERROR; } } else if (strnicmp(argv[0], "RTS", strlen(argv[0])) == 0) { if (! EscapeCommFunction(infoPtr->handle, flag ? SETRTS : CLRRTS)) { if (interp) { Tcl_AppendResult(interp, "can't set RTS signal", (char *) NULL); } return TCL_ERROR; } } else if (strnicmp(argv[0], "BREAK", strlen(argv[0])) == 0) { if (! EscapeCommFunction(infoPtr->handle, flag ? SETBREAK : CLRBREAK)) { if (interp) { Tcl_AppendResult(interp, "can't set BREAK signal", (char *) NULL); } return TCL_ERROR; } } else { if (interp) { Tcl_AppendResult(interp, "bad signal for -ttycontrol: must be DTR, RTS or BREAK", (char *) NULL); } return TCL_ERROR; } argc -= 2, argv += 2; } /* while (argc > 1) */ return TCL_OK; } /* * Option -sysbuffer {read_size write_size} * Option -sysbuffer read_size */ if ((len > 1) && (strncmp(optionName, "-sysbuffer", len) == 0)) { /* * -sysbuffer 4096 or -sysbuffer {64536 4096} */ size_t inSize = -1, outSize = -1; if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } if (argc == 1) { inSize = atoi(argv[0]); outSize = infoPtr->sysBufWrite; } else if (argc == 2) { inSize = atoi(argv[0]); outSize = atoi(argv[1]); } if ( (inSize <= 0) || (outSize <= 0) ) { if (interp) { Tcl_AppendResult(interp, "bad value for -sysbuffer: should be a list of one or two integers > 0", (char *) NULL); } return TCL_ERROR; } if (! SetupComm(infoPtr->handle, inSize, outSize)) { if (interp) { Tcl_AppendResult(interp, "can't setup comm buffers", (char *) NULL); } return TCL_ERROR; } infoPtr->sysBufRead = inSize; infoPtr->sysBufWrite = outSize; /* * Adjust the handshake limits. * Yes, the XonXoff limits seem to influence even hardware handshake */ if (! GetCommState(infoPtr->handle, &dcb)) { if (interp) { Tcl_AppendResult(interp, "can't get comm state", (char *) NULL); } return TCL_ERROR; } dcb.XonLim = (WORD) (infoPtr->sysBufRead*1/2); dcb.XoffLim = (WORD) (infoPtr->sysBufRead*1/4); if (! SetCommState(infoPtr->handle, &dcb)) { if (interp) { Tcl_AppendResult(interp, "can't set comm state", (char *) NULL); } return TCL_ERROR; } return TCL_OK; } /* * Option -pollinterval msec */ if ((len > 1) && (strncmp(optionName, "-pollinterval", len) == 0)) { if ( Tcl_GetInt(interp, value, &(infoPtr->blockTime)) != TCL_OK ) { return TCL_ERROR; } return TCL_OK; } /* * Option -timeout msec */ if ((len > 2) && (strncmp(optionName, "-timeout", len) == 0)) { int msec; COMMTIMEOUTS tout = {0,0,0,0,0}; if ( Tcl_GetInt(interp, value, &msec) != TCL_OK ) { return TCL_ERROR; } tout.ReadTotalTimeoutConstant = msec; if (! SetCommTimeouts(infoPtr->handle, &tout)) { if (interp) { Tcl_AppendResult(interp, "can't set comm timeouts", (char *) NULL); } return TCL_ERROR; } return TCL_OK; } return Tcl_BadChannelOption(interp, optionName, "mode handshake pollinterval sysbuffer timeout ttycontrol xchar");}/* *---------------------------------------------------------------------- * * SerialGetOptionProc -- * * Gets a mode associated with an IO channel. If the optionName arg * is non NULL, retrieves the value of that option. If the optionName * arg is NULL, retrieves a list of alternating option names and * values for the given channel. * * Results: * A standard Tcl result. Also sets the supplied DString to the * string value of the option(s) returned. * * Side effects: * The string returned by this function is in static storage and * may be reused at any time subsequent to the call. * *---------------------------------------------------------------------- */static intSerialGetOptionProc(instanceData, interp, optionName, dsPtr) ClientData instanceData; /* File state. */ Tcl_Interp *interp; /* For error reporting - can be NULL. */ CONST char *optionName; /* Option to get. */ Tcl_DString *dsPtr; /* Where to store value(s). */{ SerialInfo *infoPtr; DCB dcb; size_t len; int valid = 0; /* flag if valid option parsed */ infoPtr = (SerialInfo *) instanceData; if (optionName == NULL) { len = 0; } else { len = strlen(optionName); } /* * get option -mode */ if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-mode"); } if ((len == 0) || ((len > 2) && (strncmp(optionName, "-mode", len) == 0))) { char parity; char *stop; char buf[2 * TCL_INTEGER_SPACE + 16]; if (! GetCommState(infoPtr->handle, &dcb)) { if (interp) { Tcl_AppendResult(interp, "can't get comm state", (char *) NULL); } return TCL_ERROR; } valid = 1; parity = 'n'; if (dcb.Parity <= 4) { parity = "noems"[dcb.Parity]; } stop = (dcb.StopBits == ONESTOPBIT) ? "1" : (dcb.StopBits == ONE5STOPBITS) ? "1.5" : "2"; wsprintfA(buf, "%d,%c,%d,%s", dcb.BaudRate, parity, dcb.ByteSize, stop); Tcl_DStringAppendElement(dsPtr, buf); } /* * get option -pollinterval */ if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-pollinterval"); } if ((len == 0) || ((len > 1) && (strncmp(optionName, "-pollinterval", len) == 0))) { char buf[TCL_INTEGER_SPACE + 1]; valid = 1; wsprintfA(buf, "%d", infoPtr->blockTime); Tcl_DStringAppendElement(dsPtr, buf); } /* * get option -sysbuffer */ if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-sysbuffer"); Tcl_DStringStartSublist(dsPtr); } if ((len == 0) || ((len > 1) && (strncmp(optionName, "-sysbuffer", len) == 0))) { char buf[TCL_INTEGER_SPACE + 1]; valid = 1; wsprintfA(buf, "%d", infoPtr->sysBufRead); Tcl_DStringAppendElement(dsPtr, buf); wsprintfA(buf, "%d", infoPtr->sysBufWrite); Tcl_DStringAppendElement(dsPtr, buf); } if (len == 0) { Tcl_DStringEndSublist(dsPtr); } /* * get option -xchar */ if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-xchar"); Tcl_DStringStartSublist(dsPtr); } if ((len == 0) || ((len > 1) && (strncmp(optionName, "-xchar", len) == 0))) { char buf[4]; valid = 1; if (! GetCommState(infoPtr->handle, &dcb)) { if (interp) { Tcl_AppendResult(interp, "can't get comm state", (char *) NULL); } return TCL_ERROR; } sprintf(buf, "%c", dcb.XonChar); Tcl_DStringAppendElement(dsPtr, buf); sprintf(buf, "%c", dcb.XoffChar); Tcl_DStringAppendElement(dsPtr, buf); } if (len == 0) { Tcl_DStringEndSublist(dsPtr); } /* * get option -lasterror * option is readonly and returned by [fconfigure chan -lasterror] * but not returned by unnamed [fconfigure chan] */ if ( (len > 1) && (strncmp(optionName, "-lasterror", len) == 0) ) { valid = 1; SerialErrorStr(infoPtr->lastError, dsPtr); } /* * get option -queue * option is readonly and returned by [fconfigure chan -queue] */ if ((len > 1) && (strncmp(optionName, "-queue", len) == 0)) { char buf[TCL_INTEGER_SPACE + 1]; COMSTAT cStat; int error; int inBuffered, outBuffered, count; valid = 1; /* * Query the pending data in Tcl's internal queues */ inBuffered = Tcl_InputBuffered(infoPtr->channel); outBuffered = Tcl_OutputBuffered(infoPtr->channel); /* * Query the number of bytes in our output queue: * 1. The bytes pending in the output thread * 2. The bytes in the system drivers buffer * The writer thread should not interfere this action. */ EnterCriticalSection(&infoPtr->csWrite); ClearCommError( infoPtr->handle, &error, &cStat ); count = (int)cStat.cbOutQue + infoPtr->writeQueue; LeaveCriticalSection(&infoPtr->csWrite); wsprintfA(buf, "%d", inBuffered + cStat.cbInQue); Tcl_DStringAppendElement(dsPtr, buf); wsprintfA(buf, "%d", outBuffered + count); Tcl_DStringAppendElement(dsPtr, buf); } /* * get option -ttystatus * option is readonly and returned by [fconfigure chan -ttystatus] * but not returned by unnamed [fconfigure chan] */ if ( (len > 4) && (strncmp(optionName, "-ttystatus", len) == 0) ) { DWORD status; if (! GetCommModemStatus(infoPtr->handle, &status)) { if (interp) { Tcl_AppendResult(interp, "can't get tty status", (char *) NULL); } return TCL_ERROR; } valid = 1; SerialModemStatusStr(status, dsPtr); } if (valid) { return TCL_OK; } else { return Tcl_BadChannelOption(interp, optionName, "mode pollinterval lasterror queue sysbuffer ttystatus xchar"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -