📄 tclunixchan.c
字号:
* Side effects: * Sets up the notifier so that a future event on the channel will * be seen by Tcl. * *---------------------------------------------------------------------- */static voidFileWatchProc(instanceData, mask) ClientData instanceData; /* The file state. */ int mask; /* Events of interest; an OR-ed * combination of TCL_READABLE, * TCL_WRITABLE and TCL_EXCEPTION. */{ FileState *fsPtr = (FileState *) instanceData; /* * Make sure we only register for events that are valid on this file. * Note that we are passing Tcl_NotifyChannel directly to * Tcl_CreateFileHandler with the channel pointer as the client data. */ mask &= fsPtr->validMask; if (mask) { Tcl_CreateFileHandler(fsPtr->fd, mask, (Tcl_FileProc *) Tcl_NotifyChannel, (ClientData) fsPtr->channel); } else { Tcl_DeleteFileHandler(fsPtr->fd); }}/* *---------------------------------------------------------------------- * * FileGetHandleProc -- * * Called from Tcl_GetChannelFile to retrieve OS handles from * a file 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 intFileGetHandleProc(instanceData, direction, handlePtr) ClientData instanceData; /* The file state. */ int direction; /* TCL_READABLE or TCL_WRITABLE */ ClientData *handlePtr; /* Where to store the handle. */{ FileState *fsPtr = (FileState *) instanceData; if (direction & fsPtr->validMask) { *handlePtr = (ClientData) fsPtr->fd; return TCL_OK; } else { return TCL_ERROR; }}/* *---------------------------------------------------------------------- * * TtySetOptionProc -- * * Sets an option on a channel. * * Results: * A standard Tcl result. Also sets interp->result on error if * interp is not NULL. * * Side effects: * May modify an option on a device. * Sets Error message if needed (by calling Tcl_BadChannelOption). * *---------------------------------------------------------------------- */static int TtySetOptionProc(instanceData, interp, optionName, value) ClientData instanceData; /* File state. */ Tcl_Interp *interp; /* For error reporting - can be NULL. */ char *optionName; /* Which option to set? */ char *value; /* New value for option. */{ FileState *fsPtr = (FileState *) instanceData; unsigned int len; TtyAttrs tty; len = strlen(optionName); if ((len > 1) && (strncmp(optionName, "-mode", len) == 0)) { if (TtyParseMode(interp, value, &tty.baud, &tty.parity, &tty.data, &tty.stop) != TCL_OK) { return TCL_ERROR; } /* * system calls results should be checked there. -- dl */ TtySetAttributes(fsPtr->fd, &tty); return TCL_OK; } else { return Tcl_BadChannelOption(interp, optionName, "mode"); }}/* *---------------------------------------------------------------------- * * TtyGetOptionProc -- * * 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. * Sets Error message if needed (by calling Tcl_BadChannelOption). * *---------------------------------------------------------------------- */static int TtyGetOptionProc(instanceData, interp, optionName, dsPtr) ClientData instanceData; /* File state. */ Tcl_Interp *interp; /* For error reporting - can be NULL. */ char *optionName; /* Option to get. */ Tcl_DString *dsPtr; /* Where to store value(s). */{ FileState *fsPtr = (FileState *) instanceData; unsigned int len; char buf[32]; TtyAttrs tty; if (optionName == NULL) { Tcl_DStringAppendElement(dsPtr, "-mode"); len = 0; } else { len = strlen(optionName); } if ((len == 0) || ((len > 1) && (strncmp(optionName, "-mode", len) == 0))) { TtyGetAttributes(fsPtr->fd, &tty); sprintf(buf, "%d,%c,%d,%d", tty.baud, tty.parity, tty.data, tty.stop); Tcl_DStringAppendElement(dsPtr, buf); return TCL_OK; } else { return Tcl_BadChannelOption(interp, optionName, "mode"); }}#undef DIRECT_BAUD#ifdef B4800# if (B4800 == 4800)# define DIRECT_BAUD# endif#endif#ifdef DIRECT_BAUD# define TtyGetSpeed(baud) ((unsigned) (baud))# define TtyGetBaud(speed) ((int) (speed))#elsestatic struct {int baud; unsigned long speed;} speeds[] = {#ifdef B0 {0, B0},#endif#ifdef B50 {50, B50},#endif#ifdef B75 {75, B75},#endif#ifdef B110 {110, B110},#endif#ifdef B134 {134, B134},#endif#ifdef B150 {150, B150},#endif#ifdef B200 {200, B200},#endif#ifdef B300 {300, B300},#endif#ifdef B600 {600, B600},#endif#ifdef B1200 {1200, B1200},#endif#ifdef B1800 {1800, B1800},#endif#ifdef B2400 {2400, B2400},#endif#ifdef B4800 {4800, B4800},#endif#ifdef B9600 {9600, B9600},#endif#ifdef B14400 {14400, B14400},#endif#ifdef B19200 {19200, B19200},#endif#ifdef EXTA {19200, EXTA},#endif#ifdef B28800 {28800, B28800},#endif#ifdef B38400 {38400, B38400},#endif#ifdef EXTB {38400, EXTB},#endif#ifdef B57600 {57600, B57600},#endif#ifdef _B57600 {57600, _B57600},#endif#ifdef B76800 {76800, B76800},#endif#ifdef B115200 {115200, B115200},#endif#ifdef _B115200 {115200, _B115200},#endif#ifdef B153600 {153600, B153600},#endif#ifdef B230400 {230400, B230400},#endif#ifdef B307200 {307200, B307200},#endif#ifdef B460800 {460800, B460800},#endif {-1, 0}};/* *--------------------------------------------------------------------------- * * TtyGetSpeed -- * * Given a baud rate, get the mask value that should be stored in * the termios, termio, or sgttyb structure in order to select that * baud rate. * * Results: * As above. * * Side effects: * None. * *--------------------------------------------------------------------------- */static unsigned longTtyGetSpeed(baud) int baud; /* The baud rate to look up. */{ int bestIdx, bestDiff, i, diff; bestIdx = 0; bestDiff = 1000000; /* * If the baud rate does not correspond to one of the known mask values, * choose the mask value whose baud rate is closest to the specified * baud rate. */ for (i = 0; speeds[i].baud >= 0; i++) { diff = speeds[i].baud - baud; if (diff < 0) { diff = -diff; } if (diff < bestDiff) { bestIdx = i; bestDiff = diff; } } return speeds[bestIdx].speed;}/* *--------------------------------------------------------------------------- * * TtyGetBaud -- * * Given a speed mask value from a termios, termio, or sgttyb * structure, get the baus rate that corresponds to that mask value. * * Results: * As above. If the mask value was not recognized, 0 is returned. * * Side effects: * None. * *--------------------------------------------------------------------------- */static intTtyGetBaud(speed) unsigned long speed; /* Speed mask value to look up. */{ int i; for (i = 0; speeds[i].baud >= 0; i++) { if (speeds[i].speed == speed) { return speeds[i].baud; } } return 0;}#endif /* !DIRECT_BAUD *//* *--------------------------------------------------------------------------- * * TtyInit -- * * Given file descriptor that refers to a serial port, * initialize the serial port to a set of sane values so that * Tcl can talk to a device located on the serial port. * * Results: * None. * * Side effects: * Serial device initialized. * *--------------------------------------------------------------------------- */static voidTtyInit(fd) int fd; /* Open file descriptor for serial port to * be initialized. */{#ifdef USE_TERMIOS struct termios termios; tcgetattr(fd, &termios); termios.c_iflag = IGNBRK; termios.c_oflag = 0; termios.c_lflag = 0; termios.c_cflag |= CREAD; termios.c_cc[VMIN] = 60; termios.c_cc[VTIME] = 2; tcsetattr(fd, TCSANOW, &termios);#else /* !USE_TERMIOS */#ifdef USE_TERMIO struct termio termio; ioctl(fd, TCGETA, &termio); termio.c_iflag = IGNBRK; termio.c_oflag = 0; termio.c_lflag = 0; termio.c_cflag |= CREAD; termio.c_cc[VMIN] = 60; termio.c_cc[VTIME] = 2; ioctl(fd, TCSETAW, &termio);#else /* !USE_TERMIO */#ifdef USE_SGTTY struct sgttyb sgttyb; ioctl(fd, TIOCGETP, &sgttyb); sgttyb.sg_flags &= (EVENP | ODDP); sgttyb.sg_flags |= RAW; ioctl(fd, TIOCSETP, &sgttyb);#endif /* USE_SGTTY */#endif /* !USE_TERMIO */#endif /* !USE_TERMIOS */}/* *--------------------------------------------------------------------------- * * TtyGetAttributes -- * * Get the current attributes of the specified serial device. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static voidTtyGetAttributes(fd, ttyPtr) int fd; /* Open file descriptor for serial port to * be queried. */ TtyAttrs *ttyPtr; /* Buffer filled with serial port * attributes. */{#ifdef USE_TERMIOS int parity, data; struct termios termios; tcgetattr(fd, &termios); ttyPtr->baud = TtyGetBaud(cfgetospeed(&termios)); parity = 'n';#ifdef PAREXT switch ((int) (termios.c_cflag & (PARENB | PARODD | PAREXT))) { case PARENB : parity = 'e'; break; case PARENB | PARODD : parity = 'o'; break; case PARENB | PAREXT : parity = 's'; break; case PARENB | PARODD | PAREXT : parity = 'm'; break; }#else /* !PAREXT */ switch ((int) (termios.c_cflag & (PARENB | PARODD))) { case PARENB : parity = 'e'; break; case PARENB | PARODD : parity = 'o'; break; }#endif /* !PAREXT */ ttyPtr->parity = parity; data = termios.c_cflag & CSIZE; ttyPtr->data = (data == CS5) ? 5 : (data == CS6) ? 6 : (data == CS7) ? 7 : 8; ttyPtr->stop = (termios.c_cflag & CSTOPB) ? 2 : 1;#else /* !USE_TERMIOS */#ifdef USE_TERMIO int parity, data; struct termio termio; ioctl(fd, TCGETA, &termio); ttyPtr->baud = TtyGetBaud(termio.c_cflag & CBAUD); parity = 'n'; switch (termio.c_cflag & (PARENB | PARODD | PAREXT)) { case PARENB : parity = 'e'; break; case PARENB | PARODD : parity = 'o'; break; case PARENB | PAREXT : parity = 's'; break; case PARENB | PARODD | PAREXT : parity = 'm'; break; } ttyPtr->parity = parity; data = termio.c_cflag & CSIZE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -