static int set_tty_settings (int tty, TIOTYPE *tiop) { while (SETATTR (tty, tiop) < 0) { if (errno != EINTR) return -1; errno = 0; } #if 0 #if defined (TERMIOS_TTY_DRIVER) # if defined (__ksr1__) if (ksrflow) { ksrflow = 0; tcflow (tty, TCOON); } # else /* !ksr1 */ tcflow (tty, TCOON); /* Simulate a ^Q. */ # endif /* !ksr1 */ #else ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */ #endif /* !TERMIOS_TTY_DRIVER */ #endif return 0; }
int rl_restart_output (int count, int key) { int fildes = fileno (rl_outstream); #if defined (TIOCSTART) #if defined (apollo) ioctl (&fildes, TIOCSTART, 0); #else ioctl (fildes, TIOCSTART, 0); #endif /* apollo */ #else /* !TIOCSTART */ # if defined (TERMIOS_TTY_DRIVER) # if defined (__ksr1__) if (ksrflow) { ksrflow = 0; tcflow (fildes, TCOON); } # else /* !ksr1 */ tcflow (fildes, TCOON); /* Simulate a ^Q. */ # endif /* !ksr1 */ # else /* !TERMIOS_TTY_DRIVER */ # if defined (TCXONC) ioctl (fildes, TCXONC, TCOON); # endif /* TCXONC */ # endif /* !TERMIOS_TTY_DRIVER */ #endif /* !TIOCSTART */ return 0; }
static void read_password(char *buf, size_t len, char *host) { char pwd[80]; struct termios old; struct termios tp; tcgetattr(0, &tp); old = tp; tp.c_lflag &= (~ECHO); tcsetattr(0, TCSANOW, &tp); fprintf(stdout, "Enter password for %s: ", host); fflush(stdout); tcflow(0, TCOOFF); /* * I'd like to do something with the return value here, but really, * what can be done? */ (void)scanf("%79s", pwd); tcflow(0, TCOON); fprintf(stdout, "\n"); tcsetattr(0, TCSANOW, &old); strncpy(buf, pwd, len); buf[len-1] = '\0'; }
static void read_password(char *buf, size_t len, char *host) { char pwd[80]; int retval; struct termios old; struct termios tp; tcgetattr(0, &tp); old = tp; tp.c_lflag &= (~ECHO); tcsetattr(0, TCSANOW, &tp); fprintf(stdout, "Enter password for %s: ", host); fflush(stdout); tcflow(0, TCOOFF); retval = scanf("%79s", pwd); tcflow(0, TCOON); fprintf(stdout, "\n"); tcsetattr(0, TCSANOW, &old); strncpy(buf, pwd, len); buf[len-1] = '\0'; }
unit posix_tty_tcflow(cerr er, int fd, int action) { if(tcflow(fd, action) == -1) send_errno(er,errno); return empty_record; }
int rl_stop_output (int count, int key) { int fildes = fileno (rl_instream); #if defined (TIOCSTOP) # if defined (apollo) ioctl (&fildes, TIOCSTOP, 0); # else ioctl (fildes, TIOCSTOP, 0); # endif /* apollo */ #else /* !TIOCSTOP */ # if defined (TERMIOS_TTY_DRIVER) # if defined (__ksr1__) ksrflow = 1; # endif /* ksr1 */ tcflow (fildes, TCOOFF); # else # if defined (TCXONC) ioctl (fildes, TCXONC, TCOON); # endif /* TCXONC */ # endif /* !TERMIOS_TTY_DRIVER */ #endif /* !TIOCSTOP */ return 0; }
/* The function calling [tcflow]. */ static void worker_tcflow(struct job_tcflow* job) { /* Perform the blocking call. */ job->result = tcflow(job->fd, job->action); /* Save the value of errno. */ job->errno_copy = errno; }
/* * does not change IXON but simulates that IXON has been received: */ static NTSTATUS set_XOn(int fd) { if (tcflow(fd, TCOON)) { return FILE_GetNtStatus(); } return STATUS_SUCCESS; }
/*** Suspend transmission or receipt of data. @function tcflow @int fd terminal descriptor to act on @int action one of `TCOOFF`, `TCOON`, `TCIOFF` or `TCION` @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see tcflow(3) */ static int Ptcflow(lua_State *L) { int fd = checkint(L, 1); int action = checkint(L, 2); checknargs(L, 2); return pushresult(L, tcflow(fd, action), NULL); }
int main(void) { int n1, n2, fd; if((fd=open("/dev/ttyS0", O_RDWR|O_NOCTTY|O_NONBLOCK))== -1){ fprintf(stderr, "Open port: Unable to open, %s\n",strerror(errno)); exit(EXIT_FAILURE); } write(fd, "Example of line control functions ", 34); tcdrain(fd); /* 等待輸出佇列中的資料全部送出 */ tcflow(fd, TCOOFF); /* 懸掛輸出傳輸 */ n1 = write(fd, "this line will be thrown over\n", 30); tcflush(fd, TCOFLUSH); /* 清除輸出佇列 */ n2 = write(fd, "this line will not be thrown over\n", 34); tcflow(fd, TCOON); /* 還原輸出傳輸 */ write(fd,"restart the output\n",19); exit(EXIT_SUCCESS); }
BOOL closetty(INT fd, const struct termios *restore) { sigset_t mask, oldmask; /* must first block SIGINT to avoid possible interrruption between * restoral of termios modes and the final close()... * NOTE: must ensure that we can restore the current signal mask * when finished. */ sigemptyset(&mask); sigemptyset(&oldmask); sigaddset(&mask, SIGINT); sigprocmask(SIG_BLOCK, &mask, &oldmask); /* restore termios modes: */ tcflow(fd, TCOON); /* better would be to turn off flow-control! */ if (tcsetattr(fd, TCSADRAIN, (struct termios *) restore) < 0) { sigprocmask(SIG_SETMASK, &oldmask, NULL); return (NO); } /* close the port: * NOTE: some UNIX serial UARTs or device-drivers will hard-hang in * close() if the ports transmitter is disabled by flow-control, * EVEN IF THERE ARE NO OUTPUT BYTES QUEUED FOR TRANSMISSION!!! * Thus we must turn off flow-control before calling close()... */ tcflow(fd, TCOON); if (close(fd) < 0) { sigprocmask(SIG_SETMASK, &oldmask, NULL); return (NO); } /* now is safe to unblock SIGINT: */ sigprocmask(SIG_SETMASK, &oldmask, NULL); return (YES); }
static BOOL _set_xon(WINPR_COMM *pComm) { if (tcflow(pComm->fd, TCION) < 0) { CommLog_Print(WLOG_WARN, "TCION failure, errno=[%d] %s", errno, strerror(errno)); SetLastError(ERROR_IO_DEVICE); return FALSE; } return TRUE; }
/****************************************************** * re_open_device * *******************************************************/ void re_open_device () { int j = 0; { tcflow(serial_filedesc,TCOON); close_device(); usleep(400000); open_configure(); } }
static PyObject * termios_tcflow(PyObject *self, PyObject *args) { int fd, action; if (!PyArg_ParseTuple(args, "O&i:tcflow", fdconv, &fd, &action)) return NULL; if (tcflow(fd, action) == -1) return PyErr_SetFromErrno(TermiosError); Py_INCREF(Py_None); return Py_None; }
Val _lib7_P_TTY_tcflow (Task* task, Val arg) { //================== // // Mythrryl type: (Int, Int) -> Void // // Suspend transmission or receipt of data. // // This fn gets bound as tcflow in: // // src/lib/std/src/posix-1003.1b/posix-tty.pkg int status = tcflow( GET_TUPLE_SLOT_AS_INT(arg, 0),GET_TUPLE_SLOT_AS_INT(arg, 1) ); CHECK_RETURN_UNIT(task, status) }
/* this is a fall back, only taking care that input can be read when getting back into the forground, again */ static char * retrieve_tty_getpass (const char *prompt) { int fd ; if ((fd = open ("/dev/tty", O_RDONLY)) < 0) { fprintf (stderr, "Cannot open tty (%s)" BLURB, strerror (errno)) ; exit (0); } /* this causes getpass() to retrieve the input properly once it has been brought back in the foreground, again */ if (tcflow (fd, TCION) < 0) { fprintf (stderr, "Cannot access tty (%s)" BLURB, strerror (errno)) ; exit (0); } close (fd); return getpass (prompt); }
mraa_result_t mraa_uart_set_flowcontrol(mraa_uart_context dev, mraa_boolean_t xonxoff, mraa_boolean_t rtscts) { if (!dev) { syslog(LOG_ERR, "uart: set_flowcontrol: context is NULL"); return MRAA_ERROR_INVALID_HANDLE; } if (IS_FUNC_DEFINED(dev, uart_set_flowcontrol_replace)) { return dev->advance_func->uart_set_flowcontrol_replace(dev, xonxoff, rtscts); } // hardware flow control int action = TCIOFF; if (xonxoff) { action = TCION; } if (tcflow(dev->fd, action)) { return MRAA_ERROR_FEATURE_NOT_SUPPORTED; } // rtscts struct termios termio; // get current modes if (tcgetattr(dev->fd, &termio)) { syslog(LOG_ERR, "uart%i: set_flowcontrol: tcgetattr() failed: %s", dev->index, strerror(errno)); return MRAA_ERROR_INVALID_RESOURCE; } if (rtscts) { termio.c_cflag |= CRTSCTS; } else { termio.c_cflag &= ~CRTSCTS; } if (tcsetattr(dev->fd, TCSAFLUSH, &termio) < 0) { syslog(LOG_ERR, "uart%i: set_flowcontrol: tcsetattr() failed: %s", dev->index, strerror(errno)); return MRAA_ERROR_FEATURE_NOT_SUPPORTED; } return MRAA_SUCCESS; }
RadioLinux::RadioLinux(const std::string &devfile, int baudrate, Parity p) { mBaudRate = baudrate; mParity = p; mFD = open(devfile.c_str(), O_RDWR | O_ASYNC); if (mFD == -1) THROW_EXCEPT(RadioException, "Could not open " + devfile); struct termios tprops; tcgetattr(mFD, &tprops); tprops.c_iflag = 0; if (mParity != PARITY_NONE) tprops.c_iflag |= INPCK; tprops.c_oflag = 0; tprops.c_cflag = CS8 | CREAD; if (mParity != PARITY_NONE) { tprops.c_cflag |= PARENB; if (mParity == PARITY_ODD) tprops.c_cflag |= PARODD; } tprops.c_lflag = 0; // Disable control characaters for (int cc = 0; cc < NCCS; ++cc) tprops.c_cc[cc] = _POSIX_VDISABLE; tprops.c_cc[VMIN] = 0; // No minimum number of characters for reads tprops.c_cc[VTIME] = 0; // No timeout (0 deciseconds) speed_t baudspeed = baudToSpeed(mBaudRate); cfsetospeed(&tprops, baudspeed); cfsetispeed(&tprops, baudspeed); tcsetattr(mFD, TCSAFLUSH, &tprops); tcflow(mFD, TCOON | TCION); tcflush(mFD, TCIOFLUSH); }
bool mdtSerialPortPosix::resumeTransmission() { int err; if(flowCtlRtsCtsOn()){ if(!setRtsOn()){ return false; } } if(flowCtlXonXoffOn()){ if(tcflow(pvFd, TCION) < 0){ err = errno; mdtError e(MDT_PORT_IO_ERROR, "tcflow() call failed", mdtError::Error); e.setSystemError(err, strerror(err)); MDT_ERROR_SET_SRC(e, "mdtSerialPortPosix"); e.commit(); return false; } } return true; }
mraa_result_t mraa_uart_set_flowcontrol(mraa_uart_context dev, mraa_boolean_t xonxoff, mraa_boolean_t rtscts) { if (!dev) { syslog(LOG_ERR, "uart: stop: context is NULL"); return MRAA_ERROR_INVALID_HANDLE; } // hardware flow control int action = TCIOFF; if (xonxoff) { action = TCION; } if (tcflow(dev->fd, action)) { return MRAA_ERROR_FEATURE_NOT_SUPPORTED; } // rtscts struct termios termio; // get current modes if (tcgetattr(dev->fd, &termio)) { syslog(LOG_ERR, "uart: tcgetattr() failed"); return MRAA_ERROR_INVALID_HANDLE; } if (rtscts) { termio.c_cflag |= CRTSCTS; } else { termio.c_cflag &= ~CRTSCTS; } if (tcsetattr(dev->fd, TCSAFLUSH, &termio) < 0) { syslog(LOG_ERR, "uart: tcsetattr() failed"); return MRAA_ERROR_FEATURE_NOT_SUPPORTED; } return MRAA_SUCCESS; }
int uart_init(int baudrate, UARTParity parity) { // Establish endianness of the running system uint32_t test; char *set = (char *)&test; set[0] = 0x11; set[1] = 0x22; set[2] = 0x33; set[3] = 0x44; if (test == 0x11223344) hostendian = 1; // Big-endian else if (test == 0x44332211) hostendian = 0; // Little-endian else hostendian = -1; // Unsupported // Convert to speed_t / validate provided baudrate speed_t baud; switch (baudrate) { case 1200: baud = B1200; break; case 1800: baud = B1800; break; case 2400: baud = B2400; break; case 4800: baud = B4800; break; case 9600: baud = B9600; break; case 19200: baud = B19200; break; case 38400: baud = B38400; break; case 57600: baud = B57600; break; case 115200: baud = B115200; break; case 230400: baud = B230400; break; default: generateError("Unsupported baud rate requested"); return 0; } uartfd = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NONBLOCK); if (uartfd == -1) { generateError("Could not open /dev/ttyAMA0"); return 0; } struct sigaction sa; sa.sa_handler = sigHandlerIO; sa.sa_flags = 0; sa.sa_restorer = NULL; sigaction(SIGIO, &sa, NULL); fcntl(uartfd, F_SETOWN, getpid()); fcntl(uartfd, F_SETFL, O_ASYNC); // Set terminal properties for /dev/ttyAMA0 struct termios tprops; tprops.c_iflag = 0; if (parity != UART_PARDISABLE) tprops.c_iflag = INPCK; tprops.c_oflag = 0; tprops.c_cflag = CS8 | CREAD; if (parity != UART_PARDISABLE) { tprops.c_cflag |= PARENB; if (parity == UART_PARODD) tprops.c_cflag |= PARODD; } tprops.c_lflag = 0; // Disable control characters int cc; for (cc = 0; cc < NCCS; ++cc) tprops.c_cc[cc] = _POSIX_VDISABLE; tprops.c_cc[VMIN] = 0; // No minimum number of characters for reads tprops.c_cc[VTIME] = 0; // No timeout (0 deciseconds) // Baud rate cfsetospeed(&tprops, baud); cfsetispeed(&tprops, baud); // Set the attributes tcsetattr(uartfd, TCSAFLUSH, &tprops); tcflow(uartfd, TCOON | TCION); // Restart input and output tcflush(uartfd, TCIOFLUSH); // Flush buffer for clean start qb_initialize(&queuebuffer); return 1; }
// Serial 1 port setup void setupSerial1( int baud ) { /* */ mraa_uart_context uart1 = mraa_uart_init( 0 ); char *devPort = mraa_uart_get_dev_path( uart1 ); // "/dev/ttyMFD1"; // mraa_uart_get_dev_path( uart1 ); printf( " setupSerial1 at start with dev path: %s\n", devPort ); // sets up uart1, connected to Arduino BB pins 0 & 1 serialFDOut = -1; // Say that it is not open... serialFDIn = -1; fPtrOut = NULL; fPtrIn = NULL; // Try to open File Descriptor // char devPort[] = "/dev/ttyMFD1"; printf( " Serial port prepare to open %s\n", devPort ); // int serialFDOut = open( devPort, O_RDWR| O_NONBLOCK | O_NDELAY ); int serialFDOut = open( devPort, O_RDWR| O_NONBLOCK | O_NOCTTY | O_SYNC ); // Error check if ( serialFDOut < 0 ) { printf( " Error opening %s: %d, %s\n", devPort, errno, strerror( errno ) ); return; } printf( " Serial port %s opened successfully\n", devPort ); if ( ( fPtrOut = fdopen( serialFDOut, "r+" ) ) == NULL ) { printf( " Error opening file associated with %s: %d, %s\n", devPort, errno, strerror( errno ) ); close( serialFDOut ); return; } printf( " Serial port access file %s opened successfully\n", devPort ); // For normal files _pfileIn will simply be _pfileOut likewise for file descriptors fPtrIn = fPtrOut; serialFDIn = serialFDOut; setvbuf( fPtrOut, NULL, _IONBF, BUFSIZ ); fflush( fPtrOut ); // Start port config struct termios tty; memset(&tty, 0, sizeof tty ); // Error Handling if ( tcgetattr ( serialFDOut, &tty ) != 0 ) { printf( " Error from tcgetattr: %d, %s\n", errno, strerror (errno) ); fclose( fPtrOut ); close( serialFDOut ); return; } speed_t inSpeed = cfgetispeed( &tty ); speed_t outSpeed = cfgetispeed( &tty ); printf( " Existing port speed, in: %d, out: %d\n", inSpeed, outSpeed ); // Setting other Port Stuff tty.c_cflag &= ~PARENB; // Make 8n1 tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CSIZE; tty.c_cflag &= ~CRTSCTS; // no flow control tty.c_cflag |= CS8 | HUPCL; // 8 bits, enable lower control lines on close - hang up tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines tty.c_lflag = 0; // no signaling chars, no echo, no canonical processing // tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw tty.c_oflag = 0; // no remapping, no delays // tty.c_oflag &= ~OPOST; // make raw tty.c_iflag = 0; // turn off s/w flow ctrl // tty.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl tty.c_cc[VMIN] = 0; // read doesn't block tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout // Set Baud Rate if ( 0 != baud ) { if ( cfsetspeed (&tty, baud ) != 0) { printf( " Error from cfsetspeed: %d, %s\n", errno, strerror (errno) ); return; } } // Flush Port, then applies attributes if ( tcflush( serialFDOut, TCIFLUSH ) != 0) { printf( " Error from tcflush: %d, %s\n", errno, strerror (errno) ); return; } if ( tcsetattr ( serialFDOut, TCSAFLUSH, &tty ) != 0) { printf( " Error from tcsetattr: %d, %s\n", errno, strerror (errno) ); return; } // enable input & output transmission if ( tcflow(serialFDOut, TCOON | TCION) != 0) { printf( " Error from tcflow: %d, %s\n", errno, strerror (errno) ); return; } // purge buffer { char buf[1024]; int n; do { usleep( 5000 ); // 5ms n = read( serialFDOut, buf, sizeof( buf ) ); } while ( n > 0 ); } fcntl( serialFDOut, F_SETFL, 0 ); // disable blocking /**/ }
rtems_task Init( rtems_task_argument ignored ) { int sc; pid_t pid; char *term_name_p; char term_name[32]; puts( "\n\n*** TERMIOS 02 TEST ***" ); puts( "tcdrain(12) - EBADF" ); sc = tcdrain(12); rtems_test_assert( sc == -1 ); rtems_test_assert( errno == EBADF ); puts( "tcdrain(stdin) - OK" ); sc = tcdrain(0); rtems_test_assert( !sc ); puts( "tcdrain(stdout) - OK" ); tcdrain(1); rtems_test_assert( !sc ); puts( "tcdrain(stderr) - OK" ); tcdrain(2); rtems_test_assert( !sc ); puts( "" ); /***** TEST TCFLOW *****/ puts( "tcflow(stdin, TCOOFF) - ENOTSUP" ); sc = tcflow( 0, TCOOFF ); rtems_test_assert( sc == -1 ); rtems_test_assert( errno = ENOTSUP ); puts( "tcflow(stdin, TCOON) - ENOTSUP" ); sc = tcflow( 0, TCOON ); rtems_test_assert( sc == -1 ); rtems_test_assert( errno = ENOTSUP ); puts( "tcflow(stdin, TCIOFF) - ENOTSUP" ); sc = tcflow( 0, TCIOFF ); rtems_test_assert( sc == -1 ); rtems_test_assert( errno = ENOTSUP ); puts( "tcflow(stdin, TCION) - ENOTSUP" ); sc = tcflow( 0, TCION ); rtems_test_assert( sc == -1 ); rtems_test_assert( errno = ENOTSUP ); puts( "tcflow(stdin, 22) - EINVAL" ); sc = tcflow( 0, 22 ); rtems_test_assert( sc == -1 ); rtems_test_assert( errno = EINVAL ); puts( "" ); /***** TEST TCFLUSH *****/ puts( "tcflush(stdin, TCIFLUSH) - ENOTSUP" ); sc = tcflush( 0, TCIFLUSH ); rtems_test_assert( sc == -1 ); rtems_test_assert( errno = ENOTSUP ); puts( "tcflush(stdin, TCOFLUSH) - ENOTSUP" ); sc = tcflush( 0, TCOFLUSH ); rtems_test_assert( sc == -1 ); rtems_test_assert( errno = ENOTSUP ); puts( "tcflush(stdin, TCIOFLUSH) - ENOTSUP" ); sc = tcflush( 0, TCIOFLUSH ); rtems_test_assert( sc == -1 ); rtems_test_assert( errno = ENOTSUP ); puts( "tcflush(stdin, 22) - EINVAL" ); sc = tcflush( 0, 22 ); rtems_test_assert( sc == -1 ); rtems_test_assert( errno = EINVAL ); puts( "" ); /***** TEST TCGETPGRP *****/ puts( "tcgetpgrp( 1 ) - OK" ); pid = tcgetpgrp(1); rtems_test_assert( pid == getpid() ); puts( "tcsetpgrp( 1, 3 ) - OK" ); sc = tcsetpgrp( 1, 3 ); rtems_test_assert( !sc ); puts( "" ); /***** TEST TCSENDBREAK *****/ puts( "tcsendbreak( 1, 0 ) - OK" ); sc = tcsendbreak( 1, 0 ); rtems_test_assert( !sc ); puts( "" ); /***** TEST CTERMID *****/ puts( "ctermid( NULL ) - OK" ); term_name_p = ctermid( NULL ); rtems_test_assert( term_name_p ); printf( "ctermid ==> %s\n", term_name_p ); puts( "ctermid( term_name ) - OK" ); term_name_p = ctermid( term_name ); rtems_test_assert( term_name_p == term_name ); printf( "ctermid ==> %s\n", term_name_p ); puts( "*** END OF TERMIOS 02 TEST ***" ); exit( 0 ); }
int xsys_serialSetup(struct xbee_serialInfo *info) { struct termios tc; speed_t chosenbaud; if (!info) return XBEE_EMISSINGPARAM; switch (info->baudrate) { case 1200: chosenbaud = B1200; break; case 2400: chosenbaud = B2400; break; case 4800: chosenbaud = B4800; break; case 9600: chosenbaud = B9600; break; case 19200: chosenbaud = B19200; break; case 38400: chosenbaud = B38400; break; case 57600: chosenbaud = B57600; break; case 115200: chosenbaud = B115200; break; default: return XBEE_EINVAL; } if ((info->dev.fd = open(info->device, O_RDWR | O_NOCTTY | O_SYNC | O_NONBLOCK)) == -1) return XBEE_EIO; if ((info->dev.f = fdopen(info->dev.fd, "r+")) == NULL) return XBEE_EIO; fflush(info->dev.f); setvbuf(info->dev.f, NULL, _IONBF, BUFSIZ); if (tcgetattr(info->dev.fd, &tc)) { perror("tcgetattr()"); return XBEE_ESETUP; } /* input flags */ tc.c_iflag &= ~ IGNBRK; /* enable ignoring break */ tc.c_iflag &= ~(IGNPAR | PARMRK); /* disable parity checks */ tc.c_iflag &= ~ INPCK; /* disable parity checking */ tc.c_iflag &= ~ ISTRIP; /* disable stripping 8th bit */ tc.c_iflag &= ~(INLCR | ICRNL); /* disable translating NL <-> CR */ tc.c_iflag &= ~ IGNCR; /* disable ignoring CR */ tc.c_iflag &= ~(IXON | IXOFF); /* disable XON/XOFF flow control */ /* output flags */ tc.c_oflag &= ~ OPOST; /* disable output processing */ tc.c_oflag &= ~(ONLCR | OCRNL); /* disable translating NL <-> CR */ #ifdef linux /* not for FreeBSD */ tc.c_oflag &= ~ OFILL; /* disable fill characters */ #endif /* linux */ /* control flags */ tc.c_cflag |= CLOCAL; /* prevent changing ownership */ tc.c_cflag |= CREAD; /* enable reciever */ tc.c_cflag &= ~ PARENB; /* disable parity */ tc.c_cflag &= ~ CSTOPB; /* disable 2 stop bits */ tc.c_cflag &= ~ CSIZE; /* remove size flag... */ tc.c_cflag |= CS8; /* ...enable 8 bit characters */ tc.c_cflag |= HUPCL; /* enable lower control lines on close - hang up */ #ifdef XBEE_NO_RTSCTS tc.c_cflag &= ~ CRTSCTS; /* disable hardware CTS/RTS flow control */ #else tc.c_cflag |= CRTSCTS; /* enable hardware CTS/RTS flow control */ #endif /* local flags */ tc.c_lflag &= ~ ISIG; /* disable generating signals */ tc.c_lflag &= ~ ICANON; /* disable canonical mode - line by line */ tc.c_lflag &= ~ ECHO; /* disable echoing characters */ tc.c_lflag &= ~ ECHONL; /* ??? */ tc.c_lflag &= ~ NOFLSH; /* disable flushing on SIGINT */ tc.c_lflag &= ~ IEXTEN; /* disable input processing */ /* control characters */ memset(tc.c_cc,0,sizeof(tc.c_cc)); /* set i/o baud rate */ if (cfsetspeed(&tc, chosenbaud)) { perror("cfsetspeed()"); return XBEE_ESETUP; } if (tcsetattr(info->dev.fd, TCSAFLUSH, &tc)) { perror("tcsetattr()"); return XBEE_ESETUP; } /* enable input & output transmission */ #ifdef linux /* for Linux */ if (tcflow(info->dev.fd, TCOON | TCION)) { #else /* for FreeBSD */ if (tcflow(info->dev.fd, TCOON)) { #endif perror("tcflow()"); return XBEE_ESETUP; } /* purge buffer */ { char buf[1024]; int n; do { usleep(5000); /* 5ms */ n = read(info->dev.fd, buf, sizeof(buf)); } while (n > 0); } fcntl(info->dev.fd, F_SETFL, 0); /* disable blocking */ #ifndef linux /* for FreeBSD */ usleep(250000); /* it seems that the serial port takes a while to get going... */ #endif return XBEE_ENONE; } int xsys_serialShutdown(struct xbee_serialInfo *info) { if (!info) return XBEE_EMISSINGPARAM; if (info->dev.f) fclose(info->dev.f); info->dev.f = NULL; if (info->dev.fd) close(info->dev.fd); info->dev.fd = -1; return XBEE_ENONE; } int xsys_serialRead(struct xbee_serialInfo *info, int len, unsigned char *dest) { fd_set fds; int ret; int pos; if (!info || !dest) return XBEE_EMISSINGPARAM; if (info->dev.fd == -1 || !info->dev.f || len == 0) return XBEE_EINVAL; for (pos = 0; pos < len; pos += ret) { FD_ZERO(&fds); FD_SET(info->dev.fd, &fds); if (select(info->dev.fd + 1, &fds, NULL, NULL, NULL) == -1) { if (errno == EINTR) return XBEE_ESELECTINTERRUPTED; return XBEE_ESELECT; } if ((ret = fread(&(dest[pos]), 1, len - pos, info->dev.f)) > 0) continue; if (feof(info->dev.f)) { #ifndef linux /* for FreeBSD */ usleep(10000); continue; #else return XBEE_EEOF; #endif /* !linux */ } if (ferror(info->dev.f)) { perror("fread()"); return XBEE_EIO; } } return XBEE_ENONE; }
CAMLprim value unix_tcflow(value fd, value action) { if (tcflow(Int_val(fd), action_flag_table[Int_val(action)]) == -1) uerror("tcflow", Nothing); return Val_unit; }
UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, wStream* output, UINT32* abort_io) { int purge_mask; UINT32 result; UINT32 modemstate; BYTE immediate; UINT32 ret = STATUS_SUCCESS; UINT32 length = 0; UINT32 pos; DEBUG_SVC("in"); Stream_Seek(output, sizeof(UINT32)); switch (IoControlCode) { case IOCTL_SERIAL_SET_BAUD_RATE: Stream_Read_UINT32(input, tty->baud_rate); tty_set_termios(tty); DEBUG_SVC("SERIAL_SET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_GET_BAUD_RATE: length = 4; Stream_Write_UINT32(output, tty->baud_rate); DEBUG_SVC("SERIAL_GET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_SET_QUEUE_SIZE: Stream_Read_UINT32(input, tty->queue_in_size); Stream_Read_UINT32(input, tty->queue_out_size); DEBUG_SVC("SERIAL_SET_QUEUE_SIZE in %d out %d", tty->queue_in_size, tty->queue_out_size); break; case IOCTL_SERIAL_SET_LINE_CONTROL: Stream_Read_UINT8(input, tty->stop_bits); Stream_Read_UINT8(input, tty->parity); Stream_Read_UINT8(input, tty->word_length); tty_set_termios(tty); DEBUG_SVC("SERIAL_SET_LINE_CONTROL stop %d parity %d word %d", tty->stop_bits, tty->parity, tty->word_length); break; case IOCTL_SERIAL_GET_LINE_CONTROL: DEBUG_SVC("SERIAL_GET_LINE_CONTROL"); length = 3; Stream_Write_UINT8(output, tty->stop_bits); Stream_Write_UINT8(output, tty->parity); Stream_Write_UINT8(output, tty->word_length); break; case IOCTL_SERIAL_IMMEDIATE_CHAR: DEBUG_SVC("SERIAL_IMMEDIATE_CHAR"); Stream_Read_UINT8(input, immediate); tty_write_data(tty, &immediate, 1); break; case IOCTL_SERIAL_CONFIG_SIZE: DEBUG_SVC("SERIAL_CONFIG_SIZE"); length = 4; Stream_Write_UINT32(output, 0); break; case IOCTL_SERIAL_GET_CHARS: DEBUG_SVC("SERIAL_GET_CHARS"); length = 6; Stream_Write(output, tty->chars, 6); break; case IOCTL_SERIAL_SET_CHARS: DEBUG_SVC("SERIAL_SET_CHARS"); Stream_Read(input, tty->chars, 6); tty_set_termios(tty); break; case IOCTL_SERIAL_GET_HANDFLOW: length = 16; tty_get_termios(tty); Stream_Write_UINT32(output, tty->control); Stream_Write_UINT32(output, tty->xonoff); Stream_Write_UINT32(output, tty->onlimit); Stream_Write_UINT32(output, tty->offlimit); DEBUG_SVC("IOCTL_SERIAL_GET_HANDFLOW %X %X %X %X", tty->control, tty->xonoff, tty->onlimit, tty->offlimit); break; case IOCTL_SERIAL_SET_HANDFLOW: Stream_Read_UINT32(input, tty->control); Stream_Read_UINT32(input, tty->xonoff); Stream_Read_UINT32(input, tty->onlimit); Stream_Read_UINT32(input, tty->offlimit); DEBUG_SVC("IOCTL_SERIAL_SET_HANDFLOW %X %X %X %X", tty->control, tty->xonoff, tty->onlimit, tty->offlimit); tty_set_termios(tty); break; case IOCTL_SERIAL_SET_TIMEOUTS: Stream_Read_UINT32(input, tty->read_interval_timeout); Stream_Read_UINT32(input, tty->read_total_timeout_multiplier); Stream_Read_UINT32(input, tty->read_total_timeout_constant); Stream_Read_UINT32(input, tty->write_total_timeout_multiplier); Stream_Read_UINT32(input, tty->write_total_timeout_constant); /* http://www.codeproject.com/KB/system/chaiyasit_t.aspx, see 'ReadIntervalTimeout' section http://msdn.microsoft.com/en-us/library/ms885171.aspx */ if (tty->read_interval_timeout == SERIAL_TIMEOUT_MAX) { tty->read_interval_timeout = 0; tty->read_total_timeout_multiplier = 0; } DEBUG_SVC("SERIAL_SET_TIMEOUTS read timeout %d %d %d", tty->read_interval_timeout, tty->read_total_timeout_multiplier, tty->read_total_timeout_constant); break; case IOCTL_SERIAL_GET_TIMEOUTS: DEBUG_SVC("SERIAL_GET_TIMEOUTS read timeout %d %d %d", tty->read_interval_timeout, tty->read_total_timeout_multiplier, tty->read_total_timeout_constant); length = 20; Stream_Write_UINT32(output, tty->read_interval_timeout); Stream_Write_UINT32(output, tty->read_total_timeout_multiplier); Stream_Write_UINT32(output, tty->read_total_timeout_constant); Stream_Write_UINT32(output, tty->write_total_timeout_multiplier); Stream_Write_UINT32(output, tty->write_total_timeout_constant); break; case IOCTL_SERIAL_GET_WAIT_MASK: DEBUG_SVC("SERIAL_GET_WAIT_MASK %X", tty->wait_mask); length = 4; Stream_Write_UINT32(output, tty->wait_mask); break; case IOCTL_SERIAL_SET_WAIT_MASK: Stream_Read_UINT32(input, tty->wait_mask); DEBUG_SVC("SERIAL_SET_WAIT_MASK %X", tty->wait_mask); break; case IOCTL_SERIAL_SET_DTR: DEBUG_SVC("SERIAL_SET_DTR"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); tty->dtr = 1; break; case IOCTL_SERIAL_CLR_DTR: DEBUG_SVC("SERIAL_CLR_DTR"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); tty->dtr = 0; break; case IOCTL_SERIAL_SET_RTS: DEBUG_SVC("SERIAL_SET_RTS"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); tty->rts = 1; break; case IOCTL_SERIAL_CLR_RTS: DEBUG_SVC("SERIAL_CLR_RTS"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); tty->rts = 0; break; case IOCTL_SERIAL_GET_MODEMSTATUS: modemstate = 0; #ifdef TIOCMGET ioctl(tty->fd, TIOCMGET, &result); if (result & TIOCM_CTS) modemstate |= SERIAL_MS_CTS; if (result & TIOCM_DSR) modemstate |= SERIAL_MS_DSR; if (result & TIOCM_RNG) modemstate |= SERIAL_MS_RNG; if (result & TIOCM_CAR) modemstate |= SERIAL_MS_CAR; if (result & TIOCM_DTR) modemstate |= SERIAL_MS_DTR; if (result & TIOCM_RTS) modemstate |= SERIAL_MS_RTS; #endif DEBUG_SVC("SERIAL_GET_MODEMSTATUS %X", modemstate); length = 4; Stream_Write_UINT32(output, modemstate); break; case IOCTL_SERIAL_GET_COMMSTATUS: length = 18; Stream_Write_UINT32(output, 0); /* Errors */ Stream_Write_UINT32(output, 0); /* Hold reasons */ result = 0; #ifdef TIOCINQ ioctl(tty->fd, TIOCINQ, &result); #endif Stream_Write_UINT32(output, result); /* Amount in in queue */ if (result) DEBUG_SVC("SERIAL_GET_COMMSTATUS in queue %d", result); result = 0; #ifdef TIOCOUTQ ioctl(tty->fd, TIOCOUTQ, &result); #endif Stream_Write_UINT32(output, result); /* Amount in out queue */ DEBUG_SVC("SERIAL_GET_COMMSTATUS out queue %d", result); Stream_Write_UINT8(output, 0); /* EofReceived */ Stream_Write_UINT8(output, 0); /* WaitForImmediate */ break; case IOCTL_SERIAL_PURGE: Stream_Read_UINT32(input, purge_mask); DEBUG_SVC("SERIAL_PURGE purge_mask %X", purge_mask); /* See http://msdn.microsoft.com/en-us/library/ms901431.aspx PURGE_TXCLEAR Clears the output buffer, if the driver has one. PURGE_RXCLEAR Clears the input buffer, if the driver has one. It clearly states to clear the *driver* buffer, not the port buffer */ #ifdef DEBUG_SVC if (purge_mask & SERIAL_PURGE_TXCLEAR) DEBUG_SVC("Ignoring SERIAL_PURGE_TXCLEAR"); if (purge_mask & SERIAL_PURGE_RXCLEAR) DEBUG_SVC("Ignoring SERIAL_PURGE_RXCLEAR"); #endif if (purge_mask & SERIAL_PURGE_TXABORT) *abort_io |= SERIAL_ABORT_IO_WRITE; if (purge_mask & SERIAL_PURGE_RXABORT) *abort_io |= SERIAL_ABORT_IO_READ; break; case IOCTL_SERIAL_WAIT_ON_MASK: DEBUG_SVC("SERIAL_WAIT_ON_MASK %X", tty->wait_mask); tty->event_pending = 1; length = 4; if (serial_tty_get_event(tty, &result)) { DEBUG_SVC("WAIT end event = %X", result); Stream_Write_UINT32(output, result); break; } ret = STATUS_PENDING; break; case IOCTL_SERIAL_SET_BREAK_ON: DEBUG_SVC("SERIAL_SET_BREAK_ON"); tcsendbreak(tty->fd, 0); break; case IOCTL_SERIAL_RESET_DEVICE: DEBUG_SVC("SERIAL_RESET_DEVICE"); break; case IOCTL_SERIAL_SET_BREAK_OFF: DEBUG_SVC("SERIAL_SET_BREAK_OFF"); break; case IOCTL_SERIAL_SET_XOFF: DEBUG_SVC("SERIAL_SET_XOFF"); break; case IOCTL_SERIAL_SET_XON: DEBUG_SVC("SERIAL_SET_XON"); tcflow(tty->fd, TCION); break; default: DEBUG_SVC("NOT FOUND IoControlCode SERIAL IOCTL %d", IoControlCode); return STATUS_INVALID_PARAMETER; } /* Write OutputBufferLength */ pos = Stream_GetPosition(output); Stream_SetPosition(output, 16); Stream_Write_UINT32(output, length); Stream_SetPosition(output, pos); return ret; }
static uint32 serial_control(IRP * irp) { int flush_mask, purge_mask; uint32 result, modemstate; uint8 immediate; int size = 0, ret = RD_STATUS_SUCCESS; SERIAL_DEVICE_INFO *info = (SERIAL_DEVICE_INFO *) irp->dev->info; char *inbuf = irp->inputBuffer; char *outbuf = NULL; /* the server commands, we obbey */ switch (irp->ioControlCode) { case IOCTL_SERIAL_SET_BAUD_RATE: info->baud_rate = GET_UINT32(inbuf, 0); set_termios(info); LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BAUD_RATE %d", info->baud_rate)); break; case IOCTL_SERIAL_GET_BAUD_RATE: size = 4; outbuf = malloc(size); SET_UINT32(outbuf, 0, info->baud_rate); LLOGLN(10, ("serial_ioctl -> SERIAL_GET_BAUD_RATE %d", info->baud_rate)); break; case IOCTL_SERIAL_SET_QUEUE_SIZE: info->queue_in_size = GET_UINT32(inbuf, 0); info->queue_out_size = GET_UINT32(inbuf, 4); LLOGLN(10, ("serial_ioctl -> SERIAL_SET_QUEUE_SIZE in %d out %d", info->queue_in_size, info->queue_out_size)); break; case IOCTL_SERIAL_SET_LINE_CONTROL: info->stop_bits = GET_UINT8(inbuf, 0); info->parity = GET_UINT8(inbuf, 1); info->word_length = GET_UINT8(inbuf, 2); set_termios(info); LLOGLN(10, ("serial_ioctl -> SERIAL_SET_LINE_CONTROL stop %d parity %d word %d", info->stop_bits, info->parity, info->word_length)); break; case IOCTL_SERIAL_GET_LINE_CONTROL: LLOGLN(10, ("serial_ioctl -> SERIAL_GET_LINE_CONTROL")); size = 3; outbuf = malloc(size); SET_UINT8(outbuf, 0, info->stop_bits); SET_UINT8(outbuf, 1, info->parity); SET_UINT8(outbuf, 2, info->word_length); break; case IOCTL_SERIAL_IMMEDIATE_CHAR: LLOGLN(10, ("serial_ioctl -> SERIAL_IMMEDIATE_CHAR")); immediate = GET_UINT8(inbuf, 0); serial_write_data(irp, &immediate, 1); break; case IOCTL_SERIAL_CONFIG_SIZE: LLOGLN(10, ("serial_ioctl -> SERIAL_CONFIG_SIZE")); size = 4; outbuf = malloc(size); SET_UINT32(outbuf, 0, 0); break; case IOCTL_SERIAL_GET_CHARS: LLOGLN(10, ("serial_ioctl -> SERIAL_GET_CHARS")); size = 6; outbuf = malloc(size); memcpy(outbuf, info->chars, size); break; case IOCTL_SERIAL_SET_CHARS: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_CHARS")); memcpy(info->chars, inbuf, 6); set_termios(info); break; case IOCTL_SERIAL_GET_HANDFLOW: LLOGLN(10, ("serial_ioctl -> IOCTL_SERIAL_GET_HANDFLOW")); size = 16; outbuf = malloc(size); get_termios(info); SET_UINT32(outbuf, 0, info->control); SET_UINT32(outbuf, 4, info->xonoff); SET_UINT32(outbuf, 8, info->onlimit); SET_UINT32(outbuf, 12, info->offlimit); break; case IOCTL_SERIAL_SET_HANDFLOW: info->control = GET_UINT32(inbuf, 0); info->xonoff = GET_UINT32(inbuf, 4); info->onlimit = GET_UINT32(inbuf, 8); info->offlimit = GET_UINT32(inbuf, 12); LLOGLN(10, ("serial_ioctl -> IOCTL_SERIAL_SET_HANDFLOW %x %x %x %x", info->control, info->xonoff, info->onlimit, info->onlimit)); set_termios(info); break; case IOCTL_SERIAL_SET_TIMEOUTS: info->read_interval_timeout = GET_UINT32(inbuf, 0); info->read_total_timeout_multiplier = GET_UINT32(inbuf, 4); info->read_total_timeout_constant = GET_UINT32(inbuf, 8); info->write_total_timeout_multiplier = GET_UINT32(inbuf, 12); info->write_total_timeout_constant = GET_UINT32(inbuf, 16); /* http://www.codeproject.com/KB/system/chaiyasit_t.aspx, see 'ReadIntervalTimeout' section http://msdn.microsoft.com/en-us/library/ms885171.aspx */ if (info->read_interval_timeout == SERIAL_TIMEOUT_MAX) { info->read_interval_timeout = 0; info->read_total_timeout_multiplier = 0; } LLOGLN(10, ("serial_ioctl -> SERIAL_SET_TIMEOUTS read timeout %d %d %d", info->read_interval_timeout, info->read_total_timeout_multiplier, info->read_total_timeout_constant)); break; case IOCTL_SERIAL_GET_TIMEOUTS: LLOGLN(10, ("serial_ioctl -> SERIAL_GET_TIMEOUTS read timeout %d %d %d", info->read_interval_timeout, info->read_total_timeout_multiplier, info->read_total_timeout_constant)); size = 20; outbuf = malloc(size); SET_UINT32(outbuf, 0, info->read_interval_timeout); SET_UINT32(outbuf, 4, info->read_total_timeout_multiplier); SET_UINT32(outbuf, 8, info->read_total_timeout_constant); SET_UINT32(outbuf, 12, info->write_total_timeout_multiplier); SET_UINT32(outbuf, 16, info->write_total_timeout_constant); break; case IOCTL_SERIAL_GET_WAIT_MASK: LLOGLN(10, ("serial_ioctl -> SERIAL_GET_WAIT_MASK %X", info->wait_mask)); size = 4; outbuf = malloc(size); SET_UINT32(outbuf, 0, info->wait_mask); break; case IOCTL_SERIAL_SET_WAIT_MASK: info->wait_mask = GET_UINT32(inbuf, 0); LLOGLN(10, ("serial_ioctl -> SERIAL_SET_WAIT_MASK %X", info->wait_mask)); break; case IOCTL_SERIAL_SET_DTR: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_DTR")); ioctl(info->file, TIOCMGET, &result); result |= TIOCM_DTR; ioctl(info->file, TIOCMSET, &result); info->dtr = 1; break; case IOCTL_SERIAL_CLR_DTR: LLOGLN(10, ("serial_ioctl -> SERIAL_CLR_DTR")); ioctl(info->file, TIOCMGET, &result); result &= ~TIOCM_DTR; ioctl(info->file, TIOCMSET, &result); info->dtr = 0; break; case IOCTL_SERIAL_SET_RTS: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_RTS")); ioctl(info->file, TIOCMGET, &result); result |= TIOCM_RTS; ioctl(info->file, TIOCMSET, &result); info->rts = 1; break; case IOCTL_SERIAL_CLR_RTS: LLOGLN(10, ("serial_ioctl -> SERIAL_CLR_RTS")); ioctl(info->file, TIOCMGET, &result); result &= ~TIOCM_RTS; ioctl(info->file, TIOCMSET, &result); info->rts = 0; break; case IOCTL_SERIAL_GET_MODEMSTATUS: modemstate = 0; #ifdef TIOCMGET ioctl(info->file, TIOCMGET, &result); if (result & TIOCM_CTS) modemstate |= SERIAL_MS_CTS; if (result & TIOCM_DSR) modemstate |= SERIAL_MS_DSR; if (result & TIOCM_RNG) modemstate |= SERIAL_MS_RNG; if (result & TIOCM_CAR) modemstate |= SERIAL_MS_CAR; if (result & TIOCM_DTR) modemstate |= SERIAL_MS_DTR; if (result & TIOCM_RTS) modemstate |= SERIAL_MS_RTS; #endif LLOGLN(10, ("serial_ioctl -> SERIAL_GET_MODEMSTATUS %X", modemstate)); size = 4; outbuf = malloc(size); SET_UINT32(outbuf, 0, modemstate); break; case IOCTL_SERIAL_GET_COMMSTATUS: size = 18; outbuf = malloc(size); SET_UINT32(outbuf, 0, 0); /* Errors */ SET_UINT32(outbuf, 4, 0); /* Hold reasons */ result = 0; #ifdef TIOCINQ ioctl(info->file, TIOCINQ, &result); #endif SET_UINT32(outbuf, 8, result); /* Amount in in queue */ if (result) LLOGLN(10, ("serial_ioctl -> SERIAL_GET_COMMSTATUS in queue %d", result)); result = 0; #ifdef TIOCOUTQ ioctl(info->file, TIOCOUTQ, &result); #endif SET_UINT32(outbuf, 12, result); /* Amount in out queue */ LLOGLN(10, ("serial_ioctl -> SERIAL_GET_COMMSTATUS out queue %d", result)); SET_UINT8(outbuf, 16, 0); /* EofReceived */ SET_UINT8(outbuf, 17, 0); /* WaitForImmediate */ break; case IOCTL_SERIAL_PURGE: purge_mask = GET_UINT32(inbuf, 0); LLOGLN(10, ("serial_ioctl -> SERIAL_PURGE purge_mask %X", purge_mask)); flush_mask = 0; if (purge_mask & SERIAL_PURGE_TXCLEAR) flush_mask |= TCOFLUSH; if (purge_mask & SERIAL_PURGE_RXCLEAR) flush_mask |= TCIFLUSH; if (flush_mask != 0) tcflush(info->file, flush_mask); if (purge_mask & SERIAL_PURGE_TXABORT) irp->abortIO |= RDPDR_ABORT_IO_WRITE; if(purge_mask & SERIAL_PURGE_RXABORT) irp->abortIO |= RDPDR_ABORT_IO_READ; break; case IOCTL_SERIAL_WAIT_ON_MASK: LLOGLN(10, ("serial_ioctl -> SERIAL_WAIT_ON_MASK %X", info->wait_mask)); info->event_pending = 1; if (serial_get_event(irp, &result)) { size = 4; outbuf = malloc(size); LLOGLN(10, ("WAIT end event = %x", result)); SET_UINT32(outbuf, 0, result); break; } irp->outputBufferLength = 4; ret = RD_STATUS_PENDING; break; case IOCTL_SERIAL_SET_BREAK_ON: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BREAK_ON")); tcsendbreak(info->file, 0); break; case IOCTL_SERIAL_RESET_DEVICE: LLOGLN(10, ("serial_ioctl -> SERIAL_RESET_DEVICE")); break; case IOCTL_SERIAL_SET_BREAK_OFF: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BREAK_OFF")); break; case IOCTL_SERIAL_SET_XOFF: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_XOFF")); break; case IOCTL_SERIAL_SET_XON: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_XON")); tcflow(info->file, TCION); break; default: LLOGLN(10, ("NOT FOUND IoControlCode SERIAL IOCTL %d", irp->ioControlCode)); return RD_STATUS_INVALID_PARAMETER; } irp->outputBuffer = outbuf; irp->outputBufferLength = size; return ret; }
// thread main! int uart_unix_main(void* arg) { dthread_t* self = (dthread_t*) arg; dthread_t* other = (dthread_t*) self->arg; dmessage_t* mp = NULL; dthread_poll_event_t ev, *evp; size_t nev; dterm_t term; uart_ctx_t ctx; ErlDrvTermData mp_from; ErlDrvTermData mp_ref; dthread_t* mp_source; int tmo; int r; DEBUGF("uart_unix: thread started"); uart_init(&ctx, self, other); dterm_init(&term); again_tmo: tmo = next_timeout(&ctx); again: nev = 0; evp = NULL; if (ctx.fd >= 0) { ev.event = (ErlDrvEvent) ((long)ctx.fd); ev.events = 0; if ((ctx.option.active != UART_PASSIVE) || ctx.recv) { ev.events |= ERL_DRV_READ; if (ctx.option.ptypkt && (ctx.fd != ctx.tty_fd)) ev.events |= ERL_DRV_EXCEP; } if (ctx.oq.mesg) ev.events |= ERL_DRV_WRITE; if (ev.events) { evp = &ev; nev = 1; } DEBUGF("ctx.fd=%d, ev.events=%d", ctx.fd, ev.events); } DEBUGF("uart_unix_main: nev=%d, events=%x, timeout = %d", nev, ev.events, tmo); r = dthread_poll(self, evp, &nev, tmo); if (r < 0) { DEBUGF("uart_unix_main: dthread_poll failed=%d", r); goto again_tmo; } else { DEBUGF("uart_unix_main: nev=%d, r=%d", nev, r); if (evp && (nev == 1)) { if (evp->revents & ERL_DRV_WRITE) process_output(&ctx, self); if (evp->revents & (ERL_DRV_READ|ERL_DRV_EXCEP)) { while((process_input(&ctx, self, 0) == 1) && (ctx.option.active != UART_PASSIVE)) ; } } tmo = next_timeout(&ctx); DEBUGF("uart_unix_main: timeout = %d", tmo); if (ctx.recv) { if (tmo == 0) { uart_async_error_am(&ctx, ctx.dport, ctx.caller, am_timeout); clear_timeout(&ctx); ctx.remain = 0; } } if (r == 0) goto again; // r>0 (number of messages) DEBUGF("about to receive message r=%d", r); if ((mp = dthread_recv(self, NULL)) == NULL) { DEBUGF("uart_unix_main: message was NULL"); goto again; } mp_from = mp->from; mp_ref = mp->ref; mp_source = mp->source; switch (mp->cmd) { case DTHREAD_STOP: DEBUGF("uart_unix_main: STOP"); close_device(&ctx); uart_final(&ctx); dmessage_free(mp); DEBUGF("uart_unix_main: EXIT"); dthread_exit(0); break; case DTHREAD_OUTPUT: // async send! DEBUGF("uart_unix_main: OUTPUT"); if (ctx.fd < 0) { dmessage_free(mp); goto again; } if (enq_output(&ctx, self, mp, 0) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_CONNECT: { ErlDrvTermData owner; if (mp->used != 0) goto badarg; owner = driver_connected(self->port); self->owner = owner; other->owner = owner; goto ok; } case UART_CMD_CLOSE: DEBUGF("uart_unix_main: CLOSE"); close_device(&ctx); goto ok; case UART_CMD_SEND: // sync send DEBUGF("uart_unix_main: SEND"); if (ctx.fd < 0) goto ebadf; if (enq_output(&ctx, self, mp, mp_from) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_SENDCHAR: // sync send DEBUGF("uart_unix_main: SENDCHAR"); if (ctx.fd < 0) goto ebadf; if (enq_output(&ctx, self, mp, mp_from) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_RECV: { // <<Time:32, Length:32>> Time=0xffffffff=inf uint32_t tm; int len; DEBUGF("uart_unix_main: RECV"); if (ctx.fd < 0) goto ebadf; if (ctx.recv) goto ealready; if (mp->used != 8) goto badarg; if (ctx.option.active != UART_PASSIVE) goto badarg; tm = get_uint32((uint8_t*) mp->buffer); len = (int) get_uint32((uint8_t*) (mp->buffer+4)); if ((len < 0) || (len > UART_MAX_PACKET_SIZE)) goto badarg; ctx.ref = mp_ref; ctx.caller = mp_from; set_timeout(&ctx, tm); ctx.recv = 1; DEBUGF("recv timeout %lu", tm); process_input(&ctx, self, len); dmessage_free(mp); goto again_tmo; } case UART_CMD_UNRECV: { // argument is data to push back uart_buf_push(&ctx.ib, mp->buffer, mp->used); DEBUGF("unrecived %d bytes", ctx.ib.ptr - ctx.ib.ptr_start); if (ctx.option.active != UART_PASSIVE) { while((process_input(&ctx, self, 0) == 1) && (ctx.option.active != UART_PASSIVE)) ; } goto ok; } case UART_CMD_SETOPTS: { uart_com_state_t state = ctx.state; uart_opt_t option = ctx.option; uint32_t sflags = ctx.sflags; // parse & update options in state,option and sflag if (uart_parse_opts(mp->buffer, mp->used, &state, &option, &sflags) < 0) goto badarg; // apply the changed values if ((r=apply_opts(&ctx, &state, &option, sflags)) < 0) goto error; if (r == 1) { while((process_input(&ctx, self, 0) == 1) && (ctx.option.active != UART_PASSIVE)) ; } goto ok; } case UART_CMD_GETOPTS: { dterm_mark_t m1; dterm_mark_t m2; // {Ref, {ok,List}} || {Ref, {error,Reason}} dterm_tuple_begin(&term, &m1); { dterm_uint(&term, mp_ref); dterm_tuple_begin(&term, &m2); { dterm_atom(&term, am_ok); if (uart_get_opts(&term, &ctx,(uint8_t*)mp->buffer,mp->used) < 0) { dterm_reset(&term); goto badarg; } } dterm_tuple_end(&term, &m2); } dterm_tuple_end(&term, &m1); dthread_port_send_dterm(mp_source, self, mp_from, &term); dterm_reset(&term); dmessage_free(mp); goto again; } case UART_CMD_GET_MODEM: { dterm_mark_t m1; dterm_mark_t m2; uart_modem_state_t mstate; if (ctx.tty_fd < 0) goto ebadf; if (get_modem_state(ctx.tty_fd, &mstate) < 0) goto error; dterm_tuple_begin(&term, &m1); { dterm_uint(&term, mp_ref); dterm_tuple_begin(&term, &m2); { dterm_atom(&term, am_ok); modem_state_dterm(&term, mstate); } dterm_tuple_end(&term, &m2); } dterm_tuple_end(&term, &m1); dthread_port_send_dterm(mp_source, self, mp_from, &term); dterm_reset(&term); dmessage_free(mp); goto again; } case UART_CMD_SET_MODEM: { uart_modem_state_t mstate; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 4) goto badarg; mstate = (uart_modem_state_t) get_uint32((uint8_t*) mp->buffer); if (set_modem_state(ctx.tty_fd, mstate, 1) < 0) goto error; goto ok; } case UART_CMD_CLR_MODEM: { uart_modem_state_t mstate; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 4) goto badarg; mstate = (uart_modem_state_t) get_uint32((uint8_t*) mp->buffer); if (set_modem_state(ctx.tty_fd, mstate, 0) < 0) goto error; goto ok; } case UART_CMD_HANGUP: { struct termios tio; int r; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 0) goto badarg; if ((r = tcgetattr(ctx.tty_fd, &tio)) < 0) { INFOF("tcgetattr: error=%s\n", strerror(errno)); goto badarg; } cfsetispeed(&tio, B0); cfsetospeed(&tio, B0); if ((r = tcsetattr(ctx.tty_fd, TCSANOW, &tio)) < 0) { INFOF("tcsetattr: error=%s\n", strerror(errno)); goto badarg; } goto ok; } case UART_CMD_BREAK: { int duration; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 4) goto badarg; duration = (int) get_uint32((uint8_t*) mp->buffer); if (tcsendbreak(ctx.tty_fd, duration) < 0) goto error; goto ok; } case UART_CMD_FLOW: if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 1) goto badarg; switch(mp->buffer[0]) { case 0: r = tcflow(ctx.tty_fd, TCIOFF); break; case 1: r = tcflow(ctx.tty_fd, TCION); break; case 2: r = tcflow(ctx.tty_fd, TCOOFF); break; case 3: r = tcflow(ctx.tty_fd, TCOON); break; default: goto badarg; break; } if (r < 0) goto error; goto ok; default: goto badarg; } } ok: dthread_port_send_ok(mp_source, self, mp_from, mp_ref); if (mp) dmessage_free(mp); goto again; ebadf: errno = EBADF; goto error; badarg: errno = EINVAL; goto error; ealready: errno = EALREADY; goto error; error: dthread_port_send_error(mp_source, self, mp_from, mp_ref, uart_errno(&ctx)); if (mp) dmessage_free(mp); goto again; }
void *Commander::XBeeThreadProc(void *pv) { Commander *pcmdr = (Commander*)pv; fd_set readfs; // file descriptor set to wait on. timeval tv; // how long to wait. // printf("Thread start(%s)\n", pcmdr->_pszDevice); // Lets do our init of the xbee here. // We will do all of the stuff to intialize the serial port plus we will spawn off our thread. struct termios tc; if ((pcmdr->fdXBee = open(pcmdr->_pszDevice, O_RDWR | O_NOCTTY | O_SYNC /* | O_NONBLOCK */)) == -1) { printf("Open Failed\n"); return 0; } if ((pcmdr->pfileXBee = fdopen(pcmdr->fdXBee, "r+")) == NULL) { return 0; } setvbuf(pcmdr->pfileXBee, NULL, _IONBF, BUFSIZ); fflush(pcmdr->pfileXBee); if (tcgetattr(pcmdr->fdXBee, &tc)) { perror("tcgetattr()"); return 0; } /* input flags */ tc.c_iflag &= ~ IGNBRK; /* enable ignoring break */ tc.c_iflag &= ~(IGNPAR | PARMRK); /* disable parity checks */ tc.c_iflag &= ~ INPCK; /* disable parity checking */ tc.c_iflag &= ~ ISTRIP; /* disable stripping 8th bit */ tc.c_iflag &= ~(INLCR | ICRNL); /* disable translating NL <-> CR */ tc.c_iflag &= ~ IGNCR; /* disable ignoring CR */ tc.c_iflag &= ~(IXON | IXOFF); /* disable XON/XOFF flow control */ /* output flags */ tc.c_oflag &= ~ OPOST; /* disable output processing */ tc.c_oflag &= ~(ONLCR | OCRNL); /* disable translating NL <-> CR */ /* not for FreeBSD */ tc.c_oflag &= ~ OFILL; /* disable fill characters */ /* control flags */ tc.c_cflag |= CLOCAL; /* prevent changing ownership */ tc.c_cflag |= CREAD; /* enable reciever */ tc.c_cflag &= ~ PARENB; /* disable parity */ tc.c_cflag &= ~ CSTOPB; /* disable 2 stop bits */ tc.c_cflag &= ~ CSIZE; /* remove size flag... */ tc.c_cflag |= CS8; /* ...enable 8 bit characters */ tc.c_cflag |= HUPCL; /* enable lower control lines on close - hang up */ #ifdef XBEE_NO_RTSCTS tc.c_cflag &= ~ CRTSCTS; /* disable hardware CTS/RTS flow control */ #else tc.c_cflag |= CRTSCTS; /* enable hardware CTS/RTS flow control */ #endif /* local flags */ tc.c_lflag &= ~ ISIG; /* disable generating signals */ tc.c_lflag &= ~ ICANON; /* disable canonical mode - line by line */ tc.c_lflag &= ~ ECHO; /* disable echoing characters */ tc.c_lflag &= ~ ECHONL; /* ??? */ tc.c_lflag &= ~ NOFLSH; /* disable flushing on SIGINT */ tc.c_lflag &= ~ IEXTEN; /* disable input processing */ /* control characters */ memset(tc.c_cc,0,sizeof(tc.c_cc)); /* set i/o baud rate */ if (cfsetspeed(&tc, pcmdr->_baud)) { perror("cfsetspeed()"); return 0; } if (tcsetattr(pcmdr->fdXBee, TCSAFLUSH, &tc)) { perror("tcsetattr()"); return 0; } /* enable input & output transmission */ if (tcflow(pcmdr->fdXBee, TCOON | TCION)) { perror("tcflow()"); return 0; } fflush(pcmdr->pfileXBee); // again discard anything we have not read... // printf("Thread Init\n"); // May want to add end code... But for now don't have any defined... int ch; while(!pcmdr->_fCancel) { // Lets try using select to block our thread until we have some input available... FD_ZERO(&readfs); FD_SET(pcmdr->fdXBee, &readfs); // Make sure we are set to wait for our descriptor tv.tv_sec = 0; tv.tv_usec = 250000; // 1/4 of a second... // wait until some input is available... select(pcmdr->fdXBee + 1, &readfs, NULL, NULL, &tv); while((!pcmdr->_fCancel) && (ch = getc(pcmdr->pfileXBee)) != EOF) { if(pcmdr->index == -1) // looking for new packet { if(ch == 0xff) { pcmdr->index = 0; pcmdr->checksum = 0; } } else if(pcmdr->index == 0) { pcmdr->bInBuf[pcmdr->index] = (unsigned char) ch; if(pcmdr->bInBuf[pcmdr->index] != 0xff) { pcmdr->checksum += ch; pcmdr->index++; } } else { pcmdr->bInBuf[pcmdr->index] = (unsigned char) ch; pcmdr->checksum += ch; pcmdr->index++; if(pcmdr->index == 7) // packet complete { if(pcmdr->checksum%256 == 255) { // Lets grab our mutex to keep things consistent pthread_mutex_lock(&pcmdr->lock); for (int i=0; i < 6; i++) pcmdr->vals[i] = pcmdr->bInBuf[i]; pcmdr->fValidPacket = true; pthread_mutex_unlock(&pcmdr->lock); } pcmdr->index = -1; // Say we are ready to start looking for start of next message... } } } // If we get to here try sleeping for a little time usleep(1000); // Note: we could maybe simply block the thread until input available! } printf("Commander - XBee thread exit\n"); return 0; }
s48_ref_t sch_tcflow(s48_call_t call, s48_ref_t sch_fd, s48_ref_t sch_action) { if (tcflow (s48_extract_long_2(call, sch_fd), s48_extract_long_2(call, sch_action)) == -1) s48_os_error_2(call, "sch_tcflow", errno, 2, sch_fd, sch_action); return s48_unspecific_2(call); }