2 * Copyright © 2009 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 #define AOVIEW_SERIAL_IN_BUF 64
23 #define AOVIEW_SERIAL_OUT_BUF 64
33 aoview_buf_write(struct aoview_buf *buf, char *data, int len)
35 if (buf->count + len > buf->size) {
36 int new_size = buf->size * 2;
40 buf->buf = realloc (buf->buf, new_size);
42 buf->buf = malloc (new_size);
45 memcpy(buf->buf + buf->count, data, len);
51 aoview_buf_read(struct aoview_buf *buf, char *data, int len)
53 if (len > buf->count - buf->off)
54 len = buf->count - buf->off;
55 memcpy (data, buf->buf + buf->off, len);
57 if (buf->off == buf->count)
58 buf->off = buf->count = 0;
63 aoview_buf_getc(struct aoview_buf *buf)
68 r = aoview_buf_read(buf, &b, 1);
75 aoview_buf_flush(struct aoview_buf *buf, int fd)
79 if (buf->count > buf->off) {
80 ret = write(fd, buf->buf + buf->off, buf->count - buf->off);
83 if (buf->off == buf->count)
84 buf->off = buf->count = 0;
90 aoview_buf_fill(struct aoview_buf *buf, int fd)
94 while (buf->count >= buf->size) {
95 int new_size = buf->size * 2;
96 buf->buf = realloc (buf->buf, new_size);
100 ret = read(fd, buf->buf + buf->count, buf->size - buf->count);
106 aoview_buf_init(struct aoview_buf *buf)
108 buf->buf = malloc (buf->size = 1024);
113 aoview_buf_fini(struct aoview_buf *buf)
118 struct aoview_serial {
121 struct termios save_termios;
122 struct aoview_buf in_buf;
123 struct aoview_buf out_buf;
129 aoview_serial_printf(struct aoview_serial *serial, char *format, ...)
135 /* sprintf to a local buffer */
136 va_start(ap, format);
137 ret = vsnprintf(buf, sizeof(buf), format, ap);
139 if (ret > sizeof(buf)) {
140 fprintf(stderr, "printf overflow for format %s\n",
144 /* flush local buffer to the wire */
145 aoview_buf_write(&serial->out_buf, buf, ret);
146 aoview_buf_flush(&serial->out_buf, serial->fd);
150 aoview_serial_read(struct aoview_serial *serial, char *buf, int len)
152 return aoview_buf_read(&serial->in_buf, buf, len);
156 aoview_serial_getc(struct aoview_serial *serial)
158 return aoview_buf_getc(&serial->in_buf);
162 serial_prepare(GSource *source, gint *timeout)
164 struct aoview_serial *serial = (struct aoview_serial *) source;
167 if (serial->out_buf.count)
168 serial->poll_fd.events |= G_IO_OUT;
170 serial->poll_fd.events &= ~G_IO_OUT;
175 serial_check(GSource *source)
177 struct aoview_serial *serial = (struct aoview_serial *) source;
178 gint revents = serial->poll_fd.revents;
180 if (revents & G_IO_NVAL)
182 if (revents & G_IO_IN)
184 if (revents & G_IO_OUT)
190 serial_dispatch(GSource *source,
191 GSourceFunc callback,
194 struct aoview_serial *serial = (struct aoview_serial *) source;
195 aoview_serial_callback func = (aoview_serial_callback) callback;
196 gint revents = serial->poll_fd.revents;
198 if (revents & G_IO_IN)
199 aoview_buf_fill(&serial->in_buf, serial->fd);
201 if (revents & G_IO_OUT)
202 aoview_buf_flush(&serial->out_buf, serial->fd);
205 (*func)(user_data, serial, revents);
210 serial_finalize(GSource *source)
212 struct aoview_serial *serial = (struct aoview_serial *) source;
214 aoview_buf_fini(&serial->in_buf);
215 aoview_buf_fini(&serial->out_buf);
216 tcsetattr(serial->fd, TCSAFLUSH, &serial->save_termios);
220 static GSourceFuncs serial_funcs = {
227 struct aoview_serial *
228 aoview_serial_open(const char *tty)
230 struct aoview_serial *serial;
231 struct termios termios;
233 serial = (struct aoview_serial *) g_source_new(&serial_funcs, sizeof (struct aoview_serial));
234 aoview_buf_init(&serial->in_buf);
235 aoview_buf_init(&serial->out_buf);
236 serial->fd = open (tty, O_RDWR | O_NONBLOCK);
237 if (serial->fd < 0) {
238 g_source_destroy(&serial->source);
241 tcgetattr(serial->fd, &termios);
242 serial->save_termios = termios;
244 tcsetattr(serial->fd, TCSAFLUSH, &termios);
246 aoview_serial_printf(serial, "E 0\n");
249 tcflush(serial->fd, TCIFLUSH);
250 serial->poll_fd.fd = serial->fd;
251 serial->poll_fd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR;
252 g_source_attach(&serial->source, NULL);
253 g_source_add_poll(&serial->source,&serial->poll_fd);
254 aoview_serial_set_callback(serial, NULL);
259 aoview_serial_close(struct aoview_serial *serial)
261 g_source_remove_poll(&serial->source, &serial->poll_fd);
263 g_source_destroy(&serial->source);
267 aoview_serial_set_callback(struct aoview_serial *serial,
268 aoview_serial_callback func)
270 g_source_set_callback(&serial->source, (GSourceFunc) func, serial, NULL);