--- np2/x11/cmserial.c 2004/03/26 13:58:51 1.1 +++ np2/x11/cmserial.c 2011/01/15 16:48:39 1.5 @@ -1,4 +1,4 @@ -/* $Id: cmserial.c,v 1.1 2004/03/26 13:58:51 monaka Exp $ */ +/* $Id: cmserial.c,v 1.5 2011/01/15 16:48:39 monaka Exp $ */ /* * Copyright (c) 2004 NONAKA Kimihiro @@ -12,8 +12,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -42,7 +40,9 @@ typedef struct { - int hdl; + int hdl; + + struct termios tio; } _CMSER, *CMSER; const UINT32 cmserial_speed[10] = { @@ -118,12 +118,117 @@ serialrelease(COMMNG self) { CMSER serial = (CMSER)(self + 1); + tcsetattr(serial->hdl, TCSANOW, &serial->tio); close(serial->hdl); _MFREE(self); } /* ---- interface */ +#if defined(SERIAL_DEBUG) +static void +print_status(const struct termios *tio) +{ + char *csstr; + int cs; + speed_t ispeed = cfgetispeed(tio); + speed_t ospeed = cfgetospeed(tio); + + g_printerr(" ispeed %d", ispeed); + g_printerr(" ospeed %d", ospeed); + g_printerr("%s", "\r\n"); + g_printerr(" %cIGNBRK", (tio->c_iflag & IGNBRK) ? '+' : '-'); + g_printerr(" %cBRKINT", (tio->c_iflag & BRKINT) ? '+' : '-'); + g_printerr(" %cIGNPAR", (tio->c_iflag & IGNPAR) ? '+' : '-'); + g_printerr(" %cPARMRK", (tio->c_iflag & PARMRK) ? '+' : '-'); + g_printerr(" %cINPCK", (tio->c_iflag & INPCK) ? '+' : '-'); + g_printerr(" %cISTRIP", (tio->c_iflag & ISTRIP) ? '+' : '-'); + g_printerr(" %cINLCR", (tio->c_iflag & INLCR) ? '+' : '-'); + g_printerr(" %cIGNCR", (tio->c_iflag & IGNCR) ? '+' : '-'); + g_printerr(" %cICRNL", (tio->c_iflag & ICRNL) ? '+' : '-'); + g_printerr(" %cIXON", (tio->c_iflag & IXON) ? '+' : '-'); + g_printerr(" %cIXOFF", (tio->c_iflag & IXOFF) ? '+' : '-'); + g_printerr(" %cIXANY", (tio->c_iflag & IXANY) ? '+' : '-'); + g_printerr(" %cIMAXBEL", (tio->c_iflag & IMAXBEL) ? '+' : '-'); + g_printerr("%s", "\r\n"); + g_printerr(" %cOPOST", (tio->c_oflag & OPOST) ? '+' : '-'); + g_printerr(" %cONLCR", (tio->c_oflag & ONLCR) ? '+' : '-'); +#ifdef OXTABS + g_printerr(" %cOXTABS", (tio->c_oflag & OXTABS) ? '+' : '-'); +#endif +#ifdef TABDLY + g_printerr(" %cTABDLY", (tio->c_oflag & TABDLY) == XTABS ? '+' : '-'); +#endif +#ifdef ONOEOT + g_printerr(" %cONOEOT", (tio->c_oflag & ONOEOT) ? '+' : '-'); +#endif + g_printerr("%s", "\r\n"); + + cs = tio->c_cflag & CSIZE; + switch (cs) { + case CS5: + csstr = "5"; + break; + + case CS6: + csstr = "6"; + break; + + case CS7: + csstr = "7"; + break; + + case CS8: + csstr = "8"; + break; + + default: + csstr = "?"; + break; + } + g_printerr(" cs%s", csstr); + g_printerr(" %cCSTOPB", (tio->c_cflag & CSTOPB) ? '+' : '-'); + g_printerr(" %cCREAD", (tio->c_cflag & CREAD) ? '+' : '-'); + g_printerr(" %cPARENB", (tio->c_cflag & PARENB) ? '+' : '-'); + g_printerr(" %cPARODD", (tio->c_cflag & PARODD) ? '+' : '-'); + g_printerr(" %cHUPCL", (tio->c_cflag & HUPCL) ? '+' : '-'); + g_printerr(" %cCLOCAL", (tio->c_cflag & CLOCAL) ? '+' : '-'); +#ifdef CCTS_OFLOW + g_printerr(" %cCCTS_OFLOW", (tio->c_cflag & CCTS_OFLOW) ? '+' : '-'); +#endif + g_printerr(" %cCRTSCTS", (tio->c_cflag & CRTSCTS) ? '+' : '-'); +#ifdef CRTS_IFLOW + g_printerr(" %cCRTS_IFLOW", (tio->c_cflag & CRTS_IFLOW) ? '+' : '-'); +#endif +#ifdef MDMBUF + g_printerr(" %cMDMBUF", (tio->c_cflag & MDMBUF) ? '+' : '-'); +#endif + g_printerr(" %cECHOKE", (tio->c_lflag & ECHOKE) ? '+' : '-'); + g_printerr(" %cECHOE", (tio->c_lflag & ECHOE) ? '+' : '-'); + g_printerr(" %cECHO", (tio->c_lflag & ECHO) ? '+' : '-'); + g_printerr(" %cECHONL", (tio->c_lflag & ECHONL) ? '+' : '-'); + g_printerr(" %cECHOPRT", (tio->c_lflag & ECHOPRT) ? '+' : '-'); + g_printerr(" %cECHOCTL", (tio->c_lflag & ECHOCTL) ? '+' : '-'); + g_printerr(" %cISIG", (tio->c_lflag & ISIG) ? '+' : '-'); + g_printerr(" %cICANON", (tio->c_lflag & ICANON) ? '+' : '-'); +#ifdef ALTWERASE + g_printerr(" %cALTWERASE", (tio->c_lflag & ALTWERASE) ? '+' : '-'); +#endif + g_printerr(" %cIEXTEN", (tio->c_lflag & IEXTEN) ? '+' : '-'); + g_printerr("%s", "\r\n"); +#ifdef EXTPROC + g_printerr(" %cEXTPROC", (tio->c_lflag & EXTPROC) ? '+' : '-'); +#endif + g_printerr(" %cTOSTOP", (tio->c_lflag & TOSTOP) ? '+' : '-'); + g_printerr(" %cFLUSHO", (tio->c_lflag & FLUSHO) ? '+' : '-'); +#ifdef NOKERNINFO + g_printerr(" %cNOKERNINFO", (tio->c_lflag & NOKERNINFO) ? '+' : '-'); +#endif + g_printerr(" %cPENDIN", (tio->c_lflag & PENDIN) ? '+' : '-'); + g_printerr(" %cNOFLSH", (tio->c_lflag & NOFLSH) ? '+' : '-'); + g_printerr("%s", "\r\n"); +} +#endif COMMNG cmserial_create(UINT port, BYTE param, UINT32 speed) @@ -133,7 +238,7 @@ cmserial_create(UINT port, BYTE param, U B9600, B19200, B38400, B57600, B115200 }; static const int csize[] = { CS5, CS6, CS7, CS8 }; - struct termios options; + struct termios options, origopt; COMMNG ret; CMSER serial; int hdl; @@ -157,12 +262,17 @@ cmserial_create(UINT port, BYTE param, U VERBOSE(("cmserial_create: open failure %s, %s", np2oscfg.com[port].mout, strerror(errno))); goto cscre_failure; } - fcntl(hdl, F_SETFL, 0); + + if (!isatty(hdl)) { + VERBOSE(("cmserial_create: not terminal file descriptor (%s)", strerror(errno))); + goto cscre_close; + } /* get current options for the port */ tcgetattr(hdl, &options); + origopt = options; - /* set the baud rates */ + /* baud rates */ for (i = 0; i < NELEMENTS(cmserial_speed); i++) { if (cmserial_speed[i] >= speed) { VERBOSE(("cmserial_create: spped = %d", cmserial_speed[i])); @@ -176,18 +286,16 @@ cmserial_create(UINT port, BYTE param, U cfsetispeed(&options, cmserial_cflag[i]); cfsetospeed(&options, cmserial_cflag[i]); - /* set the character size bits */ + /* character size bits */ options.c_cflag &= ~CSIZE; options.c_cflag |= csize[(param >> 2) & 3]; VERBOSE(("cmserial_create: charactor size = %d", csize[(param >> 2) & 3])); - /* set parity check */ + /* parity check */ switch (param & 0x30) { case 0x10: VERBOSE(("cmserial_create: odd parity")); - options.c_cflag |= PARENB; - options.c_cflag |= PARODD; - options.c_cflag &= ~CSTOPB; + options.c_cflag |= PARENB | PARODD; options.c_iflag |= INPCK | ISTRIP; break; @@ -195,33 +303,40 @@ cmserial_create(UINT port, BYTE param, U VERBOSE(("cmserial_create: even parity")); options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; - options.c_cflag &= ~CSTOPB; options.c_iflag |= INPCK | ISTRIP; break; default: VERBOSE(("cmserial_create: non parity")); options.c_cflag &= ~PARENB; - options.c_cflag &= ~CSTOPB; options.c_iflag &= ~(INPCK | ISTRIP); break; } - /* set stop bits XXX */ -#if 0 + /* stop bits */ switch (param & 0xc0) { case 0x80: - dcb.StopBits = ONE5STOPBITS; + VERBOSE(("cmserial_create: stop bits: 1.5")); break; case 0xc0: - dcb.StopBits = TWOSTOPBITS; + VERBOSE(("cmserial_create: stop bits: 2")); + options.c_cflag |= CSTOPB; break; default: - dcb.StopBits = ONESTOPBIT; + VERBOSE(("cmserial_create: stop bits: 1")); + options.c_cflag &= ~CSTOPB; break; } + + /* set misc flag */ + cfmakeraw(&options); + options.c_cflag |= CLOCAL | CREAD; + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + +#if defined(SERIAL_DEBUG) + print_status(&options); #endif ret = (COMMNG)_MALLOC(sizeof(_COMMNG) + sizeof(_CMSER), "SERIAL"); @@ -230,19 +345,9 @@ cmserial_create(UINT port, BYTE param, U goto cscre_close; } - /* set misc flag */ - options.c_cflag |= CLOCAL | CREAD; /* enable recv and local mode */ - options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* raw input */ - options.c_oflag &= ~OPOST; /* raw output */ - /* set the new options for the port */ tcsetattr(hdl, TCSANOW, &options); -#if 0 - /* set Non-blocking I/O mode */ - fcntl(hdl, F_SETFL, FNDELAY); -#endif - #if 1 ret->connect = COMCONNECT_MIDI; #else @@ -255,6 +360,7 @@ cmserial_create(UINT port, BYTE param, U ret->release = serialrelease; serial = (CMSER)(ret + 1); serial->hdl = hdl; + serial->tio = origopt; return ret; cscre_close: