patch #8380: adds 500k 1M 2M baud to ser_posix.c

* ser_posix.c: Add a hack to allow for arbitrary baud rates on
Linux




git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1351 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Joerg Wunsch 2014-11-25 21:33:22 +00:00
parent 3fd1765025
commit be5defaa86
3 changed files with 92 additions and 6 deletions

View File

@ -1,3 +1,9 @@
2014-11-25 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
patch #8380: adds 500k 1M 2M baud to ser_posix.c
* ser_posix.c: Add a hack to allow for arbitrary baud rates on
Linux
2014-11-25 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
patch #8437: [PATCH] Serial-over-ethernet for Win32

4
NEWS
View File

@ -28,6 +28,9 @@ Current:
- The "-P net:" syntax (forwarding of serial data over TCP) is now
also implemented for Win32 systems.
- Allow for arbitrary serial baudrates under Linux (OSX and *BSD
could already handle it).
* New devices supported:
- AT90PWM216 (bug #42310: New part description for AT90PWM216)
@ -57,6 +60,7 @@ Current:
- bug #40870: config nitpick: ATtiny25/45/85 have 1 calibration byte not 2
- bug #42908: no external reset at JTAGICE3
- patch #8437: [PATCH] Serial-over-ethernet for Win32
- patch #8380: adds 500k 1M 2M baud to ser_posix.c
* Internals:
- Removing exit calls from config parser

View File

@ -37,6 +37,9 @@
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#ifdef __linux__
#include <linux/serial.h>
#endif
#include <fcntl.h>
#include <termios.h>
@ -52,8 +55,13 @@ struct baud_mapping {
speed_t speed;
};
/* There are a lot more baud rates we could handle, but what's the point? */
static struct termios original_termios;
static int saved_original_termios;
#if !defined __linux__
/* For linux this mapping is no longer needed.
* (OSX and *BSD do not need this mapping either because for them,
* Bxxx is the same as xxx.) */
static struct baud_mapping baud_lookup_table [] = {
{ 1200, B1200 },
{ 2400, B2400 },
@ -73,8 +81,6 @@ static struct baud_mapping baud_lookup_table [] = {
{ 0, 0 } /* Terminator. */
};
static struct termios original_termios;
static int saved_original_termios;
static speed_t serial_baud_lookup(long baud)
{
@ -95,12 +101,19 @@ static speed_t serial_baud_lookup(long baud)
return baud;
}
#endif
static int ser_setspeed(union filedescriptor *fd, long baud)
{
int rc;
struct termios termios;
#if defined __linux__
/* for linux no conversion is needed*/
speed_t speed = baud;
#else
/* converting the baud rate to the bit set needed by posix way*/
speed_t speed = serial_baud_lookup (baud);
#endif
if (!isatty(fd->ifd))
return -ENOTTY;
@ -128,16 +141,79 @@ static int ser_setspeed(union filedescriptor *fd, long baud)
termios.c_cflag = (CS8 | CREAD | CLOCAL);
termios.c_cc[VMIN] = 1;
termios.c_cc[VTIME] = 0;
#ifdef __linux__
/* Support for custom baud rate for linux is implemented by setting
* a dummy baud rate of 38400 and manupulating the custom divider of
* the serial interface*/
struct serial_struct ss;
int ioret = ioctl(fd->ifd, TIOCGSERIAL, &ss);
if (ioret < 0){
avrdude_message(MSG_INFO,
"%s: Cannot get serial port settings. ioctl returned %d\n",
progname, ioret);
return -errno;
}
ss.flags = (ss.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
ss.custom_divisor = (ss.baud_base + (speed / 2)) / speed;
unsigned int closestSpeed = ss.baud_base / ss.custom_divisor;
cfsetospeed(&termios, speed);
cfsetispeed(&termios, speed);
if (closestSpeed < speed * 98 / 100 || closestSpeed > speed * 102 / 100) {
avrdude_message(MSG_INFO,
"%s: Cannot set serial port speed to %d. Closest possible is %d\n",
progname, speed, closestSpeed);
return -errno;
}
ioret= ioctl(fd->ifd, TIOCSSERIAL, &ss);
if (ioret < 0){
avrdude_message(MSG_INFO,
"%s: Cannot set serial port speed to %d. ioctl returned %d\n",
progname, speed, ioret);
return -errno;
}
if (cfsetispeed(&termios, B38400) < 0){
avrdude_message(MSG_INFO,
"%s: cfsetispeed: failed to set dummy baud\n",
progname);
return -errno;
}
if (cfsetospeed(&termios, B38400) < 0){
avrdude_message(MSG_INFO,
"%s: cfsetospeed: failed to set dummy baud\n",
progname);
return -errno;
}
#else /* !linux */
if (cfsetospeed(&termios, speed) < 0){
avrdude_message(MSG_INFO,
"%s: cfsetospeed: failed to set speed: %d\n",
progname, speed);
return -errno;
}
if (cfsetispeed(&termios, speed) < 0){
avrdude_message(MSG_INFO,
"%s: cfsetispeed: failed to set speed: %d\n",
progname, speed);
return -errno;
}
#endif /* linux */
rc = tcsetattr(fd->ifd, TCSANOW, &termios);
if (rc < 0) {
avrdude_message(MSG_INFO, "%s: ser_setspeed(): tcsetattr() failed\n",
progname);
return -errno;
}
#ifdef __linux__
/* a bit more linux specific stuff to set custom baud rates*/
if (ioctl(fd->ifd, TIOCGSERIAL, &ss) < 0){
avrdude_message(MSG_INFO, "%s: ioctl: failed to get port settins\n", progname);
return -errno;
}
ss.flags &= ~ASYNC_SPD_MASK;
if (ioctl(fd->ifd, TIOCSSERIAL, &ss) < 0){
avrdude_message(MSG_INFO, "%s: ioctl: failed to set port settins\n", progname);
return -errno;
}
#endif
/*
* Everything is now set up for a local line without modem control