/ bf16-uartdevice.c
bf16-uartdevice.c
  1  #include <fcntl.h>
  2  #include <unistd.h>
  3  
  4  #include "bf16-uartdevice.h"
  5  #include "miner.h"
  6  
  7  #define SRV_TIMEOUT 2
  8  
  9  char *uart1_device_name = "/dev/ttyO1";
 10  char *uart2_device_name = "/dev/ttyO4";
 11  
 12  int8_t uart_init(device_t* attr, uart_channel_id_t channel_id, int8_t mode, uint32_t speed, uint16_t size)
 13  {
 14  	switch (channel_id) {
 15  	case UART_CHANNEL1:
 16  		attr->device = uart1_device_name;
 17  		break;
 18  	case UART_CHANNEL2:
 19  		attr->device = uart2_device_name;
 20  		break;
 21  	}
 22  
 23  	attr->mode = mode;
 24  	attr->speed = speed;
 25  	attr->bits = 8;
 26  	attr->size = size;
 27  	attr->rx = malloc(size);
 28  	attr->tx = malloc(size);
 29  
 30  	int fd;
 31  	if ((fd = open(attr->device, O_RDWR | O_NOCTTY | O_NDELAY)) < 0)
 32  		quit(1, "BF16: %s() failed to open device [%s]: %s",
 33  				__func__, attr->device, strerror(errno));
 34  
 35  	attr->fd = fd;
 36  
 37  	if (fcntl(fd, F_SETFL, 0) < 0)
 38  		quit(1, "BF16: %s() failed to set descriptor status flags [%s]: %s",
 39  				__func__, attr->device, strerror(errno));
 40  
 41  	struct termios settings;
 42  	if (tcgetattr(fd, &settings) < 0)
 43  		quit(1, "BF16: %s() failed to get device attributes [%s]: %s",
 44  				__func__, attr->device, strerror(errno));
 45  
 46  	settings.c_cflag &= ~PARENB; /* no parity */
 47  	settings.c_cflag &= ~CSTOPB; /* 1 stop bit */
 48  	settings.c_cflag &= ~CSIZE;
 49  	settings.c_cflag |= CS8 | CLOCAL | CREAD; /* 8 bits */
 50  	settings.c_cc[VMIN] = 1;
 51  	settings.c_cc[VTIME] = 2;
 52  	settings.c_lflag = ICANON; /* canonical mode */
 53  	settings.c_oflag &= ~OPOST; /* raw output */
 54  
 55  	if (cfsetospeed(&settings, speed) < 0)
 56  		quit(1, "BF16: %s() failed to set device output speed [%s]: %s",
 57  				__func__, attr->device, strerror(errno));
 58  
 59  	if (cfsetispeed(&settings, speed) < 0)
 60  		quit(1, "BF16: %s() failed to set device input speed [%s]: %s",
 61  				__func__, attr->device, strerror(errno));
 62  
 63  	if (tcsetattr(fd, TCSANOW, &settings) < 0)
 64  		quit(1, "BF16: %s() failed to get device attributes [%s]: %s",
 65  				__func__, attr->device, strerror(errno));
 66  
 67  	if (tcflush(fd, TCOFLUSH) < 0)
 68  		quit(1, "BF16: %s() failed to flush device data [%s]: %s",
 69  				__func__, attr->device, strerror(errno));
 70  
 71  	return 0;
 72  }
 73  
 74  /* TODO: add errors processing */
 75  static int read_to(int fd, uint8_t* buffer, int len, int timeout)
 76  {
 77  	fd_set readset;
 78  	int result;
 79  	struct timeval tv;
 80  
 81  	FD_ZERO(&readset);
 82  	FD_SET(fd, &readset);
 83  
 84  	tv.tv_sec = timeout;
 85  	tv.tv_usec = 0;
 86  	result = select(fd + 1, &readset, NULL, NULL, &tv);
 87   
 88  	if (result < 0)
 89  		return result;
 90  	else if (result > 0 && FD_ISSET(fd, &readset)) {
 91  		result = read(fd, buffer, len);
 92  		return result;
 93  	}
 94  	return -2;
 95  }
 96  
 97  static int write_to(int fd, uint8_t* buffer, int len, int timeout)
 98  {
 99  	fd_set writeset;
100  	int result;
101  	struct timeval tv;
102  
103  	FD_ZERO(&writeset);
104  	FD_SET(fd, &writeset);
105  
106  	tv.tv_sec = timeout;
107  	tv.tv_usec = 0;
108  	result = select(fd + 1, NULL, &writeset, NULL, &tv);
109  
110  	if (result < 0)
111  		return result;
112  	else if (result > 0 && FD_ISSET(fd, &writeset)) {
113  		result = write(fd, buffer, len);
114  		return result;
115  	}
116  
117  	return -2;
118  }
119  
120  int8_t uart_transfer(device_t *attr)
121  {
122  	int ret;
123  
124  	if ((ret = write_to(attr->fd, attr->tx, attr->datalen, SRV_TIMEOUT)) < 1) {
125  		applog(LOG_ERR, "BF16: %s() failed to send UART message to [%s]: %s",
126  				__func__, attr->device, strerror(errno));
127  
128  		attr->datalen = 0;
129  		return -1;
130  	}
131  
132  	if ((ret = read_to(attr->fd, attr->rx, attr->size, SRV_TIMEOUT)) < 1) {
133  		applog(LOG_ERR, "BF16: %s() failed to read UART message from [%s]: %s",
134  				__func__, attr->device, strerror(errno));
135  
136  		attr->datalen = 0;
137  		return -1;
138  	}
139  
140  	attr->datalen = ret;
141  	return 0;
142  }
143  
144  void uart_release(device_t *attr)
145  {
146  	free(attr->rx);
147  	free(attr->tx);
148  	close(attr->fd);
149  }