Index: ser_posix.c
===================================================================
--- ser_posix.c	(revision 1288)
+++ ser_posix.c	(working copy)
@@ -37,9 +37,12 @@
 #include <sys/socket.h>
 #include <netdb.h>
 #include <netinet/in.h>
+#include <termios.h>
+#include <fcntl.h>
+#ifdef linux
+#include <linux/serial.h>
+#endif
 
-#include <fcntl.h>
-#include <termios.h>
 #include <unistd.h>
 
 #include "avrdude.h"
@@ -52,8 +55,12 @@
   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 __APPLE__ || !defined __MACH__) && !defined linux
+/* The support for other baud rates is imlemented for linux and mac os x only.
+ * For linux and mac os x this mapping is no longer needed*/
 static struct baud_mapping baud_lookup_table [] = {
   { 1200,   B1200 },
   { 2400,   B2400 },
@@ -73,8 +80,6 @@
   { 0,      0 }                 /* Terminator. */
 };
 
-static struct termios original_termios;
-static int saved_original_termios;
 
 static speed_t serial_baud_lookup(long baud)
 {
@@ -91,17 +96,24 @@
    * a warning (if we are verbose) and return the raw rate
    */
   if (verbose > 0)
-      fprintf(stderr, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld",
-              progname, baud);
+    fprintf(stderr, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld\n",
+            progname, baud);
 
   return baud;
 }
+#endif
 
 static int ser_setspeed(union filedescriptor *fd, long baud)
 {
   int rc;
   struct termios termios;
+#if (defined __APPLE__ && defined __MACH__) || defined linux
+  /* for mac os x and 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;
@@ -115,7 +127,6 @@
             progname);
     return -errno;
   }
-
   /*
    * copy termios for ser_close if we haven't already
    */
@@ -129,17 +140,80 @@
   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){
+    fprintf(stderr, "Cannot get serial port settings. ioctl returned %d\n", 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) {
+    fprintf(stderr, "Cannot set serial port speed to %d. Closest possible is %d\n", speed, closestSpeed);
+    return -errno;
+  }
+  ioret= ioctl(fd->ifd, TIOCSSERIAL, &ss);
+  if (ioret < 0){
+    fprintf(stderr, "Cannot set serial port speed to %d. ioctl returned %d\n", speed, ioret);
+    return -errno;
+  }
 
+  if (cfsetispeed(&termios, B38400) < 0){
+    fprintf(stderr, "cfsetispeed: failed to set dummy baud\n");
+    return -errno;
+  }
+  if (cfsetospeed(&termios, B38400) < 0){
+    fprintf(stderr, "cfsetospeed: failed to set dummy baud\n");
+    return -errno;
+  }
+#elif !defined __APPLE__ || !defined __MACH__ //linux
+  /* For system which do not run linux nor mac os x the standard posix way is used to set to baud rate. 
+   * Here only the few baud rates defined in baud_lookup_table are available*/
+  if (cfsetospeed(&termios, speed) < 0){
+    fprintf(stderr, "cfsetospeed: failed to set speed: %d\n",speed);
+    return -errno;
+  }
+  if (cfsetispeed(&termios, speed) < 0){
+    fprintf(stderr, "cfsetispeed: failed to set speed: %d\n",speed);
+    return -errno;
+  }
+#endif //linux
   rc = tcsetattr(fd->ifd, TCSANOW, &termios);
   if (rc < 0) {
     fprintf(stderr, "%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){
+    fprintf(stderr, "ioctl: failed to get port settins\n");
+    return -errno;
+  }
+  ss.flags &= ~ASYNC_SPD_MASK;
+  if (ioctl(fd->ifd, TIOCSSERIAL, &ss) < 0){
+    fprintf(stderr, "ioctl: failed to set port settins\n");
+    return -errno;
+  }
+#endif
 
+#if defined __APPLE__ && defined __MACH__
+  /* This sets a custom baud rate on mac os x*/ 
+#define IOSSIOSPEED _IOW('T', 2, speed_t)
+  unsigned int bufz = (unsigned int)speed;
+  if( ioctl(fd->ifd, IOSSIOSPEED, &bufz) <0 ){
+    fprintf(stderr, "ioctl: failed to set baud rate %u %d \n",bufz,errno);
+    return -errno;
+  }
+
+  if (fcntl(fd->ifd, F_NOCACHE, 1) < 0) {
+    fprintf(stderr,"could not set fcntl");
+  }
+#endif
   /*
    * Everything is now set up for a local line without modem control
    * or flow control, so clear O_NONBLOCK again.
