Initial import of the bootloader code
[bootloader] / cli / serial.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <termios.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <sys/ioctl.h>
8 #include <fcntl.h>
9 #include <string.h>
10 #include <errno.h>
11
12 #include "log.h"
13 #include "serial.h"
14
15 struct serial_port {
16         int fd;
17 };
18
19 static speed_t baud(int speed)
20 {
21         if (speed == 230400) return B230400; else
22         if (speed == 115200) return B115200; else
23         if (speed == 57600) return B57600; else
24         if (speed == 38400) return B38400; else
25         if (speed == 19200) return B19200; else
26         if (speed == 9600) return B9600; else
27         if (speed == 4800) return B4800; else
28         if (speed == 2400) return B2400; else
29         if (speed == 1200) return B1200; else {
30                 loge("Error setting baud rate: %d not recognised.", speed);
31                 return B0;
32         }
33
34 }
35
36 port_t * serial_open(const char *name, int speed)
37 {
38         port_t *pt = NULL;
39         int fd;
40
41         if ((fd = open(name, O_RDWR | O_NOCTTY))<0) {
42                 loge("Error: opening %s: %s", name, strerror(errno));
43                 return NULL;
44         }
45
46         struct termios adtio;
47         bzero(&adtio, sizeof(adtio));
48
49         tcgetattr(fd, &adtio);
50         adtio.c_cflag = CS8 | CLOCAL | CREAD;
51         adtio.c_iflag = IGNPAR | IGNBRK;
52         adtio.c_oflag = 0;
53         adtio.c_lflag = 0; // non-canon, no echo
54
55         cfmakeraw(&adtio);
56
57         adtio.c_cc[VTIME] = 0;
58         adtio.c_cc[VMIN] = 1;
59
60         cfsetispeed(&adtio, baud(speed));
61         cfsetospeed(&adtio, baud(speed));
62
63         tcsetattr(fd, TCSANOW, &adtio);
64
65         pt = malloc(sizeof(port_t));
66         pt->fd = fd;
67
68         return pt;
69
70 }
71
72 void serial_close(port_t * pt)
73 {
74         if (pt == NULL) return;
75         if (pt->fd < 0) return;
76
77         close(pt->fd);
78         pt->fd = -1;
79
80         return;
81 }
82
83 int serial_read(port_t * pt, unsigned char * buff, size_t len)
84 {
85         if (pt == NULL || pt->fd < 0) return -1;
86
87         int ret = 0;
88         int count = 0;
89         unsigned char * p = buff;
90         while (count < len) {
91                 ret = read(pt->fd, p, len-count);
92                 if (ret <= 0) return ret;
93                 p += ret;
94                 count += ret;
95         }
96         return count;
97 }
98
99 int serial_write(port_t * pt, unsigned char * buff, size_t len)
100 {
101         if (pt == NULL || pt->fd < 0) return -1;
102
103         return write(pt->fd, buff, len);
104 }
105
106 int serial_break(port_t * pt, int set)
107 {
108         if (pt == NULL || pt->fd < 0) return -1;
109
110         if (set)
111                 ioctl(pt->fd, TIOCSBRK, 0);
112         else
113                 ioctl(pt->fd, TIOCCBRK, 0);
114
115         return 0;
116 }
117