1// This file is part of SmallBASIC
2//
3// serial I/O, driver
4//
5// This program is distributed under the terms of the GPL v2.0 or later
6// Download the GNU Public License (GPL) from www.gnu.org
7//
8// Copyright(C) 2000 Nicholas Christopoulos
9
10#include "common/sys.h"
11#include "common/device.h"
12#include "common/pproc.h"
13#include "common/fs_stream.h"
14#include "common/fs_serial.h"
15
16#if USE_TERM_IO
17#include <sys/time.h>
18#include <termios.h>
19#include <unistd.h>
20#include <sys/select.h>
21#include <errno.h>
22
23int serial_open(dev_file_t *f) {
24 sprintf(f->name, "/dev/ttyS%d", f->port);
25
26 f->handle = open(f->name, O_RDWR | O_NOCTTY);
27 if (f->handle < 0) {
28 err_file((f->last_error = errno));
29 }
30 // save current port settings
31 tcgetattr(f->handle, &f->oldtio);
32 bzero(&f->newtio, sizeof(f->newtio));
33 f->newtio.c_cflag = f->devspeed | CRTSCTS | CS8 | CLOCAL | CREAD;
34 f->newtio.c_iflag = IGNPAR;
35 f->newtio.c_oflag = 0;
36
37 // set input mode (non-canonical, no echo,...)
38 f->newtio.c_lflag = 0;
39 f->newtio.c_cc[VTIME] = 0; // inter-character timer unused
40 f->newtio.c_cc[VMIN] = 1; // blocking read until 1 char received
41 tcflush(f->handle, TCIFLUSH);
42 tcsetattr(f->handle, TCSANOW, &f->newtio);
43 return (f->handle >= 0);
44}
45
46int serial_close(dev_file_t *f) {
47 tcsetattr(f->handle, TCSANOW, &f->oldtio);
48 close(f->handle);
49 f->handle = -1;
50 return 1;
51}
52
53int serial_write(dev_file_t *f, byte *data, uint32_t size) {
54 return stream_write(f, data, size);
55}
56
57int serial_read(dev_file_t *f, byte *data, uint32_t size) {
58 return stream_read(f, data, size);
59}
60
61// Returns the number of the available data on serial port
62uint32_t serial_length(dev_file_t *f) {
63 fd_set readfs;
64 struct timeval tv;
65
66 FD_ZERO(&readfs);
67 FD_SET(f->handle, &readfs);
68
69 tv.tv_usec = 250; // milliseconds
70 tv.tv_sec = 0; // seconds
71
72 select(f->handle + 1, &readfs, NULL, NULL, &tv);
73 if (FD_ISSET(f->handle, &readfs)) {
74 return 1;
75 }
76 return 0;
77}
78
79#elif defined(_Win32)
80
81int serial_open(dev_file_t *f) {
82 DCB dcb;
83 HANDLE hCom;
84 DWORD dwer;
85
86 sprintf(f->name, "COM%d", f->port);
87
88 hCom = CreateFile(f->name, GENERIC_READ | GENERIC_WRITE,
89 0, NULL, OPEN_EXISTING, 0, NULL);
90
91 if (hCom == INVALID_HANDLE_VALUE) {
92 dwer = GetLastError();
93 if (dwer != 5) {
94 rt_raise("SERIALFS: CreateFile() failed (%d)", dwer);
95 } else {
96 rt_raise("SERIALFS: ACCESS DENIED");
97 }
98 return 0;
99 }
100
101 if (!GetCommState(hCom, &dcb)) {
102 rt_raise("SERIALFS: GetCommState() failed (%d)", GetLastError());
103 return 0;
104 }
105
106 dcb.BaudRate = f->devspeed;
107 dcb.ByteSize = 8;
108 dcb.Parity = NOPARITY;
109 dcb.StopBits = ONESTOPBIT;
110
111 if (!SetCommState(hCom, &dcb)) {
112 rt_raise("SERIALFS: SetCommState() failed (%d)", GetLastError());
113 return 0;
114 }
115
116 f->handle = (intptr_t)hCom;
117 return 1;
118}
119
120int serial_close(dev_file_t *f) {
121 CloseHandle((HANDLE) (intptr_t)f->handle);
122 f->handle = -1;
123 return 1;
124}
125
126int serial_write(dev_file_t *f, byte *data, uint32_t size) {
127 DWORD bytes;
128 f->last_error = !WriteFile((HANDLE)(intptr_t)f->handle, data, size, &bytes, NULL);
129 return bytes;
130}
131
132int serial_read(dev_file_t *f, byte *data, uint32_t size) {
133 DWORD bytes;
134 f->last_error = !ReadFile((HANDLE)(intptr_t)f->handle, data, size, &bytes, NULL);
135 return bytes;
136}
137
138uint32_t serial_length(dev_file_t *f) {
139 COMSTAT cs;
140 DWORD de = CE_BREAK;
141 ClearCommError((HANDLE)(intptr_t)f->handle, &de, &cs);
142 return cs.cbInQue;
143}
144
145#else
146
147int serial_open(dev_file_t *f) {
148 err_unsup();
149 return 0;
150}
151
152int serial_close(dev_file_t *f) {
153 return 0;
154}
155
156int serial_write(dev_file_t *f, byte *data, uint32_t size) {
157 return 0;
158}
159
160int serial_read(dev_file_t *f, byte *data, uint32_t size) {
161 return 0;
162}
163
164uint32_t serial_length(dev_file_t *f) {
165 return 0;
166}
167
168#endif
169
170/*
171 * Returns true (EOF) if the connection is broken
172 */
173uint32_t serial_eof(dev_file_t *f) {
174 return f->last_error;
175}
176