1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /* serial port functions
5 * Author: Chris Toshok <toshok@ximian.com>
13 #include <sys/ioctl.h>
18 /* This is for FIONREAD on solaris */
20 #include <sys/filio.h>
23 /* This is a copy of System.IO.Ports.Handshake */
28 RequestToSendXOnXOff = 3
31 /* This is a copy of System.IO.Ports.Parity */
40 /* This is a copy of System.IO.Ports.StopBits */
48 /* This is a copy of System.IO.Ports.SerialSignal */
51 Cd = 1, /* Carrier detect */
52 Cts = 2, /* Clear to send */
53 Dsr = 4, /* Data set ready */
54 Dtr = 8, /* Data terminal ready */
55 Rts = 16 /* Request to send */
59 open_serial (char* devfile)
62 fd = open (devfile, O_RDWR | O_NOCTTY | O_NONBLOCK);
71 close_serial (int unix_fd)
77 read_serial (int fd, guchar *buffer, int offset, int count)
81 n = read (fd, buffer + offset, count);
87 write_serial (int fd, guchar *buffer, int offset, int count, int timeout)
96 tmval.tv_sec = timeout / 1000;
97 tmval.tv_usec = (timeout - tmval.tv_sec) * 1000;
105 if (select(fd+1, NULL, &writefs, NULL, &tmval) <= 0 && errno != EINTR)
111 t = write(fd, buffer + offset, count);
115 if (select(fd+1, NULL, &writefs, NULL, &tmval) <= 0 && errno != EINTR)
129 discard_buffer (int fd, gboolean input)
131 tcflush(fd, input ? TCIFLUSH : TCOFLUSH);
135 get_bytes_in_buffer (int fd, gboolean input)
139 if (ioctl (fd, input ? FIONREAD : TIOCOUTQ, &retval) == -1) {
147 set_attributes (int fd, int baud_rate, MonoParity parity, int dataBits, MonoStopBits stopBits, MonoHandshake handshake)
149 struct termios newtio;
151 tcgetattr (fd, &newtio);
152 newtio.c_cflag |= (CLOCAL | CREAD);
153 newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | IEXTEN );
154 newtio.c_oflag &= ~(OPOST);
155 newtio.c_iflag = IGNBRK;
219 newtio.c_cflag &= ~CSIZE;
223 newtio.c_cflag |= CS5;
226 newtio.c_cflag |= CS6;
229 newtio.c_cflag |= CS7;
233 newtio.c_cflag |= CS8;
244 /* do nothing, the default is one stop bit */
245 newtio.c_cflag &= ~CSTOPB;
248 newtio.c_cflag |= CSTOPB;
250 case OnePointFive: /* OnePointFive */
256 newtio.c_iflag &= ~(INPCK | ISTRIP );
260 case NoneParity: /* None */
261 newtio.c_cflag &= ~(PARENB | PARODD);
265 newtio.c_cflag |= PARENB | PARODD;
268 case Even: /* Even */
269 newtio.c_cflag &= ~(PARODD);
272 case Mark: /* Mark */
275 case Space: /* Space */
280 newtio.c_iflag &= ~(IXOFF | IXON);
282 newtio.c_cflag &= ~CRTSCTS;
283 #endif /* def CRTSCTS */
287 case NoneHandshake: /* None */
290 case RequestToSend: /* RequestToSend (RTS) */
292 newtio.c_cflag |= CRTSCTS;
293 #endif /* def CRTSCTS */
295 case RequestToSendXOnXOff: /* RequestToSendXOnXOff (RTS + XON/XOFF) */
297 newtio.c_cflag |= CRTSCTS;
298 #endif /* def CRTSCTS */
300 case XOnXOff: /* XOnXOff */
301 newtio.c_iflag |= IXOFF | IXON;
305 if (cfsetospeed (&newtio, baud_rate) < 0 || cfsetispeed (&newtio, baud_rate) < 0 ||
306 tcsetattr (fd, TCSANOW, &newtio) < 0)
318 get_signal_code (MonoSerialSignal signal)
339 static MonoSerialSignal
340 get_mono_signal_codes (int signals)
342 MonoSerialSignal retval = NoneSignal;
344 if ((signals & TIOCM_CAR) != 0)
346 if ((signals & TIOCM_CTS) != 0)
348 if ((signals & TIOCM_DSR) != 0)
350 if ((signals & TIOCM_DTR) != 0)
352 if ((signals & TIOCM_RTS) != 0)
359 get_signals (int fd, gint32 *error)
365 if (ioctl (fd, TIOCMGET, &signals) == -1) {
370 return get_mono_signal_codes (signals);
374 set_signal (int fd, MonoSerialSignal signal, gboolean value)
376 int signals, expected, activated;
378 expected = get_signal_code (signal);
379 if (ioctl (fd, TIOCMGET, &signals) == -1)
382 activated = (signals & expected) != 0;
383 if (activated == value) /* Already set */
389 signals &= ~expected;
391 if (ioctl (fd, TIOCMSET, &signals) == -1)
398 poll_serial (int fd, gint32 *error, int timeout)
405 pinfo.events = POLLIN;
408 while (poll (&pinfo, 1, timeout) == -1 && errno == EINTR) {
409 /* EINTR is an OK condition, we should not throw in the upper layer an IOException */
416 return (pinfo.revents & POLLIN) != 0 ? 1 : 0;
420 * mono internals should not be used here.
421 * this serial stuff needs to be implemented with icalls.
422 * make this at least compile until the code is moved elsewhere
423 * defined(linux) is wrong, too
426 list_serial_devices (void)
433 list_serial_devices (void)
437 /* Linux serial files are of the form ttyS[0-9]+ */
438 GSList *l, *list = NULL;
439 GDir* dir = g_dir_open ("/dev", 0, NULL);
440 const char *filename;
443 while ((filename = g_dir_read_name (dir))) {
445 if (!strncmp (filename, "ttyS", 4))
446 list = g_slist_append (list, g_strconcat ("/dev/", filename, NULL));
452 array = mono_array_new (mono_domain_get (), mono_get_string_class (), g_slist_length (list));
453 for (l = list; l; l = l->next) {
454 mono_array_set (array, gpointer, i++, mono_string_new (mono_domain_get (), (char*)l->data));
461 #warning "list_serial_devices isn't ported to this OS"