CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC4_patch1/src/OnlineDB/SiStripConfigDb/src/DeviceDescriptions.cc

Go to the documentation of this file.
00001 // Last commit: $Id: DeviceDescriptions.cc,v 1.38 2011/09/02 11:25:25 eulisse Exp $
00002 
00003 #include "OnlineDB/SiStripConfigDb/interface/SiStripConfigDb.h"
00004 #include "DataFormats/SiStripCommon/interface/SiStripFecKey.h"
00005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00006 
00007 using namespace std;
00008 using namespace sistrip;
00009 
00010 // -----------------------------------------------------------------------------
00011 // 
00012 SiStripConfigDb::DeviceDescriptionsRange SiStripConfigDb::getDeviceDescriptions( std::string partition ) {
00013 
00014   // Check
00015   if ( ( !dbParams_.usingDbCache() && !deviceFactory(__func__) ) ||
00016        (  dbParams_.usingDbCache() && !databaseCache(__func__) ) ) { 
00017     return devices_.emptyRange(); 
00018   }
00019   
00020   try { 
00021 
00022     if ( !dbParams_.usingDbCache() ) { 
00023 
00024       SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
00025       SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
00026       for ( ; iter != jter; ++iter ) {
00027         
00028         if ( partition == "" || partition == iter->second.partitionName() ) {
00029           
00030           if ( iter->second.partitionName() == SiStripPartition::defaultPartitionName_ ) { continue; }
00031 
00032           DeviceDescriptionsRange range = devices_.find( iter->second.partitionName() );
00033           if ( range == devices_.emptyRange() ) {
00034             
00035             // Retrieve conections
00036             DeviceDescriptionsV tmp1;
00037             deviceFactory(__func__)->getFecDeviceDescriptions( iter->second.partitionName(), 
00038                                                                tmp1,
00039                                                                iter->second.fecVersion().first,
00040                                                                iter->second.fecVersion().second,
00041                                                                //#ifdef USING_DATABASE_MASKING
00042                                                                iter->second.maskVersion().first,
00043                                                                iter->second.maskVersion().second,
00044                                                                //#endif
00045                                                                false ); //@@ do not get DISABLED devices
00046             
00047             // Make local copy 
00048             DeviceDescriptionsV tmp2;
00049             FecFactory::vectorCopyI( tmp2, tmp1, true );
00050 
00051             // Add to cache
00052             devices_.loadNext( iter->second.partitionName(), tmp2 );
00053 
00054             // Some debug
00055             DeviceDescriptionsRange range = devices_.find( iter->second.partitionName() );
00056             std::stringstream ss;
00057             ss << "[SiStripConfigDb::" << __func__ << "]"
00058                << " Downloaded " << range.size() 
00059                << " device descriptions to local cache for partition \""
00060                << iter->second.partitionName() << "\"" << std::endl;
00061             ss << "[SiStripConfigDb::" << __func__ << "]"
00062                << " Cache holds device descriptions for " 
00063                << devices_.size() << " partitions.";
00064             LogTrace(mlConfigDb_) << ss.str();
00065 
00066           }
00067           
00068         }
00069         
00070       }
00071       
00072     } else { // Using database cache
00073 
00074       DeviceDescriptionsV* tmp1 = databaseCache(__func__)->getDevices();
00075 
00076       if ( tmp1 ) { 
00077         
00078         // Make local copy 
00079         DeviceDescriptionsV tmp2;
00080         FecFactory::vectorCopyI( tmp2, *tmp1, true );
00081         
00082         // Add to cache
00083         devices_.loadNext( SiStripPartition::defaultPartitionName_, tmp2 );
00084 
00085       } else {
00086         edm::LogWarning(mlConfigDb_)
00087           << "[SiStripConfigDb::" << __func__ << "]"
00088           << " NULL pointer to DeviceDescriptions vector!";
00089       }
00090       
00091     }
00092     
00093   } catch (...) { handleException( __func__ ); }
00094   
00095   // Create range object
00096   uint16_t np = 0;
00097   uint16_t nc = 0;
00098   DeviceDescriptionsRange devs;
00099   if ( partition != "" ) { 
00100     devs = devices_.find( partition );
00101     np = 1;
00102     nc = devs.size();
00103   } else { 
00104     if ( !devices_.empty() ) {
00105       devs = DeviceDescriptionsRange( devices_.find( dbParams_.partitions().begin()->second.partitionName() ).begin(),
00106                                       devices_.find( (--(dbParams_.partitions().end()))->second.partitionName() ).end() );
00107     } else { devs = devices_.emptyRange(); }
00108     np = devices_.size();
00109     nc = devs.size();
00110   }
00111   
00112   stringstream ss; 
00113   ss << "[SiStripConfigDb::" << __func__ << "]"
00114      << " Found " << nc << " device descriptions";
00115   if ( !dbParams_.usingDb() ) { ss << " in " << dbParams_.inputFecXmlFiles().size() << " 'fec.xml' file(s)"; }
00116   else { if ( !dbParams_.usingDbCache() )  { ss << " in " << np << " database partition(s)"; } 
00117   else { ss << " from shared memory name '" << dbParams_.sharedMemory() << "'"; } }
00118   if ( devices_.empty() ) { edm::LogWarning(mlConfigDb_) << ss.str(); }
00119   else { LogTrace(mlConfigDb_) << ss.str(); }
00120   
00121   return devs;
00122 
00123 }
00124 
00125 // -----------------------------------------------------------------------------
00126 // 
00127 SiStripConfigDb::DeviceDescriptionsRange SiStripConfigDb::getDeviceDescriptions( DeviceType device_type, 
00128                                                                                  std::string partition ) {
00129   
00130   typedDevices_.clear();
00131   apvDevices_.clear();
00132   muxDevices_.clear();
00133   dcuDevices_.clear();
00134   lldDevices_.clear();
00135   pllDevices_.clear();
00136   dohDevices_.clear();
00137   
00138   DeviceDescriptionsRange tmp( typedDevices_.end(), typedDevices_.end() );
00139   
00140   if ( ( !dbParams_.usingDbCache() && !deviceFactory(__func__) ) ||
00141        (  dbParams_.usingDbCache() && !databaseCache(__func__) ) ) { 
00142     return tmp;
00143   }
00144   
00145   try { 
00146     DeviceDescriptionsRange devs = SiStripConfigDb::getDeviceDescriptions( partition );
00147     if ( !devs.empty() ) {
00148       DeviceDescriptionsV tmp( devs.begin(), devs.end() );
00149       typedDevices_ = FecFactory::getDeviceFromDeviceVector( tmp, device_type );
00150     }
00151   } catch (...) { handleException( __func__ ); }
00152   
00153   if ( device_type == APV25 ) { 
00154     apvDevices_.swap( typedDevices_ ); 
00155     tmp = DeviceDescriptionsRange( apvDevices_.begin(), apvDevices_.end() );
00156   } else if ( device_type == APVMUX ) { 
00157     muxDevices_.swap( typedDevices_ );  
00158     tmp = DeviceDescriptionsRange( muxDevices_.begin(), muxDevices_.end() );
00159   } else if ( device_type == DCU ) { 
00160     dcuDevices_.swap( typedDevices_ ); 
00161     tmp = DeviceDescriptionsRange( dcuDevices_.begin(), dcuDevices_.end() );
00162   } else if ( device_type == LASERDRIVER ) { 
00163     lldDevices_.swap( typedDevices_ ); 
00164     tmp = DeviceDescriptionsRange( lldDevices_.begin(), lldDevices_.end() );
00165   } else if ( device_type == PLL ) { 
00166     pllDevices_.swap( typedDevices_ ); 
00167     tmp = DeviceDescriptionsRange( pllDevices_.begin(), pllDevices_.end() );
00168   } else if ( device_type == DOH ) { 
00169     dohDevices_.swap( typedDevices_ ); 
00170     tmp = DeviceDescriptionsRange( dohDevices_.begin(), dohDevices_.end() );
00171   } else {
00172     tmp = DeviceDescriptionsRange( typedDevices_.begin(), typedDevices_.end() );
00173   }
00174 
00175 //   stringstream sss; 
00176 //   sss << " Number of devices:" 
00177 //       << " TYP: " << typedDevices_.size()
00178 //       << " APV: " << apvDevices_.size()
00179 //       << " MUX: " << muxDevices_.size()
00180 //       << " DCU: " << dcuDevices_.size()
00181 //       << " LLD: " << lldDevices_.size()
00182 //       << " PLL: " << pllDevices_.size()
00183 //       << " DOH: " << dohDevices_.size()
00184 //       << " tmp: " << tmp.size();
00185 //   LogTrace(mlConfigDb_) << sss.str();
00186 
00187   stringstream ss; 
00188   ss << "[SiStripConfigDb::" << __func__ << "]"
00189      << " Extracted " << tmp.size() 
00190      << " device descriptions (for devices of type " 
00191      << deviceType( device_type ) << ")";
00192   LogTrace(mlConfigDb_) << ss.str();
00193   
00194   return tmp;
00195   
00196 }
00197 
00198 // -----------------------------------------------------------------------------
00199 // 
00200 void SiStripConfigDb::addDeviceDescriptions( std::string partition, DeviceDescriptionsV& devs ) {
00201 
00202   if ( !deviceFactory(__func__) ) { return; }
00203 
00204   if ( partition.empty() ) { 
00205     stringstream ss; 
00206     ss << "[SiStripConfigDb::" << __func__ << "]" 
00207        << " Partition string is empty,"
00208        << " therefore cannot add device descriptions to local cache!"; 
00209     edm::LogWarning(mlConfigDb_) << ss.str(); 
00210     return; 
00211   }
00212   
00213   if ( devs.empty() ) { 
00214     stringstream ss; 
00215     ss << "[SiStripConfigDb::" << __func__ << "]" 
00216        << " Vector of device descriptions is empty,"
00217        << " therefore cannot add device descriptions to local cache!"; 
00218     edm::LogWarning(mlConfigDb_) << ss.str(); 
00219     return; 
00220   }
00221 
00222   SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
00223   SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
00224   for ( ; iter != jter; ++iter ) { if ( partition == iter->second.partitionName() ) { break; } }
00225   if ( iter == dbParams_.partitions().end() ) { 
00226     stringstream ss; 
00227     ss << "[SiStripConfigDb::" << __func__ << "]" 
00228        << " Partition \"" << partition
00229        << "\" not found in partition list, "
00230        << " therefore cannot add device descriptions!";
00231     edm::LogWarning(mlConfigDb_) << ss.str(); 
00232     return; 
00233   }
00234   
00235   DeviceDescriptionsRange range = devices_.find( partition );
00236   if ( range == devices_.emptyRange() ) {
00237     
00238     // Make local copy 
00239     DeviceDescriptionsV tmp;
00240     FecFactory::vectorCopyI( tmp, devs, true );
00241     
00242     // Add to local cache
00243     devices_.loadNext( partition, tmp );
00244 
00245     // Some debug
00246     std::stringstream ss;
00247     ss << "[SiStripConfigDb::" << __func__ << "]"
00248        << " Added " << devs.size() 
00249        << " device descriptions to local cache for partition \""
00250        << partition << "\"."
00251        << " (Cache holds device descriptions for " 
00252        << devices_.size() << " partitions.)";
00253     LogTrace(mlConfigDb_) << ss.str();
00254     
00255   } else {
00256     stringstream ss; 
00257     ss << "[SiStripConfigDb::" << __func__ << "]" 
00258        << " Partition \"" << partition
00259        << "\" already found in local cache, "
00260        << " therefore cannot add device descriptions!";
00261     edm::LogWarning(mlConfigDb_) << ss.str(); 
00262     return; 
00263   }
00264   
00265 }
00266 
00267 // -----------------------------------------------------------------------------
00268 // 
00269 void SiStripConfigDb::uploadDeviceDescriptions( std::string partition ) {
00270 
00271   if ( dbParams_.usingDbCache() ) {
00272     edm::LogWarning(mlConfigDb_)
00273       << "[SiStripConfigDb::" << __func__ << "]" 
00274       << " Using database cache! No uploads allowed!"; 
00275     return;
00276   }
00277   
00278   if ( !deviceFactory(__func__) ) { return; }
00279   
00280   if ( devices_.empty() ) { 
00281     stringstream ss; 
00282     ss << "[SiStripConfigDb::" << __func__ << "]" 
00283        << " Found no cached device descriptions, therefore no upload!"; 
00284     edm::LogWarning(mlConfigDb_) << ss.str(); 
00285     return; 
00286   }
00287   
00288   try { 
00289 
00290     SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
00291     SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
00292     for ( ; iter != jter; ++iter ) {
00293       
00294       if ( partition == "" || partition == iter->second.partitionName() ) {
00295         
00296         DeviceDescriptionsRange range = devices_.find( iter->second.partitionName() );
00297         if ( range != devices_.emptyRange() ) {
00298           
00299           DeviceDescriptionsV devs( range.begin(), range.end() );
00300           
00301           SiStripPartition::Versions fecVersion = iter->second.fecVersion();
00302           deviceFactory(__func__)->setFecDeviceDescriptions( devs,
00303                                                              iter->second.partitionName(),
00304                                                              &(fecVersion.first),
00305                                                              &(fecVersion.second),
00306                                                              true ); // new major version
00307 
00308           // Some debug
00309           std::stringstream ss;
00310           ss << "[SiStripConfigDb::" << __func__ << "]"
00311              << " Uploaded " << devs.size() 
00312              << " device descriptions to database for partition \""
00313              << iter->second.partitionName() << "\".";
00314           LogTrace(mlConfigDb_) << ss.str();
00315           
00316         } else {
00317           stringstream ss; 
00318           ss << "[SiStripConfigDb::" << __func__ << "]" 
00319              << " Vector of device descriptions is empty for partition \"" 
00320              << iter->second.partitionName()
00321              << "\", therefore aborting upload for this partition!";
00322           edm::LogWarning(mlConfigDb_) << ss.str(); 
00323           continue; 
00324         }
00325         
00326       } else {
00327         //        stringstream ss; 
00328         //        ss << "[SiStripConfigDb::" << __func__ << "]" 
00329         //           << " Cannot find partition \"" << partition
00330         //           << "\" in cached partitions list: \""
00331         //           << dbParams_.partitionNames( dbParams_.partitionNames() ) 
00332         //           << "\", therefore aborting upload for this partition!";
00333         //        edm::LogWarning(mlConfigDb_) << ss.str(); 
00334       }
00335       
00336     }
00337     
00338   } catch (...) { handleException( __func__ ); }
00339   
00340   allowCalibUpload_ = true;
00341   
00342 }
00343 
00344 // -----------------------------------------------------------------------------
00345 // 
00346 void SiStripConfigDb::clearDeviceDescriptions( std::string partition ) {
00347   LogTrace(mlConfigDb_) << "[SiStripConfigDb::" << __func__ << "]";
00348   
00349   if ( devices_.empty() ) { 
00350     stringstream ss; 
00351     ss << "[SiStripConfigDb::" << __func__ << "]" 
00352        << " Found no cached device descriptions!"; 
00353     //edm::LogWarning(mlConfigDb_) << ss.str(); 
00354     return; 
00355   }
00356   
00357   // Reproduce temporary cache for "all partitions except specified one" (or clear all if none specified)
00358   DeviceDescriptions temporary_cache;
00359   if ( partition == ""  ) { temporary_cache = DeviceDescriptions(); }
00360   else {
00361     SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
00362     SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
00363     for ( ; iter != jter; ++iter ) {
00364       if ( partition != iter->second.partitionName() ) {
00365         DeviceDescriptionsRange range = devices_.find( iter->second.partitionName() );
00366         if ( range != devices_.emptyRange() ) {
00367           temporary_cache.loadNext( partition, DeviceDescriptionsV( range.begin(), range.end() ) );
00368         } else {
00369           //      stringstream ss; 
00370           //      ss << "[SiStripConfigDb::" << __func__ << "]" 
00371           //         << " Cannot find partition \"" << iter->second.partitionName()
00372           //         << "\" in local cache!";
00373           //      edm::LogWarning(mlConfigDb_) << ss.str(); 
00374         }
00375       }
00376     }
00377   }
00378 
00379   // Delete objects in local cache for specified partition (or all if not specified) 
00380   DeviceDescriptionsRange devs;
00381   if ( partition == "" ) { 
00382     if ( !devices_.empty() ) {
00383       devs = DeviceDescriptionsRange( devices_.find( dbParams_.partitions().begin()->second.partitionName() ).begin(),
00384                                       devices_.find( (--(dbParams_.partitions().end()))->second.partitionName() ).end() );
00385     } else { devs = devices_.emptyRange(); }
00386   } else {
00387     SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
00388     SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
00389     for ( ; iter != jter; ++iter ) { if ( partition == iter->second.partitionName() ) { break; } }
00390     devs = devices_.find( iter->second.partitionName() );
00391   }
00392   
00393   if ( devs != devices_.emptyRange() ) {
00394     DeviceDescriptionsV::const_iterator ifed = devs.begin();
00395     DeviceDescriptionsV::const_iterator jfed = devs.end();
00396     for ( ; ifed != jfed; ++ifed ) { if ( *ifed ) { delete *ifed; } }
00397   } else {
00398     stringstream ss; 
00399     ss << "[SiStripConfigDb::" << __func__ << "]";
00400     if ( partition == "" ) { ss << " Found no device descriptions in local cache!"; }
00401     else { ss << " Found no device descriptions in local cache for partition \"" << partition << "\"!"; }
00402     edm::LogWarning(mlConfigDb_) << ss.str(); 
00403   }
00404   
00405   // Overwrite local cache with temporary cache
00406   devices_ = temporary_cache; 
00407 
00408 }
00409 
00410 // -----------------------------------------------------------------------------
00411 // 
00412 void SiStripConfigDb::printDeviceDescriptions( std::string partition ) {
00413 
00414   std::stringstream ss;
00415   ss << "[SiStripConfigDb::" << __func__ << "]"
00416      << " Contents of DeviceDescriptions container:" << std::endl;
00417   ss << " Number of partitions: " << devices_.size() << std::endl;
00418 
00419   // Loop through partitions
00420   uint16_t cntr = 0;
00421   DeviceDescriptions::const_iterator idev = devices_.begin();
00422   DeviceDescriptions::const_iterator jdev = devices_.end();
00423   for ( ; idev != jdev; ++idev ) {
00424 
00425     cntr++;
00426     if ( partition == "" || partition == idev->first ) {
00427       
00428       ss << "  Partition number : " << cntr << " (out of " << devices_.size() << ")" << std::endl;
00429       ss << "  Partition name   : \"" << idev->first << "\"" << std::endl;
00430       ss << "  Num of devices   : " << idev->second.size() << std::endl;
00431       
00432       // Extract FEC crate, slot, etc
00433       std::map< uint32_t, vector<std::string> > devices;
00434       DeviceDescriptionsV::const_iterator iter = idev->second.begin();
00435       DeviceDescriptionsV::const_iterator jter = idev->second.end();
00436       for ( ; iter != jter; ++iter ) { 
00437         if ( *iter ) { 
00438           DeviceAddress addr = deviceAddress( **iter );
00439           uint32_t key  = SiStripFecKey( addr.fecCrate_, 
00440                                          addr.fecSlot_, 
00441                                          addr.fecRing_, 
00442                                          0, 
00443                                          0, 
00444                                          0, 
00445                                          0 ).key();
00446           std::stringstream data;
00447           data << (*iter)->getDeviceType() 
00448                << "_"
00449                << SiStripFecKey( addr.fecCrate_, 
00450                                  addr.fecSlot_, 
00451                                  addr.fecRing_, 
00452                                  addr.ccuAddr_, 
00453                                  addr.ccuChan_, 
00454                                  addr.lldChan_, 
00455                                  addr.i2cAddr_ ).key();
00456           if ( find( devices[key].begin(), devices[key].end(), data.str() ) == devices[key].end() ) { 
00457             devices[key].push_back( data.str() );
00458           }
00459         }
00460       }
00461       
00462       // Sort contents
00463       std::map< uint32_t, std::vector<std::string> > tmp;
00464       std::map< uint32_t, std::vector<std::string> >::const_iterator ii = devices.begin();
00465       std::map< uint32_t, std::vector<std::string> >::const_iterator jj = devices.end();
00466       for ( ; ii != jj; ++ii ) {
00467         std::vector<std::string> temp = ii->second;
00468         std::sort( temp.begin(), temp.end() );
00469         std::vector<std::string>::const_iterator iii = temp.begin();
00470         std::vector<std::string>::const_iterator jjj = temp.end();
00471         for ( ; iii != jjj; ++iii ) { tmp[ii->first].push_back( *iii ); }
00472       }
00473       devices.clear();
00474       devices = tmp;
00475       
00476       // Print FEC crate, slot, etc...
00477       std::map< uint32_t, std::vector<std::string> >::const_iterator idev = devices.begin();
00478       std::map< uint32_t, std::vector<std::string> >::const_iterator jdev = devices.end();
00479       for ( ; idev != jdev; ++idev ) {
00480         SiStripFecKey key(idev->first);
00481         ss << "  Found " << std::setw(3) << idev->second.size()
00482            << " devices for FEC crate/slot/ring " 
00483            << key.fecCrate() << "/"
00484            << key.fecSlot() << "/"
00485            << key.fecRing();
00486         //<< " (ccu/module/lld/i2c): ";
00487         //      if ( !idev->second.empty() ) { 
00488         //        uint16_t first = idev->second.front();
00489         //        uint16_t last = idev->second.front();
00490         //        std::vector<std::string>::const_iterator chan = idev->second.begin();
00491         //        for ( ; chan != idev->second.end(); chan++ ) { 
00492         //          if ( chan != idev->second.begin() ) {
00493         //            if ( *chan != last+1 ) { 
00494         //              ss << std::setw(2) << first << "->" << std::setw(2) << last << ", ";
00495         //              if ( chan != idev->second.end() ) { first = *(chan+1); }
00496         //            } 
00497         //          }
00498         //          last = *chan;
00499         //        }
00500         //        if ( first != last ) { ss << std::setw(2) << first << "->" << std::setw(2) << last; }
00501         ss << std::endl;
00502       }
00503 
00504     }
00505     
00506   }
00507   
00508   LogTrace(mlConfigDb_) << ss.str();
00509 
00510 }
00511 
00512 // -----------------------------------------------------------------------------
00513 // 
00514 SiStripConfigDb::DeviceAddress SiStripConfigDb::deviceAddress( const deviceDescription& description ) {
00515   
00516   deviceDescription& desc = const_cast<deviceDescription&>(description); 
00517   
00518   DeviceAddress addr;
00519   try {
00520     addr.fecCrate_ = static_cast<uint16_t>( desc.getCrateId() + sistrip::FEC_CRATE_OFFSET ); //@@ temporary offset?
00521     addr.fecSlot_  = static_cast<uint16_t>( desc.getFecSlot() );
00522     addr.fecRing_  = static_cast<uint16_t>( desc.getRingSlot() + sistrip::FEC_RING_OFFSET ); //@@ temporary offset?
00523     addr.ccuAddr_  = static_cast<uint16_t>( desc.getCcuAddress() );
00524     addr.ccuChan_  = static_cast<uint16_t>( desc.getChannel() );
00525     addr.lldChan_  = static_cast<uint16_t>( SiStripFecKey::lldChan( desc.getAddress() ) );
00526     addr.i2cAddr_  = static_cast<uint16_t>( desc.getAddress() );
00527   } catch (...) { handleException( __func__ ); }
00528   
00529   return addr;
00530 }
00531 
00532 // -----------------------------------------------------------------------------
00533 //
00534 string SiStripConfigDb::deviceType( const enumDeviceType& device_type ) const {
00535   if      ( device_type == PLL )         { return "PLL"; }
00536   else if ( device_type == LASERDRIVER ) { return "LLD"; }
00537   else if ( device_type == DOH )         { return "DOH"; }
00538   else if ( device_type == APVMUX )      { return "MUX"; }
00539   else if ( device_type == APV25 )       { return "APV"; }
00540   else if ( device_type == DCU )         { return "DCU"; }
00541   else if ( device_type == GOH )         { return "GOH"; }
00542   else { return "UNKNOWN DEVICE!"; }
00543 }