use Win32::TieRegistry(qw(:KEY_));

use Win32::SerialPort;
# use cpan to install Win32::SerialPort as follows:
# Start menu, All Programs, Strawberry Perl, Tools, CPAN Client, install Win32::SerialPort, exit
# If it fails, then search in C:\strawberry\... for serialport
#   then manually copy SerialPort.pm into C:\strawberry\perl\site\lib\Win32 (create Win32 directory if necessary)
#   and copy CommPort.pm into C:\strawberry\perl\site\lib\Win32API (create Win32API directory if necessary)


#Read SQM-LU

$Regkey="HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\";
$RegCOMkey="HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM\\";


# Check if FTDI "key" exists.
# This is an indication that either the device is not installed or that the FTDI driver is not installed.
$FTDIExists=0;
$FTDIKey= $Registry->Open($Regkey,{Access=>KEY_READ})
  or  die "Can't read Enum key: $^E\n";
foreach $FTDIKeyentry (  keys(%$FTDIKey)  ) {
  if ($FTDIKeyentry =~ /FTDIBUS/){
    $FTDIExists++;
  }
}
if ($FTDIExists==0){
 print "\n\tThe FTDI driver or SQM-LU device is not installed.\n";
 print "\n\tMake sure that the device is attached and that the FTDI VCP\n";
 print "\tdriver has been installed.\n";
 print "\n\tThe latest driver can be obtained from ftdichip.com/Drivers/VCP.htm\n";
 exit;
}


#Check active COM ports for VCP devices
$COMKey= $Registry->Open($RegCOMkey,{Access=>KEY_READ()})
  or  die "Can't read SERIALCOMM key: $^E\n";
$found=0;
foreach $entry (  keys(%$COMKey)  ) {
    if ($entry =~ /Device\\VCP/){
    #print "FTDI VCP device found at: ".$Registry->Open($RegCOMkey,{Access=>KEY_READ()})->{$entry}."\n";
    $found++;
  }
}
if ($found==0){
   print "\n\tNo active VCP devices found.\n";
   print "\n\tMake sure that the SQM-LU is attached.\n";
   exit;
}

#Check defined FTDI COM port assignments for matches to Active COM ports
$FTDIKeys= $Registry->Open($Regkey."FTDIBUS",{Access=>KEY_READ})
  or  die "Can't read FTDI key: $^E\n";
foreach $entry (  keys(%$FTDIKeys)  ) {
  $FTDIKey= $Registry->Open($Regkey."FTDIBUS\\".$entry."\\0000\\",{Access=>KEY_READ})
    or  die "Can't read FTDI Device key: $^E\n";
  foreach $FTDIKeyentry (  keys(%$FTDIKey)  ) {
    if ($FTDIKeyentry =~ /Device Parameters/){
      $somekeys= $Registry->Open($Regkey."FTDIBUS\\".$entry."\\0000\\".$FTDIKeyentry,{Access=>KEY_READ});
      foreach $somekey (  keys(%$somekeys)  ) {
        if ($somekey =~ /PortName/){
		  #Check through all active com ports
          foreach $COMentry (  keys(%$COMKey)  ) {
		    #Filter VCP com ports
            if ($COMentry =~ /Device\\VCP/){
              $ActiveCOM= $Registry->Open($RegCOMkey,{Access=>KEY_READ()})->{$COMentry};
              $DefinedCOM= $somekeys->{$somekey};
			  #Filter matches of active com ports with FTDI defined (previously recognized) com ports
			  if ($ActiveCOM eq $DefinedCOM) {
			    $DefinedSerial=substr($entry,18,8);
                #print "".$DefinedSerial."\t".$DefinedCOM."\n";;

                $PortName = $DefinedCOM;
                #print "PortName=".$PortName."\n";

                $PortObj = new Win32::SerialPort ("\\\\.\\$PortName", $quiet)
                       || die "Can't open $PortName: $^E\n";    # $quiet is optional

  			    $PortObj->user_msg(ON);
  			    $PortObj->databits(8);
  			    $PortObj->baudrate(115200);
  			    $PortObj->parity("none");
  			    $PortObj->stopbits(1);
  			    $PortObj->handshake("rts");
  			    $PortObj->buffers(4096, 4096);
  			    $PortObj->write_settings || undef $PortObj;

                $PortObj->write("rx\r");
                sleep 1;
                my $result = $PortObj->input; 
                print "$DefinedSerial\t$result\n";
    
                $PortObj->close || die "failed to close";
                undef $PortObj;                               # frees memory back to perl
  
  			  }
            }
          }
		}
      }
    }
  }
}


