Cleanup: Use correct format string
[hmcfgusb] / culfw.c
CommitLineData
47ea478b
MG
1/* culfw driver
2 *
7ba4ea19 3 * Copyright (c) 2014-16 Michael Gernoth <michael@gernoth.net>
47ea478b
MG
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#include <errno.h>
25#include <fcntl.h>
26#include <inttypes.h>
27#include <poll.h>
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31#include <strings.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <termios.h>
35#include <unistd.h>
36
37#include "culfw.h"
38
39struct culfw_dev *culfw_init(char *device, uint32_t speed, culfw_cb_fn cb, void *data)
40{
41 struct culfw_dev *dev = NULL;
42 struct termios oldtio, tio;
43 uint32_t brate;
44
45 switch(speed) {
46 case 115200:
47 brate = B115200;
48 break;
49 case 57600:
50 brate = B57600;
51 break;
52 case 38400:
53 brate = B38400;
54 break;
55 case 19200:
56 brate = B19200;
57 break;
58 case 9600:
59 brate = B9600;
60 break;
61 default:
62 fprintf(stderr, "Unsupported baud-rate: %u\n", speed);
63 return NULL;
64 break;
65 }
66
67 dev = malloc(sizeof(struct culfw_dev));
68 if (dev == NULL) {
69 perror("malloc(struct culfw_dev)");
70 return NULL;
71 }
72
73 memset(dev, 0, sizeof(struct culfw_dev));
74
75 dev->fd = open(device, O_RDWR | O_NOCTTY);
76 if (dev->fd < 0) {
77 perror("open(culfw)");
78 goto out;
79 }
80
81 if (tcgetattr(dev->fd, &oldtio) == -1) {
82 perror("tcgetattr");
83 goto out2;
84 }
85
86 memset(&tio, 0, sizeof(tio));
87
88 tio.c_cflag = brate | CS8 | CLOCAL | CREAD;
89 tio.c_iflag = IGNPAR | ICRNL;
90 tio.c_oflag = 0;
91 tio.c_lflag = ICANON;
92 tio.c_cc[VTIME] = 0;
93 tio.c_cc[VMIN] = 1;
94
95 tcflush(dev->fd, TCIFLUSH);
96 if (tcsetattr(dev->fd, TCSANOW, &tio) == -1) {
97 perror("tcsetattr");
98 goto out2;
99 }
100
101 dev->cb = cb;
102 dev->cb_data = data;
103
104 return dev;
105
106out2:
107 close(dev->fd);
108out:
109 free(dev);
110 return NULL;
111}
112
b8d1d0c3 113int culfw_send(struct culfw_dev *dev, const char *cmd, int cmdlen)
47ea478b
MG
114{
115 int w = 0;
116 int ret;
117
118 do {
119 ret = write(dev->fd, cmd + w, cmdlen - w);
120 if (ret < 0) {
121 perror("write");
122 return 0;
123 }
124 w += ret;
125 } while (w < cmdlen);
126
127 return 1;
128}
129
130int culfw_poll(struct culfw_dev *dev, int timeout)
131{
132 struct pollfd pfds[1];
133 int ret;
134 int r = 0;
135 uint8_t buf[1024];
136
137 errno = 0;
138
139 memset(pfds, 0, sizeof(struct pollfd) * 1);
140
141 pfds[0].fd = dev->fd;
142 pfds[0].events = POLLIN;
143
3b35a8c1 144 ret = poll(pfds, 1, timeout);
47ea478b
MG
145 if (ret == -1)
146 return -1;
147
148 if (ret == 0) {
149 errno = ETIMEDOUT;
150 return -1;
151 }
152
153 if (!(pfds[0].revents & POLLIN)) {
154 errno = EIO;
155 return -1;
156 }
157
158 memset(buf, 0, sizeof(buf));
159 r = read(dev->fd, buf, sizeof(buf));
160 if (r < 0)
161 return -1;
162
163 if (r == 0) {
164 errno = EOF;
165 return -1;
166 }
167
168 dev->cb(buf, r, dev->cb_data);
169
9f0bab37
MG
170 errno = 0;
171 return -1;
47ea478b
MG
172}
173
174void culfw_close(struct culfw_dev *dev)
175{
176 close(dev->fd);
177}
a65c08fc
MG
178
179void culfw_flush(struct culfw_dev *dev)
180{
181 struct pollfd pfds[1];
182 int ret;
183 int r = 0;
184 uint8_t buf[1024];
185
186 tcflush(dev->fd, TCIOFLUSH);
187
188 while(1) {
189 memset(pfds, 0, sizeof(struct pollfd) * 1);
190
191 pfds[0].fd = dev->fd;
192 pfds[0].events = POLLIN;
193
194 ret = poll(pfds, 1, 100);
195 if (ret <= 0)
196 break;
197
198 if (!(pfds[0].revents & POLLIN))
199 break;
200
201 memset(buf, 0, sizeof(buf));
202 r = read(dev->fd, buf, sizeof(buf));
203 if (r <= 0)
204 break;
205 }
206
207 return;
208}
Impressum, Datenschutz