int main( VecString args )
{
  bool showall = false;
  bool compact = false;
  //bool recovery = false;

  for( VecString::size_type n=1; n!=args.size(); n++ )
  {
    StringRef opt = args[n];
    if( opt == "-h" ) { usage(); return 0; }
    else if( opt == "-l" ) { showall = true; }
    else if( opt == "-c" ) { compact = true; }
    else if( opt == "-c" ) { compact = true; }
    else { usage(); throw std::runtime_error("unknown command line option "+opt); }
  }

  ListDevice devs = getDevices();

  if( showall == false )
    devs = getActiveDevices( devs );

  devs.sort();

  if( devs.empty() )
    { cout << "No devices found." << endl; return 2; }
  else if( compact )
    printDevices( devs );
  else
    prettyPrintDevices( devs );

  return 0;
}
void printDevices( const ListDevice& devs )
{
  for( ListDevice::const_iterator i=devs.begin(); i!=devs.end(); i++ )
  {
    cout << i->id << "," << i->comm << ","
	 << i->refcount << "," << i->info << endl;
  }
}
ListDevice getActiveDevices( const ListDevice& devs )
{
  ListDevice active;
  for( ListDevice::const_iterator i=devs.begin(); i!=devs.end(); i++ )
  {
    if( i->refcount > 0 )
      active.push_back( *i );
  }
  return active;
}
ListDevice getDevices()
{
    ListDevice devs;

    String ccs = "SYSTEM\\CurrentControlSet\\";
    RegKey dclass( HKEY_LOCAL_MACHINE, ccs+"Control\\DeviceClasses" );
    RegKey ftdibus( HKEY_LOCAL_MACHINE, ccs+"Enum\\FTDIBUS" );
    RegKey usb6001( HKEY_LOCAL_MACHINE, ccs+"Enum\\USB\\Vid_0403&Pid_6001" );

    VecString fdev = ftdibus.getSubkeyNames();
    for( VecString::const_iterator i=fdev.begin(); i!=fdev.end(); i++ )
    {
        if( i->substr(0,18) == String("VID_0403+PID_6001+") )
        {
            Device d;
            d.id = i->substr(18,8);

            try
            {
                RegKey devkey = ftdibus[*i];
                VecString devsub = devkey.getSubkeyNames();
                d.comm = devkey[devsub[0]+"\\Device Parameters"]("PortName").data;
            }
            catch( std::runtime_error e )
            {
                d.comm = "no_comm";
            }

            try {
                d.info = usb6001[d.id]("LocationInformation").data;
            }
            catch( std::runtime_error e ) { }

            try {
                d.refcount = getRefCount( dclass, usb6001[d.id] );
            }
            catch( std::runtime_error e ) { }

            String::size_type ncomm = d.comm.find_first_of("0123456789");
            if( ncomm != String::npos )
                d.sortnum = atoi( d.comm.substr(ncomm).c_str() );

            devs.push_back(d);
        }
    }

    return devs;
}
void prettyPrintDevices( const ListDevice& devs )
{
  const char* fmt = "%-10s %-10s %s\n";
  printf( fmt, "Reference", "CommPort", "Description" );
  printf( "---------- ---------- ----------------------------------------\n" );

  for( ListDevice::const_iterator i=devs.begin(); i!=devs.end(); i++ )
  {
    String comm = i->comm;
    if( i->refcount == 0 )
    {
      char buf[256];
      int n = snprintf( buf, 255, " (%s)", i->comm.c_str() );
      comm = String( buf, buf+n );
    }
    printf( fmt, i->id.c_str(), comm.c_str(), i->info.c_str() );
  }
}