Hi Jim,

Almost a year ago to the day I encountered the same problem; trying to get non-standard baud rates working on OSX. It's simple when you know what to do but there's a lot of out dated and just wrong info on this subject. Ultimately I worked out one solution (for Snow Leopard at the time and since tested to work okay on Lion but not yet tested on Mountain Lion).

I posted a summary you can read here:

http://sourceforge.net/mailarchive/message.php?msg_id=27950111

and I've append the patch for you here.

Hope this helps.

Cheers, Bruce.

On 05/08/12 08:49, Jim Kueneman wrote:
Excellent Marco thank you.

Next question, has there been any work to allow custom baud rates to work in 
synaser on the Mac?


http://stackoverflow.com/questions/4968529/how-to-set-baud-rate-to-307200-on-linux
http://comments.gmane.org/gmane.comp.audio.supercollider.user/42429

The second one claims the Apple implementation of IOSSIOSPEED is broken.  
Instead of pulling out my hair I will ask first.

Thanks,
Jim



On Aug 4, 2012, at 8:22 AM, Marco van de Voort wrote:

On 4-8-2012 4:16, Jim Kueneman wrote:

http://lazarus.freepascal.org/index.php/topic,17705.0.html
IIRC that thread lead to the following report:

http://bugs.freepascal.org/view.php?id=21665

and several fixes. Currently the Mac related fixes have not been merged
back to the fixes branch, but I hope they will, and thus will make it to
2.6.2 in fall.

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
synalist-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/synalist-public

*** a/synaser.pas	Tue Aug 16 10:02:01 2011
--- b/synaser.pas	Tue Aug 16 10:04:09 2011
***************
*** 195,200 ****
--- 195,232 ----
    end;
    PDCB = ^TDCB;
  
+ {$IFDEF LINUX}
+ { Translated from include/linux/serial.h }
+ type
+   TSerialStruct = packed record
+ 	  typ: Integer;
+ 	  line: Integer;
+ 	  port: Cardinal;
+ 	  irq: Integer;
+ 	  flags: Integer;
+ 	  xmit_fifo_size: Integer;
+ 	  custom_divisor: Integer;
+ 	  baud_base: Integer;
+ 	  close_delay: Word;
+ 	  io_type: Char;
+ 	  reserved_char: Char;
+ 	  hub6: Integer;
+ 	  closing_wait: Word; // time to wait before closing
+ 	  closing_wait2: Word; // no longer used...
+ 	  iomem_base: ^Char;
+ 	  iomem_reg_shift: Word;
+ 	  port_high: Cardinal;
+ 	  iomap_base: LongWord; // cookie passed into ioremap
+   end;
+ 
+ const
+ { Translated from include/linux/serial.h | 1818 }
+   ASYNC_SPD_MASK = $1030;
+   ASYNC_SPD_CUST = $0030;
+ { Baud rate dividend assuming FT232BM compatible devices | 1818 }
+   FT_BAUD_BASE = 48000000;
+ {$ENDIF}
+ 
  const
  {$IFDEF UNIX}
    {$IFDEF DARWIN}
***************
*** 248,253 ****
--- 280,289 ----
  {$IFDEF DARWIN}
  const // From fcntl.h
    O_SYNC = $0080;  { synchronous writes }
+ { FIOSSIOSPEED is from /System/Library/Frameworks/IOKit.framework/Versions/A/Headers/serial/ioss.h
+   Its definition will be in $FPC/rtl/darwin/termios.inc soon with any luck. For details see:
+   http://lists.freepascal.org/lists/fpc-pascal/2011-August/030025.html }
+   FIOSSIOSPEED = (IOC_IN or (sizeof(culong) and IOCPARM_MASK) << 16) or ((ord('T') << 8) or 2); { 18399.13 }
  {$ENDIF}
  
  const
***************
*** 943,949 ****
  {$IFNDEF FPC}
    FHandle := THandle(Libc.open(pchar(FDevice), O_RDWR or O_SYNC));
  {$ELSE}
!   FHandle := THandle(fpOpen(FDevice, O_RDWR or O_SYNC));
  {$ENDIF}
    if FHandle = INVALID_HANDLE_VALUE then  //because THandle is not integer on all platforms!
      SerialCheck(-1)
--- 979,985 ----
  {$IFNDEF FPC}
    FHandle := THandle(Libc.open(pchar(FDevice), O_RDWR or O_SYNC));
  {$ELSE}
!   FHandle := THandle(fpOpen(FDevice, O_RDWR or O_SYNC or O_NONBLOCK));
  {$ENDIF}
    if FHandle = INVALID_HANDLE_VALUE then  //because THandle is not integer on all platforms!
      SerialCheck(-1)
***************
*** 1556,1562 ****
    else
      term.c_cflag := term.c_cflag and (not CSTOPB);
    //set baudrate;
!   x := 0;
    for n := 0 to Maxrates do
      if rates[n, 0] = dcb.BaudRate then
      begin
--- 1592,1598 ----
    else
      term.c_cflag := term.c_cflag and (not CSTOPB);
    //set baudrate;
!   x := B38400; { default (and aliased) baud rate, see TBlockSerial.SetCommState }
    for n := 0 to Maxrates do
      if rates[n, 0] = dcb.BaudRate then
      begin
***************
*** 1627,1636 ****
--- 1663,1721 ----
  
  {$IFNDEF MSWINDOWS}
  procedure TBlockSerial.SetCommState;
+ {$IFDEF LINUX}
+ var
+   Ser : TSerialStruct;
+ {$ENDIF}
  begin
    DcbToTermios(dcb, termiosstruc);
    SerialCheck(tcsetattr(FHandle, TCSANOW, termiosstruc));
    ExceptCheck;
+ {$IFDEF DARWIN}
+ { Use FIOSSIOSPEED to assign the baud rate directly. This overides the
+   baud rate assigned via the cfsetXspeed functions above but they must
+   still be called to assign valid control flag values in the termios }
+   SerialCheck(fpIoctl(integer(FHandle), FIOSSIOSPEED, @dcb.BaudRate));
+   ExceptCheck;
+ {$ELSE}
+ { Use TIOCSSERIAL to assign the baud rate directly. This overrides the
+   baud rate assigned via the cfsetXspeed functions above but they must
+   still be called to assign valid control flag values in the termios.
+   If the standard rate B38400 is used the following code will assign
+   the actual baud rate. Otherwise it does nothing. This assumes we're
+   dealing with an FT232xx (or compatible) device per step 3 in comments
+   from the Linux driver reproduced here | 1818
+ 
+      * The logic involved in setting the baudrate can be cleanly split in 3 steps.
+      * Obtaining the actual baud rate is a little tricky since unix traditionally
+      * somehow ignored the possibility to set non-standard baud rates.
+      * 1. Standard baud rates are set in tty->termios->c_cflag
+      * 2. If these are not enough, you can set any speed using alt_speed as follows:
+      *    - set tty->termios->c_cflag speed to B38400
+      *    - set your real speed in tty->alt_speed; it gets ignored when
+      *      alt_speed==0, (or)
+      *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
+      *      flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], this just
+      *      sets alt_speed to (HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800)
+      * ** Steps 1, 2 are done courtesy of tty_get_baud_rate
+      * 3. You can also set baud rate by setting custom divisor as follows
+      *    - set tty->termios->c_cflag speed to B38400
+      *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
+      *      o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
+      *      o custom_divisor set to baud_base / your_new_baudrate
+      * ** Step 3 is done courtesy of code borrowed from serial.c - I should really
+      *    spend some time and separate+move this common code to serial.c, it is
+      *    replicated in nearly every serial driver you see }
+ 
+     fpIoctl(integer(FHandle), TIOCGSERIAL, @Ser);
+     with Ser do begin
+       baud_base := FT_BAUD_BASE;
+       custom_divisor := (Cardinal(baud_base) div dcb.BaudRate) div 2;
+       flags := flags or ASYNC_SPD_CUST;
+     end;
+     SerialCheck(fpIoctl(integer(FHandle), TIOCSSERIAL, @Ser));
+     ExceptCheck;
+   {$ENDIF}
  end;
  {$ELSE}
  procedure TBlockSerial.SetCommState;
***************
*** 1936,1942 ****
    SerialCheck(ioctl(FHandle, TCFLSH, TCIOFLUSH));
    {$ELSE}
      {$IFDEF DARWIN}
!     SerialCheck(fpioctl(FHandle, TCIOflush, TCIOFLUSH));
      {$ELSE}
      SerialCheck(fpioctl(FHandle, TCFLSH, Pointer(PtrInt(TCIOFLUSH))));
      {$ENDIF}
--- 2021,2027 ----
    SerialCheck(ioctl(FHandle, TCFLSH, TCIOFLUSH));
    {$ELSE}
      {$IFDEF DARWIN}
!     SerialCheck(fpioctl(FHandle, TCIOflush, Pointer(PtrInt(TCIOFLUSH))));
      {$ELSE}
      SerialCheck(fpioctl(FHandle, TCFLSH, Pointer(PtrInt(TCIOFLUSH))));
      {$ENDIF}
***************
*** 2316,2322 ****
  begin
    try
      TmpPorts := '';
!     if FindFirst('/dev/ttyS*', $FFFFFFFF, sr) = 0 then
      begin
        repeat
          if (sr.Attr and $FFFFFFFF) = Sr.Attr then
--- 2401,2407 ----
  begin
    try
      TmpPorts := '';
!     if FindFirst('/dev/ttyS*', LongInt($FFFFFFFF), sr) = 0 then
      begin
        repeat
          if (sr.Attr and $FFFFFFFF) = Sr.Attr then
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
synalist-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/synalist-public

Reply via email to