Fix up the serial code

This commit is contained in:
Peter De Wachter 2017-10-24 22:02:36 +02:00
parent 3e6ff6c22c
commit 60984d0105
3 changed files with 63 additions and 28 deletions

View File

@ -23,15 +23,31 @@ struct RawSerial {
int fd_out; int fd_out;
}; };
static int max(int a, int b) {
return a > b ? a : b;
}
static uint32_t read_status(const struct RISC_Serial *serial) { static uint32_t read_status(const struct RISC_Serial *serial) {
struct RawSerial *s = (struct RawSerial *)serial; struct RawSerial *s = (struct RawSerial *)serial;
struct timeval tv = { 0, 0 }; struct timeval tv = { 0, 0 };
fd_set rfds; fd_set read_fds;
FD_ZERO(&rfds); fd_set write_fds;
FD_SET(s->fd_in, &rfds); FD_ZERO(&read_fds);
int nfds = s->fd_in + 1; FD_SET(s->fd_in, &read_fds);
int r = select(nfds, &rfds, NULL, NULL, &tv); FD_ZERO(&write_fds);
return r == 1; FD_SET(s->fd_out, &write_fds);
int nfds = max(s->fd_in, s->fd_out) + 1;
int r = select(nfds, &read_fds, &write_fds, NULL, &tv);
int status = 0;
if (r > 0) {
if (FD_ISSET(s->fd_in, &read_fds)) {
status |= 1;
}
if (FD_ISSET(s->fd_out, &write_fds)) {
status |= 2;
}
}
return status;
} }
static uint32_t read_data(const struct RISC_Serial *serial) { static uint32_t read_data(const struct RISC_Serial *serial) {
@ -47,30 +63,24 @@ static void write_data(const struct RISC_Serial *serial, uint32_t data) {
write(s->fd_out, &byte, 1); write(s->fd_out, &byte, 1);
} }
static bool set_non_blocking(int fd) { struct RISC_Serial *raw_serial_new(const char *filename_in, const char *filename_out) {
int r = fcntl(fd, F_GETFL); int fd_in, fd_out;
if (r != -1) {
int flags = r | O_NONBLOCK;
r = fcntl(fd, F_SETFL, flags);
}
return r != -1;
}
struct RISC_Serial *raw_serial_new(int fd_in, int fd_out) { fd_in = open(filename_in, O_RDONLY | O_NONBLOCK);
if (!set_non_blocking(fd_in)) { if (fd_in < 0) {
fprintf(stderr, "serial fd %d (input): ", fd_in); perror("Failed to open serial input file");
perror(NULL); goto fail1;
return NULL;
} }
if (!set_non_blocking(fd_out)) {
fprintf(stderr, "serial fd %d (output): ", fd_out); fd_out = open(filename_out, O_RDWR | O_NONBLOCK);
perror(NULL); if (fd_out < 0) {
return NULL; perror("Failed to open serial output file");
goto fail2;
} }
struct RawSerial *s = malloc(sizeof(*s)); struct RawSerial *s = malloc(sizeof(*s));
if (!s) { if (!s) {
return NULL; goto fail3;
} }
*s = (struct RawSerial){ *s = (struct RawSerial){
@ -83,6 +93,13 @@ struct RISC_Serial *raw_serial_new(int fd_in, int fd_out) {
.fd_out = fd_out .fd_out = fd_out
}; };
return &s->serial; return &s->serial;
fail3:
close(fd_out);
fail2:
close(fd_in);
fail1:
return NULL;
} }
#endif // _WIN32 #endif // _WIN32

View File

@ -3,6 +3,6 @@
#include "risc-io.h" #include "risc-io.h"
struct RISC_Serial *raw_serial_new(int fd_in, int fd_out); struct RISC_Serial *raw_serial_new(const char *filename_in, const char *filename_out);
#endif // SERIAL_H #endif // SERIAL_H

View File

@ -66,7 +66,8 @@ static struct option long_options[] = {
{ "fullscreen", no_argument, NULL, 'f' }, { "fullscreen", no_argument, NULL, 'f' },
{ "leds", no_argument, NULL, 'L' }, { "leds", no_argument, NULL, 'L' },
{ "size", required_argument, NULL, 's' }, { "size", required_argument, NULL, 's' },
{ "serial-fd", required_argument, NULL, 'F' }, { "serial-in", required_argument, NULL, 'I' },
{ "serial-out", required_argument, NULL, 'O' },
{ NULL, no_argument, NULL, 0 } { NULL, no_argument, NULL, 0 }
}; };
@ -98,6 +99,8 @@ int main (int argc, char *argv[]) {
.w = RISC_FRAMEBUFFER_WIDTH, .w = RISC_FRAMEBUFFER_WIDTH,
.h = RISC_FRAMEBUFFER_HEIGHT .h = RISC_FRAMEBUFFER_HEIGHT
}; };
const char *serial_in = NULL;
const char *serial_out = NULL;
int opt; int opt;
while ((opt = getopt_long(argc, argv, "z:fLS:F:", long_options, NULL)) != -1) { while ((opt = getopt_long(argc, argv, "z:fLS:F:", long_options, NULL)) != -1) {
@ -127,8 +130,12 @@ int main (int argc, char *argv[]) {
risc_screen_size_hack(risc, risc_rect.w, risc_rect.h); risc_screen_size_hack(risc, risc_rect.w, risc_rect.h);
break; break;
} }
case 'F': { case 'I': {
risc_set_serial(risc, raw_serial_new(atoi(optarg), atoi(optarg) + 1)); serial_in = optarg;
break;
}
case 'O': {
serial_out = optarg;
break; break;
} }
default: { default: {
@ -136,11 +143,22 @@ int main (int argc, char *argv[]) {
} }
} }
} }
if (optind != argc - 1) { if (optind != argc - 1) {
usage(); usage();
} }
risc_set_spi(risc, 1, disk_new(argv[optind])); risc_set_spi(risc, 1, disk_new(argv[optind]));
if (serial_in || serial_out) {
if (!serial_in) {
serial_in = "/dev/null";
}
if (!serial_out) {
serial_out = "/dev/null";
}
risc_set_serial(risc, raw_serial_new(serial_in, serial_out));
}
if (SDL_Init(SDL_INIT_VIDEO) != 0) { if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fail(1, "Unable to initialize SDL: %s", SDL_GetError()); fail(1, "Unable to initialize SDL: %s", SDL_GetError());
} }