Problem porting to Mac OS-X

Martin Liddle gpc at tynecomp.co.uk
Wed Jan 16 13:28:12 CET 2008


Just to continue this story, I now have a working executable.  However I
do still have a problem that I would like to resolve.  The software is
using a serial port.  The serial port is provided by a Dynamode USB to
serial adapter (which uses the Prolific chipset). The latest drivers
from the Prolific web site are installed.  My software works correctly
providing that the adapter has just been plugged in.  Attempting to use
the software a second time fails; it looks to me as though some setting
perhaps baud rate isn't correct on subsequent attempts (some times the
first byte from the other end is missed or is incorrect).  An extract of
my code for opening and setting up the serial port is:

type
    Tterm_arg=packed record
              c_iflag:integer;
              c_oflag:integer;
              c_cflag:word;
              c_lflag:integer;
              c_cc   :packed array [0..19] of char;
              c_ispeed:integer;
              c_ospeed:integer;
             end;
var
  fildes_block,fildes_out:integer;
  block_status, write_status:integer;
  term_arg_block,SaveTermArg:Tterm_arg;

function open(protected Path: Cstring; Oflag: word; Mode: word):
integer;
  External;
function
tcsetattr(fd:integer;actions:integer;pt:pointer):integer;External;
function tcgetattr(fd:integer;pt:pointer):integer;External;
procedure cfmakeraw(pt:pointer);External;
function cfsetspeed(pt:pointer;speed:integer):integer;External;
function cfgetispeed(pt:pointer):integer;External;
function cfgetospeed(pt:pointer):integer;External;
function sys_write(Fildes: integer; Buf: pointer; NByte: integer):
integer;
 asmname 'write';
function sys_read(Fildes: integer; Buf: pointer; NByte: integer):
integer;
  asmname 'read';
function sys_close(Fildes: integer): integer; asmname 'close';

function OpenCOMPort: boolean;
CONST
    O_RDONLY = 8#0;
    O_WRONLY = 8#1;
    O_RDWR   = 8#2;
    O_NONBLOCK= 8#4;

var
  Result : boolean;
  Mode:Word;
begin
 Result:=True;
 SerialDevicename:='usbserial';
 block_status:=integer(O_RDWR or O_NONBLOCK);
 mode:=0;
 fildes_block:=open(String2Cstring('/dev/tty.'+SerialDeviceName),word(blo
ck_status),mode);
 if fildes_block<=0 then
  begin
   Result:=False;
  end;
 OpenCOMPort := Result;
end;

function SetupCOMPort: boolean;
const
      CS8    =16#0300;
      CLOCAL =16#8000;
      CREAD  =16#0800;
      VMIN=16;
      VTIME=17;

var loop,InputSpeed,OutputSpeed:integer;
    dummy:word;
    Result : boolean;

begin (*SetupComPort*)
 retval:=tcgetattr(fildes_block,Addr(SaveTermArg));
 If Retval<0 then
  Begin
   Writeln('Error retrieving existing serial port settings.');
   Halt;
  End;
 Term_arg_block:=SaveTermArg;
 With term_arg_block Do
  Begin
   c_iflag:=0;
   c_oflag:=0;
   c_cflag:=(CREAD or CLOCAL or CS8);
   c_lflag:=0;
   for loop:=0 to 19 do c_cc[loop]:=chr(0);
  End;
 Result := True;
 cfmakeraw(Addr(term_arg_block));
 Retval:=cfsetspeed(Addr(Term_arg_block),115200);
 If Retval=-1 then
  Begin
   Writeln('Error when setting speed.');
   Halt;
  End;
 retval:=tcsetattr(fildes_block,TCSANOW,Addr(term_arg_block));
 if retval=-1 then
  begin
   ErrorString:=CStringStrError(ErrorNumber);
   writeln(' When setting blocking, tcsetattr returned ',retval:1,
           ' errno ',ErrorNumber:1);
   writeln('   ',CString2String(ErrorString));
   Result:=False;
  end;
 SetupCOMPort := Result;
end;

Procedure WriteBuffer(Buffer : TBuffer; Size : longint);
var
  Count: LongWord;
begin
 retval:=sys_write(fildes_block,addr(Buffer),Size);
 if retval<0 then
  Begin
   ErrorString:=CStringStrError(ErrorNumber);
   writeln('Error from sys_write in writebuffer, retval = ',
             retval:1,' error = ',ErrorNumber);
   writeln('   ',CString2String(ErrorString));
  End;
end;

Procedure WriteByte(b : byte);
var
  Count: LongWord;
Begin
 retval:=sys_write(fildes_block,addr(b),1);
 if retval<0 then
  Begin
   ErrorString:=CStringStrError(ErrorNumber);
   writeln('Error from sys_write in writebyte, retval = ',
             retval:1,' error = ',ErrorNumber);
   writeln('   ',CString2String(ErrorString));
   Halt;
  End;
End;

Function ReadByte(var b : byte) : boolean;
Var LoopCount,Retval:Integer;
begin
 b:=0;
 LoopCount:=0;
 Retval:=0;
 Repeat
  retval:=sys_read(fildes_block,addr(b),1);
  If Retval<=0 then
   Begin
    Inc(LoopCount);
    SleepMicroSeconds(50);
   End;
 Until (Retval>0) or (Loopcount>20000);
 ReadByte:=(RetVal>0);
End;

Procedure CloseCOMPort;
Var Retval:Integer;
Begin
 retval:=tcsetattr(fildes_block,TCSANOW,Addr(SaveTermArg));
 Retval:=Sys_close(Fildes_block);
End;

Any thoughts about why this only works once?  Any other comments or
suggestions on the code snippet?
-- 
Martin Liddle, Tynemouth Computer Services, 3 Kentmere Way,
Staveley, Chesterfield, Derbyshire, S43 3TW.
Web site: <http://www.tynecomp.co.uk>.





More information about the Gpc mailing list