CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/OnlineDB/SiStripConfigDb/src/DeviceDescriptions.cc

Go to the documentation of this file.
00001 // Last commit: $Id: DeviceDescriptions.cc,v 1.36 2009/04/06 16:57:28 lowette 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           deviceFactory(__func__)->setFecDeviceDescriptions( devs,
00302                                                              iter->second.partitionName(),
00303                                                              &(iter->second.fecVersion().first),
00304                                                              &(iter->second.fecVersion().second),
00305                                                              true ); // new major version
00306 
00307           // Some debug
00308           std::stringstream ss;
00309           ss << "[SiStripConfigDb::" << __func__ << "]"
00310              << " Uploaded " << devs.size() 
00311              << " device descriptions to database for partition \""
00312              << iter->second.partitionName() << "\".";
00313           LogTrace(mlConfigDb_) << ss.str();
00314           
00315         } else {
00316           stringstream ss; 
00317           ss << "[SiStripConfigDb::" << __func__ << "]" 
00318              << " Vector of device descriptions is empty for partition \"" 
00319              << iter->second.partitionName()
00320              << "\", therefore aborting upload for this partition!";
00321           edm::LogWarning(mlConfigDb_) << ss.str(); 
00322           continue; 
00323         }
00324         
00325       } else {
00326         //        stringstream ss; 
00327         //        ss << "[SiStripConfigDb::" << __func__ << "]" 
00328         //           << " Cannot find partition \"" << partition
00329         //           << "\" in cached partitions list: \""
00330         //           << dbParams_.partitionNames( dbParams_.partitionNames() ) 
00331         //           << "\", therefore aborting upload for this partition!";
00332         //        edm::LogWarning(mlConfigDb_) << ss.str(); 
00333       }
00334       
00335     }
00336     
00337   } catch (...) { handleException( __func__ ); }
00338   
00339   allowCalibUpload_ = true;
00340   
00341 }
00342 
00343 // -----------------------------------------------------------------------------
00344 // 
00345 void SiStripConfigDb::clearDeviceDescriptions( std::string partition ) {
00346   LogTrace(mlConfigDb_) << "[SiStripConfigDb::" << __func__ << "]";
00347   
00348   if ( devices_.empty() ) { 
00349     stringstream ss; 
00350     ss << "[SiStripConfigDb::" << __func__ << "]" 
00351        << " Found no cached device descriptions!"; 
00352     //edm::LogWarning(mlConfigDb_) << ss.str(); 
00353     return; 
00354   }
00355   
00356   // Reproduce temporary cache for "all partitions except specified one" (or clear all if none specified)
00357   DeviceDescriptions temporary_cache;
00358   if ( partition == ""  ) { temporary_cache = DeviceDescriptions(); }
00359   else {
00360     SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
00361     SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
00362     for ( ; iter != jter; ++iter ) {
00363       if ( partition != iter->second.partitionName() ) {
00364         DeviceDescriptionsRange range = devices_.find( iter->second.partitionName() );
00365         if ( range != devices_.emptyRange() ) {
00366           temporary_cache.loadNext( partition, DeviceDescriptionsV( range.begin(), range.end() ) );
00367         } else {
00368           //      stringstream ss; 
00369           //      ss << "[SiStripConfigDb::" << __func__ << "]" 
00370           //         << " Cannot find partition \"" << iter->second.partitionName()
00371           //         << "\" in local cache!";
00372           //      edm::LogWarning(mlConfigDb_) << ss.str(); 
00373         }
00374       }
00375     }
00376   }
00377 
00378   // Delete objects in local cache for specified partition (or all if not specified) 
00379   DeviceDescriptionsRange devs;
00380   if ( partition == "" ) { 
00381     if ( !devices_.empty() ) {
00382       devs = DeviceDescriptionsRange( devices_.find( dbParams_.partitions().begin()->second.partitionName() ).begin(),
00383                                       devices_.find( (--(dbParams_.partitions().end()))->second.partitionName() ).end() );
00384     } else { devs = devices_.emptyRange(); }
00385   } else {
00386     SiStripDbParams::SiStripPartitions::const_iterator iter = dbParams_.partitions().begin();
00387     SiStripDbParams::SiStripPartitions::const_iterator jter = dbParams_.partitions().end();
00388     for ( ; iter != jter; ++iter ) { if ( partition == iter->second.partitionName() ) { break; } }
00389     devs = devices_.find( iter->second.partitionName() );
00390   }
00391   
00392   if ( devs != devices_.emptyRange() ) {
00393     DeviceDescriptionsV::const_iterator ifed = devs.begin();
00394     DeviceDescriptionsV::const_iterator jfed = devs.end();
00395     for ( ; ifed != jfed; ++ifed ) { if ( *ifed ) { delete *ifed; } }
00396   } else {
00397     stringstream ss; 
00398     ss << "[SiStripConfigDb::" << __func__ << "]";
00399     if ( partition == "" ) { ss << " Found no device descriptions in local cache!"; }
00400     else { ss << " Found no device descriptions in local cache for partition \"" << partition << "\"!"; }
00401     edm::LogWarning(mlConfigDb_) << ss.str(); 
00402   }
00403   
00404   // Overwrite local cache with temporary cache
00405   devices_ = temporary_cache; 
00406 
00407 }
00408 
00409 // -----------------------------------------------------------------------------
00410 // 
00411 void SiStripConfigDb::printDeviceDescriptions( std::string partition ) {
00412 
00413   std::stringstream ss;
00414   ss << "[SiStripConfigDb::" << __func__ << "]"
00415      << " Contents of DeviceDescriptions container:" << std::endl;
00416   ss << " Number of partitions: " << devices_.size() << std::endl;
00417 
00418   // Loop through partitions
00419   uint16_t cntr = 0;
00420   DeviceDescriptions::const_iterator idev = devices_.begin();
00421   DeviceDescriptions::const_iterator jdev = devices_.end();
00422   for ( ; idev != jdev; ++idev ) {
00423 
00424     cntr++;
00425     if ( partition == "" || partition == idev->first ) {
00426       
00427       ss << "  Partition number : " << cntr << " (out of " << devices_.size() << ")" << std::endl;
00428       ss << "  Partition name   : \"" << idev->first << "\"" << std::endl;
00429       ss << "  Num of devices   : " << idev->second.size() << std::endl;
00430       
00431       // Extract FEC crate, slot, etc
00432       std::map< uint32_t, vector<std::string> > devices;
00433       DeviceDescriptionsV::const_iterator iter = idev->second.begin();
00434       DeviceDescriptionsV::const_iterator jter = idev->second.end();
00435       for ( ; iter != jter; ++iter ) { 
00436         if ( *iter ) { 
00437           DeviceAddress addr = deviceAddress( **iter );
00438           uint32_t key  = SiStripFecKey( addr.fecCrate_, 
00439                                          addr.fecSlot_, 
00440                                          addr.fecRing_, 
00441                                          0, 
00442                                          0, 
00443                                          0, 
00444                                          0 ).key();
00445           std::stringstream data;
00446           data << (*iter)->getDeviceType() 
00447                << "_"
00448                << SiStripFecKey( addr.fecCrate_, 
00449                                  addr.fecSlot_, 
00450                                  addr.fecRing_, 
00451                                  addr.ccuAddr_, 
00452                                  addr.ccuChan_, 
00453                                  addr.lldChan_, 
00454                                  addr.i2cAddr_ ).key();
00455           if ( find( devices[key].begin(), devices[key].end(), data.str() ) == devices[key].end() ) { 
00456             devices[key].push_back( data.str() );
00457           }
00458         }
00459       }
00460       
00461       // Sort contents
00462       std::map< uint32_t, std::vector<std::string> > tmp;
00463       std::map< uint32_t, std::vector<std::string> >::const_iterator ii = devices.begin();
00464       std::map< uint32_t, std::vector<std::string> >::const_iterator jj = devices.end();
00465       for ( ; ii != jj; ++ii ) {
00466         std::vector<std::string> temp = ii->second;
00467         std::sort( temp.begin(), temp.end() );
00468         std::vector<std::string>::const_iterator iii = temp.begin();
00469         std::vector<std::string>::const_iterator jjj = temp.end();
00470         for ( ; iii != jjj; ++iii ) { tmp[ii->first].push_back( *iii ); }
00471       }
00472       devices.clear();
00473       devices = tmp;
00474       
00475       // Print FEC crate, slot, etc...
00476       std::map< uint32_t, std::vector<std::string> >::const_iterator idev = devices.begin();
00477       std::map< uint32_t, std::vector<std::string> >::const_iterator jdev = devices.end();
00478       for ( ; idev != jdev; ++idev ) {
00479         SiStripFecKey key(idev->first);
00480         ss << "  Found " << std::setw(3) << idev->second.size()
00481            << " devices for FEC crate/slot/ring " 
00482            << key.fecCrate() << "/"
00483            << key.fecSlot() << "/"
00484            << key.fecRing();
00485         //<< " (ccu/module/lld/i2c): ";
00486         //      if ( !idev->second.empty() ) { 
00487         //        uint16_t first = idev->second.front();
00488         //        uint16_t last = idev->second.front();
00489         //        std::vector<std::string>::const_iterator chan = idev->second.begin();
00490         //        for ( ; chan != idev->second.end(); chan++ ) { 
00491         //          if ( chan != idev->second.begin() ) {
00492         //            if ( *chan != last+1 ) { 
00493         //              ss << std::setw(2) << first << "->" << std::setw(2) << last << ", ";
00494         //              if ( chan != idev->second.end() ) { first = *(chan+1); }
00495         //            } 
00496         //          }
00497         //          last = *chan;
00498         //        }
00499         //        if ( first != last ) { ss << std::setw(2) << first << "->" << std::setw(2) << last; }
00500         ss << std::endl;
00501       }
00502 
00503     }
00504     
00505   }
00506   
00507   LogTrace(mlConfigDb_) << ss.str();
00508 
00509 }
00510 
00511 // -----------------------------------------------------------------------------
00512 // 
00513 SiStripConfigDb::DeviceAddress SiStripConfigDb::deviceAddress( const deviceDescription& description ) {
00514   
00515   deviceDescription& desc = const_cast<deviceDescription&>(description); 
00516   
00517   DeviceAddress addr;
00518   try {
00519     addr.fecCrate_ = static_cast<uint16_t>( desc.getCrateId() + sistrip::FEC_CRATE_OFFSET ); //@@ temporary offset?
00520     addr.fecSlot_  = static_cast<uint16_t>( desc.getFecSlot() );
00521     addr.fecRing_  = static_cast<uint16_t>( desc.getRingSlot() + sistrip::FEC_RING_OFFSET ); //@@ temporary offset?
00522     addr.ccuAddr_  = static_cast<uint16_t>( desc.getCcuAddress() );
00523     addr.ccuChan_  = static_cast<uint16_t>( desc.getChannel() );
00524     addr.lldChan_  = static_cast<uint16_t>( SiStripFecKey::lldChan( desc.getAddress() ) );
00525     addr.i2cAddr_  = static_cast<uint16_t>( desc.getAddress() );
00526   } catch (...) { handleException( __func__ ); }
00527   
00528   return addr;
00529 }
00530 
00531 // -----------------------------------------------------------------------------
00532 //
00533 string SiStripConfigDb::deviceType( const enumDeviceType& device_type ) const {
00534   if      ( device_type == PLL )         { return "PLL"; }
00535   else if ( device_type == LASERDRIVER ) { return "LLD"; }
00536   else if ( device_type == DOH )         { return "DOH"; }
00537   else if ( device_type == APVMUX )      { return "MUX"; }
00538   else if ( device_type == APV25 )       { return "APV"; }
00539   else if ( device_type == DCU )         { return "DCU"; }
00540   else if ( device_type == GOH )         { return "GOH"; }
00541   else { return "UNKNOWN DEVICE!"; }
00542 }