Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2008-09

[PATCH] unix/serial.pp mods for darwin

5 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Brad Campbell

These additions/changes make serial.pp work for me on MacOS X 10.4 and 10.5, both PPC and Intel.

Comments?

Regards,
Brad

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

Jonas Maebe
to Brad Campbell
Brad Campbell wrote
These additions/changes make serial.pp work for me on MacOS X 10.4 and 10.5, both PPC and Intel. Comments?

Do you also know why these changes are necessary? Adding special cases from a particular platform without any comments (other than "it works now") is unlikely to work in the long term.

Jonas

Reply by email

Brad Campbell
to Jonas Maebe
Jonas Maebe wrote 11 lines
On 30 Sep 2008, at 17:06, Brad Campbell wrote: > These additions/changes make serial.pp work for me on MacOS X 10.4 and > 10.5, both PPC and Intel. > > Comments? Do you also know why these changes are necessary? Adding special cases from a particular platform without any comments (other than "it works now") is unlikely to work in the long term

Index: rtl/unix/serial.pp
=================================================================== --- rtl/unix/serial.pp (revision 11843)
+++ rtl/unix/serial.pp (working copy)
@@ -70,7 +70,14 @@

  function SerOpen(const DeviceName: String): TSerialHandle;
  begin

This is requires as MacOS will block on the open unless Carrier Detect is asserted. So you need to open the port non-blocking and then clear the non-blocking flag. Found this in some apple sample code on the apple dev site.

+  {$IFDEF DARWIN}
+  Result := fpopen(DeviceName, O_RDWR or O_NOCTTY or O_NONBLOCK);
+  { Remove the O_NONBLOCK }
+  If Result > 0 then
+    FpFCNTL(Result, F_SETFL, 0);
+  {$ELSE}
    Result := fpopen(DeviceName, O_RDWR or O_NOCTTY);
+  {$ENDIF}
  end;
  procedure SerClose(Handle: TSerialHandle);
@@ -127,7 +134,11 @@
    tios.c_ispeed := tios.c_cflag;
    tios.c_ospeed := tios.c_ispeed;

This is required as Darwin does not use enums for the baud rate, and simply use the whole numbers. In this case some of the baud rates end up asserting weird flags in the control bits. Darwin uses c_ispeed/c_ospeed rather than extract the baud rate from c_cflag.

+{$ifndef DARWIN}

    tios.c_cflag := tios.c_cflag or CREAD or CLOCAL;

+{$else}
+ tios.c_cflag := CREAD or CLOCAL;
+{$endif}

    case ByteSize of
      5: tios.c_cflag := tios.c_cflag or CS5;
@@ -146,9 +157,10 @@
    if RtsCtsFlowControl in Flags then
      tios.c_cflag := tios.c_cflag or CRTSCTS;

This is actually only required on 10.5 on Intel, but it does not seem to hurt on the other versions. If left in place, this just blocks and stalls the program.

-
+{$IFNDEF DARWIN}

    tcflush(Handle, TCIOFLUSH);

- tcsetattr(Handle, TCSANOW, tios)
+{$ENDIF}
+ tcsetattr(Handle, TCSANOW, tios);

  end;
Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

Jonas Maebe
to Brad Campbell
Brad Campbell wrote 11 lines
This is actually only required on 10.5 on Intel, but it does not seem to hurt on the other versions. If left in place, this just blocks and stalls the program. - +{$IFNDEF DARWIN} tcflush(Handle, TCIOFLUSH); - tcsetattr(Handle, TCSANOW, tios) +{$ENDIF} + tcsetattr(Handle, TCSANOW, tios); end;

How about using "TCSADRAIN or TCSAFLUSH" instead of TCSANOW? As far as I can see, that should have the same effect as the "tcflush(Handle, TCIOFLUSH)". Does that hang too?

Thanks a lot for the explanations. Once this is settled, I'll commit your patch.

Jonas

Reply by email

Jonas Maebe
to Jonas Maebe
Jonas Maebe wrote 17 lines
On 01 Oct 2008, at 08:41, Brad Campbell wrote: > This is actually only required on 10.5 on Intel, but it does not > seem to hurt on the other versions. > If left in place, this just blocks and stalls the program. > > - > +{$IFNDEF DARWIN} > tcflush(Handle, TCIOFLUSH); > - tcsetattr(Handle, TCSANOW, tios) > +{$ENDIF} > + tcsetattr(Handle, TCSANOW, tios); > end; How about using "TCSADRAIN or TCSAFLUSH" instead of TCSANOW? As far as I can see, that should have the same effect as the "tcflush(Handle, TCIOFLUSH)". Does that hang too?

I've found some other code for setting up a serial port on Darwin at http://www.nabble.com/Patch-for-controlling-Pioneer-via-a-Mac-td6672642.html

The full code is at http://playerstage.svn.sourceforge.net/viewvc/playerstage/code/player/trunk/server/drivers/mixed/p2os/p2os.cc?view=markup (in method P2OS::Setup). Some observations:
* they use the cfsetispeed() and cfsetospeed() functions rather than directly writing in the fields. This should probably also be done at least for Darwin
* they also "or" the (CLOCAL | CREAD) flags into the c_flag field, rather just overwriting it (I guess cfsetispeed()/cfsetospeed() will make sure it's set appropriately)
* they also call tcflush() at the end

Since this project seems quite alive, I guess it works fine for them on Mac OS X/Intel, so there may be something else going wrong that requires you to clear the c_flags and remove the flush.

Jonas

They also flush before calling tcsetattr, and they do not appear to be clearing term. c_cflag

Reply by email