filename | src/drivers/serial_unix.c |
changeset | 1081:ef31ae97bb8b |
prev | 1079:691f9f621c5a |
author | nkeynes |
date | Mon Feb 13 21:02:42 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Move profile_block setting out of sh4x86 and back into sh4.c. Fix last bits preventing non-translation build |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * Host driver for a serial port attachment, that can be hooked to a character
5 * device, fifo or named pipe.
6 *
7 * Copyright (c) 2009 Nathan Keynes.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <fcntl.h>
23 #include <sys/stat.h>
25 #include "lxdream.h"
26 #include "config.h"
27 #include "ioutil.h"
28 #include "serial.h"
31 typedef struct serial_fd_device {
32 struct serial_device dev;
33 FILE *in;
34 FILE *out;
35 gboolean closeOnDestroy;
36 io_listener_t listener;
37 } *serial_fd_device_t;
39 static void serial_fd_device_attach(serial_device_t dev);
40 static void serial_fd_device_detach(serial_device_t dev);
41 static void serial_fd_device_destroy(serial_device_t dev);
42 static void serial_fd_device_set_line_speed(struct serial_device *dev, uint32_t bps);
43 static void serial_fd_device_set_line_params(struct serial_device *dev, int flags);
44 static void serial_fd_device_receive_data(struct serial_device *dev, uint8_t value);
45 static gboolean serial_fd_device_transmit_data( int fd, void *dev);
47 static gboolean serial_config_changed(void *data, struct lxdream_config_group *group, unsigned item,
48 const gchar *oldval, const gchar *newval);
50 struct lxdream_config_group serial_group =
51 { "serial", serial_config_changed, NULL, NULL,
52 {{ "device", N_("Serial device"), CONFIG_TYPE_FILE, "/dev/tty" },
53 { NULL, CONFIG_TYPE_NONE }} };
55 void serial_init()
56 {
57 const gchar *name = serial_group.params[0].value;
58 if( name != NULL ) {
59 serial_device_t dev = serial_fd_device_new_filename(name);
60 if( dev != NULL ) {
61 serial_attach_device( dev );
62 }
63 }
64 }
66 static gboolean serial_config_changed(void *data, struct lxdream_config_group *group, unsigned item,
67 const gchar *oldval, const gchar *newval)
68 {
69 if( item == 0 ) {
70 serial_destroy_device(serial_detach_device());
71 serial_device_t dev = serial_fd_device_new_filename(newval);
72 if( dev != NULL ) {
73 serial_attach_device( dev );
74 }
75 }
76 return TRUE;
77 }
81 serial_device_t serial_fd_device_new_filename( const gchar *filename )
82 {
83 FILE *out = fopen( filename, "w+" );
84 FILE *in;
85 struct stat st;
87 if( out == NULL ) {
88 return NULL;
89 }
91 if( fstat( fileno(out), &st ) != 0 ) {
92 fclose(out);
93 return NULL;
94 }
96 if( S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode) ) {
97 in = out;
98 } else {
99 in = NULL;
100 }
102 return (serial_device_t)serial_fd_device_new_file(in, out, TRUE);
103 }
105 serial_device_t serial_fd_device_new_console()
106 {
107 return serial_fd_device_new_file( stdin, stdout, FALSE );
108 }
110 serial_device_t serial_fd_device_new_file( FILE *in, FILE *out, gboolean closeOnDestroy )
111 {
112 if( in != NULL )
113 fcntl( fileno(in), F_SETFL, O_NONBLOCK );
115 serial_fd_device_t dev = (serial_fd_device_t)malloc(sizeof(struct serial_fd_device));
116 if( dev == NULL ) {
117 if( closeOnDestroy ) {
118 if( in != NULL )
119 fclose(in);
120 if( out != NULL && out != in )
121 fclose(out);
122 }
123 return NULL;
124 }
126 dev->dev.attach = serial_fd_device_attach;
127 dev->dev.detach = serial_fd_device_detach;
128 dev->dev.destroy = serial_fd_device_destroy;
129 dev->dev.set_line_speed = serial_fd_device_set_line_speed;
130 dev->dev.set_line_params = serial_fd_device_set_line_params;
131 dev->dev.receive_data = serial_fd_device_receive_data;
132 dev->in = in;
133 dev->out = out;
134 dev->closeOnDestroy = closeOnDestroy;
135 return (serial_device_t)dev;
136 }
138 static void serial_fd_device_attach(serial_device_t dev)
139 {
140 serial_fd_device_t fddev = (serial_fd_device_t)dev;
141 if( fddev->in != NULL )
142 fddev->listener = io_register_listener( fileno(fddev->in), serial_fd_device_transmit_data, fddev, NULL );
143 }
145 static void serial_fd_device_detach(serial_device_t dev)
146 {
147 serial_fd_device_t fddev = (serial_fd_device_t)dev;
148 if( fddev->in != NULL )
149 io_unregister_listener( fddev->listener );
150 }
152 static void serial_fd_device_destroy(serial_device_t dev)
153 {
154 serial_fd_device_t fddev = (serial_fd_device_t)dev;
155 if( fddev->closeOnDestroy ) {
156 if( fddev->in != NULL )
157 fclose(fddev->in);
158 if( fddev->out != NULL && fddev->out != fddev->in )
159 fclose(fddev->out);
160 }
161 fddev->in = NULL;
162 fddev->out = NULL;
163 free(fddev);
164 }
165 static void serial_fd_device_set_line_speed(struct serial_device *dev, uint32_t bps)
166 {
167 /* Do nothing for now */
168 }
169 static void serial_fd_device_set_line_params(struct serial_device *dev, int flags)
170 {
171 /* Do nothing for now */
172 }
173 static void serial_fd_device_receive_data(struct serial_device *dev, uint8_t value)
174 {
175 serial_fd_device_t fddev = (serial_fd_device_t)dev;
176 if( fddev->out != NULL )
177 fputc( value, fddev->out );
178 }
180 static gboolean serial_fd_device_transmit_data( int fd, void *dev )
181 {
182 serial_fd_device_t fddev = (serial_fd_device_t)dev;
183 char buf[4096];
184 size_t len = fread(buf, 1, sizeof(buf), fddev->in);
185 if( len > 0 ) {
186 serial_transmit_data(buf, len);
187 }
188 return TRUE;
189 }
.