// This installs the Hearsay serial port module driver

int Device_Claim=0x1;
int Device_Channel=0x2;

int Device_TxRate=0x43AC1;
int Device_RxRate=0x43AC2;
int Device_ParityBits=0x43AC3;
int Device_DataBits=0x43AC4;
int Device_StopBits=0x43AC5;
int Device_Status=0x43AC6;
int Device_Flow=0x43AC7;
int Device_Select=0x43AC8;
int Device_Break=0x43AC9;
int Device_Get=0x43ACA;
int Device_Put=0x43ACB;
int Device_CountPurge=0x43ACC;
int OS_SerialOp=0x57;
int Device_Register=0x43ACD;
int Device_BlockRead=0x43ACE;
int Device_BlockWrite=0x43ACF;


int SERIAL_RI =0x100000;
int SERIAL_DSR= 0x80000;
int SERIAL_DCD= 0x40000;
int SERIAL_DTR= 0x8;


int devblockmode;
int devratelimit;


int device_initiate(void)
{
 string s;
 
 s="RMEnsure UtilityModule 3.10 RMEnsure UtilityModule 3.00 RMEnsure Hearsay 1.00 WimpTask Run <Hearsay$Resources>.Hearsay";

 if(!osclis(s))
 {
  s="RMEnsure UtilityModule 3.10 RMEnsure Hearsay 1.00 Run <Hearsay$Resources>.HearsayA5D";
  if(!osclis(s))
  {
   s="RMEnsure Hearsay       1.00 Run <Hearsay$Resources>.HearsayA5";

   if(!osclis(s))
   {
    swi13(Device_Register,1,0,0);
    devblockmode=0;
    devratelimit=19200;

    s="RMEnsure Hearsay      2.02 Error 0";
    if(!osclis(s))
    {
     if(osversion()>=0xA4)
     {
      devblockmode=1;
      s="RMEnsure SerialDeviceDriver 0.22 Run System:Modules.SerialDev";
      if(osclis(s))
      {
       s="RMEnsure SerialDeviceDriver 0.22 Run <Hearsay$Dir>.Modules.SerialDev";
       osclis(s);
      }

      if(osversion()>=0xA5)
      {
       devratelimit=115200;
      }
     }
    }
    return(0);
   }
  }
 }
 

 errorbox(s);
 return(1);
}



void device_terminate(void)
{
 int code;

 code=swi13(Device_Register,0,0,0);
 if(!code) osclis("RMKill Hearsay");
}


int devdcdbit;

int devcon(int fn,int port,int p1,int p2)
{
 int code;

 if(fn==Device_Select)
 {
  code=swi13(fn,port,p1,p2);
  if(p1)
  {
   devdcdbit=swi13(Device_Status,port,0,-1) & SERIAL_DCD;
//   if(devdcdbit) swi13(Device_Status,port,2,~2);
//   Comment the above line, and uncomment the next line to ignore DSR
   if(devdcdbit) swi13(Device_Status,port,(2|4),~(2|4));

//   After using the internal block driver, the next line needs
//   to be uncommented to make the serial port work
     swi13(Device_Status,port,0,~(SERIAL_DTR));
  }
 }
 else
 if(fn==Device_Status)
 {
  if(devdcdbit) swi13(Device_Status,port,0,~2);
  code=swi13(Device_Status,port,0,-1);
  if(devdcdbit)
  {
   swi13(Device_Status,port,2,~2);
   code^=SERIAL_DCD;
  }
  else
  {
   code&=~SERIAL_DCD;
   if(code & SERIAL_RI) code|=SERIAL_DCD;
  }
 }
 else
 if(fn>=0x100) 
 {
  if(fn==Device_TxRate && p2 && p1>devratelimit) p1=devratelimit;
  else
  if(fn==Device_RxRate && p2 && p1>devratelimit) p1=devratelimit;

  code=swi13(fn,port,p1,p2);
 }
 else
 {
  if(fn==Device_Claim)
  {
   code=claimdevice(2,0);
  }
  else
  if(fn==Device_Channel)
  {
   if(devblockmode)
   {
    setchannel(TX,3,Device_BlockWrite,port);
    setchannel(RX,3,Device_BlockRead,port);
   }
   else
   if(port)
   {
    setchannel(TX,0,Device_Put,port);
    setchannel(RX,0,Device_Get,port);
   }
   else
   {
    setchannel(TX,0,OS_SerialOp,3);
    setchannel(RX,0,OS_SerialOp,4);
   }
   code=0;
  }
 }
 return(code);
}

