diff options
| author | Keith Packard <keithp@keithp.com> | 2010-08-29 21:41:40 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2010-08-29 21:41:40 -0700 | 
| commit | b7fa1ea3338f63b8edcf8aacccb5e519ca0b213f (patch) | |
| tree | 8bb9890803296a4b82b33c678a97c1e7ced18c01 | |
| parent | e60c59123232915e808cee23ef89eb1a38ced34b (diff) | |
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 <keithp@keithp.com>
| -rw-r--r-- | ao-tools/libaltos/libaltos.c | 134 | 
1 files changed, 86 insertions, 48 deletions
| 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 <stdlib.h>  #include <string.h> +#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 <fcntl.h>  #include <termios.h>  #include <errno.h> -#include <pthread.h>  #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 <poll.h> +#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); | 
