Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 464 lines (386 sloc) 10.277 kb
fc828ae piece of shit.
mellis authored
1 /*
2 * avrdude - A Downloader/Uploader for AVR device programmers
3 * Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
4 * Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /* $Id: ser_posix.c,v 1.20 2007/05/15 20:30:15 joerg_wunsch Exp $ */
22
23 /*
24 * Posix serial interface for avrdude.
25 */
26
27 #if !defined(WIN32NATIVE)
28
29
30 #include <ctype.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #include <sys/time.h>
37 #include <sys/socket.h>
38 #include <netdb.h>
39 #include <netinet/in.h>
40
41 #include <fcntl.h>
42 #include <termios.h>
43 #include <unistd.h>
44
45 #include "avrdude.h"
46 #include "serial.h"
47
48 long serial_recv_timeout = 5000; /* ms */
49
50 struct baud_mapping {
51 long baud;
52 speed_t speed;
53 };
54
55 /* There are a lot more baud rates we could handle, but what's the point? */
56
57 static struct baud_mapping baud_lookup_table [] = {
58 { 1200, B1200 },
59 { 2400, B2400 },
60 { 4800, B4800 },
61 { 9600, B9600 },
62 { 19200, B19200 },
63 { 38400, B38400 },
64 { 57600, B57600 },
65 { 115200, B115200 },
66 { 230400, B230400 },
67 { 0, 0 } /* Terminator. */
68 };
69
70 static struct termios original_termios;
71 static int saved_original_termios;
72
73 static speed_t serial_baud_lookup(long baud)
74 {
75 struct baud_mapping *map = baud_lookup_table;
76
77 while (map->baud) {
78 if (map->baud == baud)
79 return map->speed;
80 map++;
81 }
82
83 fprintf(stderr, "%s: serial_baud_lookup(): unknown baud rate: %ld\n",
84 progname, baud);
85 exit(1);
86 }
87
88 static int ser_setspeed(union filedescriptor *fd, long baud)
89 {
90 int rc;
91 struct termios termios;
92 speed_t speed = serial_baud_lookup (baud);
93
94 if (!isatty(fd->ifd))
95 return -ENOTTY;
96
97 /*
98 * initialize terminal modes
99 */
100 rc = tcgetattr(fd->ifd, &termios);
101 if (rc < 0) {
102 fprintf(stderr, "%s: ser_setspeed(): tcgetattr() failed",
103 progname);
104 return -errno;
105 }
106
107 /*
108 * copy termios for ser_close if we haven't already
109 */
110 if (! saved_original_termios++) {
111 original_termios = termios;
112 }
113
114 termios.c_iflag = IGNBRK;
115 termios.c_oflag = 0;
116 termios.c_lflag = 0;
117 termios.c_cflag = (CS8 | CREAD | CLOCAL);
118 termios.c_cc[VMIN] = 1;
119 termios.c_cc[VTIME] = 0;
120
121 cfsetospeed(&termios, speed);
122 cfsetispeed(&termios, speed);
123
124 rc = tcsetattr(fd->ifd, TCSANOW | TCSAFLUSH, &termios);
125 if (rc < 0) {
126 fprintf(stderr, "%s: ser_setspeed(): tcsetattr() failed",
127 progname);
128 return -errno;
129 }
130
131 /*
132 * Everything is now set up for a local line without modem control
133 * or flow control, so clear O_NONBLOCK again.
134 */
135 rc = fcntl(fd->ifd, F_GETFL, 0);
136 if (rc != -1)
137 fcntl(fd->ifd, F_SETFL, rc & ~O_NONBLOCK);
138
139 return 0;
140 }
141
142 /*
143 * Given a port description of the form <host>:<port>, open a TCP
144 * connection to the specified destination, which is assumed to be a
145 * terminal/console server with serial parameters configured
146 * appropriately (e. g. 115200-8-N-1 for a STK500.)
147 */
148 static void
149 net_open(const char *port, union filedescriptor *fdp)
150 {
151 char *hstr, *pstr, *end;
152 unsigned int pnum;
153 int fd;
154 struct sockaddr_in sockaddr;
155 struct hostent *hp;
156
157 if ((hstr = strdup(port)) == NULL) {
158 fprintf(stderr, "%s: net_open(): Out of memory!\n",
159 progname);
160 exit(1);
161 }
162
163 if (((pstr = strchr(hstr, ':')) == NULL) || (pstr == hstr)) {
164 fprintf(stderr, "%s: net_open(): Mangled host:port string \"%s\"\n",
165 progname, hstr);
166 free(hstr);
167 exit(1);
168 }
169
170 /*
171 * Terminate the host section of the description.
172 */
173 *pstr++ = '\0';
174
175 pnum = strtoul(pstr, &end, 10);
176
177 if ((*pstr == '\0') || (*end != '\0') || (pnum == 0) || (pnum > 65535)) {
178 fprintf(stderr, "%s: net_open(): Bad port number \"%s\"\n",
179 progname, pstr);
180 free(hstr);
181 exit(1);
182 }
183
184 if ((hp = gethostbyname(hstr)) == NULL) {
185 fprintf(stderr, "%s: net_open(): unknown host \"%s\"\n",
186 progname, hstr);
187 free(hstr);
188 exit(1);
189 }
190
191 free(hstr);
192
193 if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
194 fprintf(stderr, "%s: net_open(): Cannot open socket: %s\n",
195 progname, strerror(errno));
196 exit(1);
197 }
198
199 memset(&sockaddr, 0, sizeof(struct sockaddr_in));
200 sockaddr.sin_family = AF_INET;
201 sockaddr.sin_port = htons(pnum);
202 memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr));
203
204 if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
205 fprintf(stderr, "%s: net_open(): Connect failed: %s\n",
206 progname, strerror(errno));
207 exit(1);
208 }
209
210 fdp->ifd = fd;
211 }
212
213 static void ser_open(char * port, long baud, union filedescriptor *fdp)
214 {
215 int rc;
216 int fd;
217
218 /*
219 * If the port is of the form "net:<host>:<port>", then
220 * handle it as a TCP connection to a terminal server.
221 */
222 if (strncmp(port, "net:", strlen("net:")) == 0) {
223 net_open(port + strlen("net:"), fdp);
224 return;
225 }
226
227 /*
228 * open the serial port
229 */
230 fd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
231 if (fd < 0) {
232 fprintf(stderr, "%s: ser_open(): can't open device \"%s\": %s\n",
233 progname, port, strerror(errno));
234 exit(1);
235 }
236
237 fdp->ifd = fd;
238
239 /*
240 * set serial line attributes
241 */
242 rc = ser_setspeed(fdp, baud);
243 if (rc) {
244 fprintf(stderr,
245 "%s: ser_open(): can't set attributes for device \"%s\": %s\n",
246 progname, port, strerror(-rc));
247 exit(1);
248 }
249 }
250
251
252 static void ser_close(union filedescriptor *fd)
253 {
254 /*
255 * restore original termios settings from ser_open
256 */
257 if (saved_original_termios) {
258 int rc = tcsetattr(fd->ifd, TCSANOW | TCSADRAIN, &original_termios);
259 if (rc) {
260 fprintf(stderr,
261 "%s: ser_close(): can't reset attributes for device: %s\n",
262 progname, strerror(errno));
263 }
264 saved_original_termios = 0;
265 }
266
267 close(fd->ifd);
268 }
269
270
271 static int ser_send(union filedescriptor *fd, unsigned char * buf, size_t buflen)
272 {
273 struct timeval timeout, to2;
274 int rc;
275 unsigned char * p = buf;
276 size_t len = buflen;
277
278 if (!len)
279 return 0;
280
281 if (verbose > 3)
282 {
283 fprintf(stderr, "%s: Send: ", progname);
284
285 while (buflen) {
286 unsigned char c = *buf;
287 if (isprint(c)) {
288 fprintf(stderr, "%c ", c);
289 }
290 else {
291 fprintf(stderr, ". ");
292 }
293 fprintf(stderr, "[%02x] ", c);
294
295 buf++;
296 buflen--;
297 }
298
299 fprintf(stderr, "\n");
300 }
301
302 timeout.tv_sec = 0;
303 timeout.tv_usec = 500000;
304 to2 = timeout;
305
306 while (len) {
307 rc = write(fd->ifd, p, (len > 1024) ? 1024 : len);
308 if (rc < 0) {
309 fprintf(stderr, "%s: ser_send(): write error: %s\n",
310 progname, strerror(errno));
311 exit(1);
312 }
313 p += rc;
314 len -= rc;
315 }
316
317 return 0;
318 }
319
320
321 static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
322 {
323 struct timeval timeout, to2;
324 fd_set rfds;
325 int nfds;
326 int rc;
327 unsigned char * p = buf;
328 size_t len = 0;
329
330 timeout.tv_sec = serial_recv_timeout / 1000L;
331 timeout.tv_usec = (serial_recv_timeout % 1000L) * 1000;
332 to2 = timeout;
333
334 while (len < buflen) {
335 reselect:
336 FD_ZERO(&rfds);
337 FD_SET(fd->ifd, &rfds);
338
339 nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
340 if (nfds == 0) {
341 if (verbose > 1)
342 fprintf(stderr,
343 "%s: ser_recv(): programmer is not responding\n",
344 progname);
345 return -1;
346 }
347 else if (nfds == -1) {
348 if (errno == EINTR || errno == EAGAIN) {
349 fprintf(stderr,
350 "%s: ser_recv(): programmer is not responding,reselecting\n",
351 progname);
352 goto reselect;
353 }
354 else {
355 fprintf(stderr, "%s: ser_recv(): select(): %s\n",
356 progname, strerror(errno));
357 exit(1);
358 }
359 }
360
361 rc = read(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len);
362 if (rc < 0) {
363 fprintf(stderr, "%s: ser_recv(): read error: %s\n",
364 progname, strerror(errno));
365 exit(1);
366 }
367 p += rc;
368 len += rc;
369 }
370
371 p = buf;
372
373 if (verbose > 3)
374 {
375 fprintf(stderr, "%s: Recv: ", progname);
376
377 while (len) {
378 unsigned char c = *p;
379 if (isprint(c)) {
380 fprintf(stderr, "%c ", c);
381 }
382 else {
383 fprintf(stderr, ". ");
384 }
385 fprintf(stderr, "[%02x] ", c);
386
387 p++;
388 len--;
389 }
390 fprintf(stderr, "\n");
391 }
392
393 return 0;
394 }
395
396
397 static int ser_drain(union filedescriptor *fd, int display)
398 {
399 struct timeval timeout;
400 fd_set rfds;
401 int nfds;
402 int rc;
403 unsigned char buf;
404
405 timeout.tv_sec = 0;
406 timeout.tv_usec = 250000;
407
408 if (display) {
409 fprintf(stderr, "drain>");
410 }
411
412 while (1) {
413 FD_ZERO(&rfds);
414 FD_SET(fd->ifd, &rfds);
415
416 reselect:
417 nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout);
418 if (nfds == 0) {
419 if (display) {
420 fprintf(stderr, "<drain\n");
421 }
422
423 break;
424 }
425 else if (nfds == -1) {
426 if (errno == EINTR) {
427 goto reselect;
428 }
429 else {
430 fprintf(stderr, "%s: ser_drain(): select(): %s\n",
431 progname, strerror(errno));
432 exit(1);
433 }
434 }
435
436 rc = read(fd->ifd, &buf, 1);
437 if (rc < 0) {
438 fprintf(stderr, "%s: ser_drain(): read error: %s\n",
439 progname, strerror(errno));
440 exit(1);
441 }
442 if (display) {
443 fprintf(stderr, "%02x ", buf);
444 }
445 }
446
447 return 0;
448 }
449
450 struct serial_device serial_serdev =
451 {
452 .open = ser_open,
453 .setspeed = ser_setspeed,
454 .close = ser_close,
455 .send = ser_send,
456 .recv = ser_recv,
457 .drain = ser_drain,
458 .flags = SERDEV_FL_CANSETSPEED,
459 };
460
461 struct serial_device *serdev = &serial_serdev;
462
463 #endif /* WIN32NATIVE */
Something went wrong with that request. Please try again.