From: Keith Packard Date: Mon, 30 Aug 2010 04:41:40 +0000 (-0700) Subject: libaltos: Mac OS X cannot use 'poll(2)' on serial lines. X-Git-Tag: debian/0.7+22+g4790f78~19 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=b7fa1ea3338f63b8edcf8aacccb5e519ca0b213f libaltos: Mac OS X cannot use 'poll(2)' on serial lines. Who ships this stuff, anyway? Instead of blocking, we'll poll every 100ms now, otherwise, we won't be able to abort the read when the device is closed. Yay! Signed-off-by: Keith Packard --- diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 93c483d1..65cd6c1a 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -21,6 +21,8 @@ #include #include +#define USE_POLL + PUBLIC int altos_init(void) { @@ -33,6 +35,9 @@ altos_fini(void) } #ifdef DARWIN + +#undef USE_POLL + /* Mac OS X don't have strndup even if _GNU_SOURCE is defined */ static char * altos_strndup (const char *s, size_t n) @@ -471,20 +476,21 @@ altos_list_finish(struct altos_list *list) #include #include #include -#include #define USB_BUF_SIZE 64 struct altos_file { int fd; +#ifdef USE_POLL int pipe[2]; +#else + int out_fd; +#endif unsigned char out_data[USB_BUF_SIZE]; int out_used; unsigned char in_data[USB_BUF_SIZE]; int in_used; int in_read; - pthread_mutex_t putc_mutex; - pthread_mutex_t getc_mutex; }; struct altos_file * @@ -497,32 +503,54 @@ altos_open(struct altos_device *device) if (!file) return NULL; - pipe(file->pipe); + printf("open %s\n", device->path); file->fd = open(device->path, O_RDWR | O_NOCTTY); + printf("opened %d\n", file->fd); if (file->fd < 0) { perror(device->path); free(file); return NULL; } +#ifdef USE_POLL + pipe(file->pipe); +#else + file->out_fd = open(device->path, O_RDWR | O_NOCTTY); + if (file->out_fd < 0) { + perror(device->path); + close(file->fd); + free(file); + return NULL; + } +#endif ret = tcgetattr(file->fd, &term); if (ret < 0) { perror("tcgetattr"); close(file->fd); +#ifndef USE_POLL + close(file->out_fd); +#endif free(file); return NULL; } cfmakeraw(&term); +#ifdef USE_POLL term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; +#else + term.c_cc[VMIN] = 0; + term.c_cc[VTIME] = 1; +#endif ret = tcsetattr(file->fd, TCSAFLUSH, &term); if (ret < 0) { perror("tcsetattr"); close(file->fd); +#ifndef USE_POLL + close(file->out_fd); +#endif free(file); return NULL; } - pthread_mutex_init(&file->putc_mutex,NULL); - pthread_mutex_init(&file->getc_mutex,NULL); + printf("running %d\n", file->fd); return file; } @@ -532,7 +560,13 @@ altos_close(struct altos_file *file) if (file->fd != -1) { int fd = file->fd; file->fd = -1; +#ifdef USE_POLL write(file->pipe[1], "\r", 1); +#else + close(file->out_fd); + file->out_fd = -1; +#endif + printf("close %d\n", fd); close(fd); } } @@ -544,16 +578,20 @@ altos_free(struct altos_file *file) free(file); } -static int -_altos_flush(struct altos_file *file) +int +altos_flush(struct altos_file *file) { while (file->out_used) { int ret; if (file->fd < 0) return -EBADF; - fflush(stdout); + printf("write %d\n", file->out_used); +#ifdef USE_POLL ret = write (file->fd, file->out_data, file->out_used); +#else + ret = write (file->out_fd, file->out_data, file->out_used); +#endif if (ret < 0) return -errno; if (ret) { @@ -562,6 +600,7 @@ _altos_flush(struct altos_file *file) file->out_used -= ret; } } + return 0; } int @@ -569,79 +608,81 @@ altos_putchar(struct altos_file *file, char c) { int ret; - pthread_mutex_lock(&file->putc_mutex); if (file->out_used == USB_BUF_SIZE) { - ret = _altos_flush(file); + ret = altos_flush(file); if (ret) { - pthread_mutex_unlock(&file->putc_mutex); return ret; } } file->out_data[file->out_used++] = c; ret = 0; if (file->out_used == USB_BUF_SIZE) - ret = _altos_flush(file); - pthread_mutex_unlock(&file->putc_mutex); + ret = altos_flush(file); return 0; } -int -altos_flush(struct altos_file *file) -{ - int ret; - pthread_mutex_lock(&file->putc_mutex); - ret = _altos_flush(file); - pthread_mutex_unlock(&file->putc_mutex); - return ret; -} - - +#ifdef USE_POLL #include +#endif int -altos_getchar(struct altos_file *file, int timeout) +altos_fill(struct altos_file *file, int timeout) { int ret; +#ifdef USE_POLL struct pollfd fd[2]; +#endif if (timeout == 0) timeout = -1; - pthread_mutex_lock(&file->getc_mutex); - fd[0].fd = file->fd; - fd[0].events = POLLIN; - fd[1].fd = file->pipe[0]; - fd[1].events = POLLIN; while (file->in_read == file->in_used) { - if (file->fd < 0) { - pthread_mutex_unlock(&file->getc_mutex); + if (file->fd < 0) return LIBALTOS_ERROR; - } - altos_flush(file); - +#ifdef USE_POLL + fd[0].fd = file->fd; + fd[0].events = POLLIN; + fd[1].fd = file->pipe[0]; + fd[1].events = POLLIN; ret = poll(fd, 2, timeout); if (ret < 0) { perror("altos_getchar"); - pthread_mutex_unlock(&file->getc_mutex); return LIBALTOS_ERROR; } - if (ret == 0) { - pthread_mutex_unlock(&file->getc_mutex); + if (ret == 0) return LIBALTOS_TIMEOUT; - } - if (fd[0].revents & POLLIN) { + if (fd[0].revents & POLLIN) +#endif + { ret = read(file->fd, file->in_data, USB_BUF_SIZE); + if (ret) + printf("read %d\n", ret); if (ret < 0) { perror("altos_getchar"); - pthread_mutex_unlock(&file->getc_mutex); return LIBALTOS_ERROR; } file->in_read = 0; file->in_used = ret; +#ifndef USE_POLL + if (ret == 0 && timeout > 0) + return LIBALTOS_TIMEOUT; +#endif } } - ret = file->in_data[file->in_read++]; - pthread_mutex_unlock(&file->getc_mutex); - return ret; + return 0; +} + +int +altos_getchar(struct altos_file *file, int timeout) +{ + int ret; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; + ret = altos_fill(file, timeout); + if (ret) + return ret; + } + return file->in_data[file->in_read++]; } #endif /* POSIX_TTY */ @@ -919,9 +960,6 @@ altos_getchar(struct altos_file *file, int timeout) { int ret; while (file->in_read == file->in_used) { - ret = altos_flush(file); - if (ret) - return ret; if (file->handle == INVALID_HANDLE_VALUE) return LIBALTOS_ERROR; ret = altos_fill(file, timeout);