LCOV - code coverage report
Current view: top level - sspmodules/src/anlBoard - EthernetDevice.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 184 0
Test Date: 2025-12-21 13:07:08 Functions: 0.0 % 19 0

            Line data    Source code
       1              : /**
       2              :  * @file EthernetDevice.cxx
       3              :  *
       4              :  * This is part of the DUNE DAQ , copyright 2020.
       5              :  * Licensing/copyright details are in the COPYING file that you should have
       6              :  * received with this code.
       7              :  */
       8              : #ifndef SSPMODULES_SRC_ANLBOARD_ETHERNETDEVICE_CXX_
       9              : #define SSPMODULES_SRC_ANLBOARD_ETHERNETDEVICE_CXX_
      10              : 
      11              : #include "EthernetDevice.hpp"
      12              : 
      13              : #include "anlExceptions.hpp"
      14              : 
      15              : #include <algorithm>
      16              : #include <cstdlib>
      17              : #include <vector>
      18              : 
      19              : boost::asio::io_service dunedaq::sspmodules::EthernetDevice::fIo_service;
      20              : 
      21            0 : dunedaq::sspmodules::EthernetDevice::EthernetDevice(unsigned long ipAddress)  // NOLINT
      22              :   :
      23            0 :   isOpen(false)
      24            0 :   , fCommSocket(fIo_service)
      25            0 :   , fDataSocket(fIo_service)
      26            0 :   , fIP(boost::asio::ip::address_v4(ipAddress))
      27            0 : {}
      28              : 
      29              : void
      30            0 : dunedaq::sspmodules::EthernetDevice::Open(bool slowControlOnly)
      31              : {
      32              : 
      33            0 :   fSlowControlOnly = slowControlOnly;
      34              : 
      35              :   // dune::DAQLogger::LogInfo("SSP_EthernetDevice")<<"Looking for SSP Ethernet device at "<<fIP.to_string()<<std::endl;
      36            0 :   boost::asio::ip::tcp::resolver resolver(fIo_service);
      37            0 :   boost::asio::ip::tcp::resolver::query commQuery(fIP.to_string(), slowControlOnly ? "55002" : "55001");
      38            0 :   boost::asio::ip::tcp::resolver::iterator commEndpointIterator = resolver.resolve(commQuery);
      39            0 :   boost::asio::connect(fCommSocket, commEndpointIterator);
      40              : 
      41            0 :   if (slowControlOnly) {
      42              :     // dune::DAQLogger::LogInfo("SSP_EthernetDevice")<<"Connected to SSP Ethernet device at
      43              :     // "<<fIP.to_string()<<std::endl;
      44            0 :     return;
      45              :   }
      46              : 
      47            0 :   boost::asio::ip::tcp::resolver::query dataQuery(fIP.to_string(), "55010");
      48            0 :   boost::asio::ip::tcp::resolver::iterator dataEndpointIterator = resolver.resolve(dataQuery);
      49              : 
      50            0 :   boost::asio::connect(fDataSocket, dataEndpointIterator);
      51              : 
      52              :   // Set limited receive buffer size to avoid taxing switch
      53              :   // JTH: Remove this since it was causing event read errors. Could try again
      54              :   // with a different value if there are more issues which point to switch problems.
      55              :   //  boost::asio::socket_base::receive_buffer_size option(16384);
      56              :   //  fDataSocket.set_option(option);
      57              : 
      58              :   // dune::DAQLogger::LogInfo("SSP_EthernetDevice")<<"Connected to SSP Ethernet device at "<<fIP.to_string()<<std::endl;
      59            0 : }
      60              : 
      61              : void
      62            0 : dunedaq::sspmodules::EthernetDevice::Close()
      63              : {
      64            0 :   isOpen = false;
      65              :   // dune::DAQLogger::LogInfo("SSP_EthernetDevice")<<"Device closed"<<std::endl;
      66            0 : }
      67              : 
      68              : void
      69            0 : dunedaq::sspmodules::EthernetDevice::DevicePurgeComm(void)
      70              : {
      71            0 :   DevicePurge(fCommSocket);
      72            0 : }
      73              : 
      74              : void
      75            0 : dunedaq::sspmodules::EthernetDevice::DevicePurgeData(void)
      76              : {
      77            0 :   DevicePurge(fDataSocket);
      78            0 : }
      79              : 
      80              : void
      81            0 : dunedaq::sspmodules::EthernetDevice::DeviceQueueStatus(unsigned int* numWords)
      82              : {
      83            0 :   unsigned int numBytes = fDataSocket.available();
      84            0 :   (*numWords) = numBytes / sizeof(unsigned int);
      85            0 : }
      86              : 
      87              : void
      88            0 : dunedaq::sspmodules::EthernetDevice::DeviceReceive(std::vector<unsigned int>& data, unsigned int size)
      89              : {
      90            0 :   data.resize(size);
      91            0 :   unsigned int dataReturned = fDataSocket.read_some(boost::asio::buffer(data));
      92            0 :   if (dataReturned < size * sizeof(unsigned int)) {
      93            0 :     data.resize(dataReturned / sizeof(unsigned int));
      94              :   }
      95            0 : }
      96              : 
      97              : //==============================================================================
      98              : // Command Functions
      99              : //==============================================================================
     100              : 
     101              : void
     102            0 : dunedaq::sspmodules::EthernetDevice::DeviceRead(unsigned int address, unsigned int* value)
     103              : {
     104            0 :   dunedaq::sspmodules::CtrlPacket tx;
     105            0 :   dunedaq::sspmodules::CtrlPacket rx;
     106            0 :   unsigned int txSize;
     107            0 :   unsigned int rxSizeExpected;
     108              : 
     109            0 :   tx.header.length = sizeof(dunedaq::sspmodules::CtrlHeader);
     110            0 :   tx.header.address = address;
     111            0 :   tx.header.command = dunedaq::sspmodules::cmdRead;
     112            0 :   tx.header.size = 1;
     113            0 :   tx.header.status = dunedaq::sspmodules::statusNoError;
     114            0 :   txSize = sizeof(dunedaq::sspmodules::CtrlHeader);
     115            0 :   rxSizeExpected = sizeof(dunedaq::sspmodules::CtrlHeader) + sizeof(unsigned int);
     116              : 
     117            0 :   SendReceive(tx, rx, txSize, rxSizeExpected, 3);
     118            0 :   *value = rx.data[0];
     119            0 : }
     120              : 
     121              : void
     122            0 : dunedaq::sspmodules::EthernetDevice::DeviceReadMask(unsigned int address, unsigned int mask, unsigned int* value)
     123              : {
     124            0 :   dunedaq::sspmodules::CtrlPacket tx;
     125            0 :   dunedaq::sspmodules::CtrlPacket rx;
     126            0 :   unsigned int txSize;
     127            0 :   unsigned int rxSizeExpected;
     128              : 
     129            0 :   tx.header.length = sizeof(dunedaq::sspmodules::CtrlHeader) + sizeof(uint);
     130            0 :   tx.header.address = address;
     131            0 :   tx.header.command = dunedaq::sspmodules::cmdReadMask;
     132            0 :   tx.header.size = 1;
     133            0 :   tx.header.status = dunedaq::sspmodules::statusNoError;
     134            0 :   tx.data[0] = mask;
     135            0 :   txSize = sizeof(dunedaq::sspmodules::CtrlHeader) + sizeof(unsigned int);
     136            0 :   rxSizeExpected = sizeof(dunedaq::sspmodules::CtrlHeader) + sizeof(unsigned int);
     137              : 
     138            0 :   SendReceive(tx, rx, txSize, rxSizeExpected, 3);
     139            0 :   *value = rx.data[0];
     140            0 : }
     141              : 
     142              : void
     143            0 : dunedaq::sspmodules::EthernetDevice::DeviceWrite(unsigned int address, unsigned int value)
     144              : {
     145            0 :   dunedaq::sspmodules::CtrlPacket tx;
     146            0 :   dunedaq::sspmodules::CtrlPacket rx;
     147            0 :   unsigned int txSize;
     148            0 :   unsigned int rxSizeExpected;
     149              : 
     150            0 :   tx.header.length = sizeof(dunedaq::sspmodules::CtrlHeader) + sizeof(uint);
     151            0 :   tx.header.address = address;
     152            0 :   tx.header.command = dunedaq::sspmodules::cmdWrite;
     153            0 :   tx.header.size = 1;
     154            0 :   tx.header.status = dunedaq::sspmodules::statusNoError;
     155            0 :   tx.data[0] = value;
     156            0 :   txSize = sizeof(dunedaq::sspmodules::CtrlHeader) + sizeof(unsigned int);
     157            0 :   rxSizeExpected = sizeof(dunedaq::sspmodules::CtrlHeader);
     158              : 
     159            0 :   SendReceive(tx, rx, txSize, rxSizeExpected, 3);
     160            0 : }
     161              : 
     162              : void
     163            0 : dunedaq::sspmodules::EthernetDevice::DeviceWriteMask(unsigned int address, unsigned int mask, unsigned int value)
     164              : {
     165            0 :   dunedaq::sspmodules::CtrlPacket tx;
     166            0 :   dunedaq::sspmodules::CtrlPacket rx;
     167            0 :   unsigned int txSize;
     168            0 :   unsigned int rxSizeExpected;
     169              : 
     170            0 :   tx.header.length = sizeof(dunedaq::sspmodules::CtrlHeader) + (sizeof(uint) * 2);
     171            0 :   tx.header.address = address;
     172            0 :   tx.header.command = dunedaq::sspmodules::cmdWriteMask;
     173            0 :   tx.header.size = 1;
     174            0 :   tx.header.status = dunedaq::sspmodules::statusNoError;
     175            0 :   tx.data[0] = mask;
     176            0 :   tx.data[1] = value;
     177            0 :   txSize = sizeof(dunedaq::sspmodules::CtrlHeader) + (sizeof(unsigned int) * 2);
     178            0 :   rxSizeExpected = sizeof(dunedaq::sspmodules::CtrlHeader) + sizeof(unsigned int);
     179              : 
     180            0 :   SendReceive(tx, rx, txSize, rxSizeExpected, 3);
     181            0 : }
     182              : 
     183              : void
     184            0 : dunedaq::sspmodules::EthernetDevice::DeviceSet(unsigned int address, unsigned int mask)
     185              : {
     186            0 :   DeviceWriteMask(address, mask, 0xFFFFFFFF);
     187            0 : }
     188              : 
     189              : void
     190            0 : dunedaq::sspmodules::EthernetDevice::DeviceClear(unsigned int address, unsigned int mask)
     191              : {
     192            0 :   DeviceWriteMask(address, mask, 0x00000000);
     193            0 : }
     194              : 
     195              : void
     196            0 : dunedaq::sspmodules::EthernetDevice::DeviceArrayRead(unsigned int address, unsigned int size, unsigned int* data)
     197              : {
     198            0 :   unsigned int i = 0;
     199            0 :   dunedaq::sspmodules::CtrlPacket tx;
     200            0 :   dunedaq::sspmodules::CtrlPacket rx;
     201            0 :   unsigned int txSize;
     202            0 :   unsigned int rxSizeExpected;
     203              : 
     204            0 :   tx.header.length = sizeof(dunedaq::sspmodules::CtrlHeader);
     205            0 :   tx.header.address = address;
     206            0 :   tx.header.command = dunedaq::sspmodules::cmdArrayRead;
     207            0 :   tx.header.size = size;
     208            0 :   tx.header.status = dunedaq::sspmodules::statusNoError;
     209            0 :   txSize = sizeof(dunedaq::sspmodules::CtrlHeader);
     210            0 :   rxSizeExpected = sizeof(dunedaq::sspmodules::CtrlHeader) + (sizeof(unsigned int) * size);
     211              : 
     212            0 :   SendReceive(tx, rx, txSize, rxSizeExpected, 3);
     213            0 :   for (i = 0; i < rx.header.size; i++) {
     214            0 :     data[i] = rx.data[i];
     215              :   }
     216            0 : }
     217              : 
     218              : void
     219            0 : dunedaq::sspmodules::EthernetDevice::DeviceArrayWrite(unsigned int address, unsigned int size, unsigned int* data)
     220              : {
     221            0 :   unsigned int i = 0;
     222            0 :   dunedaq::sspmodules::CtrlPacket tx;
     223            0 :   dunedaq::sspmodules::CtrlPacket rx;
     224            0 :   unsigned int txSize;
     225            0 :   unsigned int rxSizeExpected;
     226              : 
     227            0 :   tx.header.length = sizeof(dunedaq::sspmodules::CtrlHeader) + (sizeof(uint) * size);
     228            0 :   tx.header.address = address;
     229            0 :   tx.header.command = dunedaq::sspmodules::cmdArrayWrite;
     230            0 :   tx.header.size = size;
     231            0 :   tx.header.status = dunedaq::sspmodules::statusNoError;
     232            0 :   txSize = sizeof(dunedaq::sspmodules::CtrlHeader) + (sizeof(unsigned int) * size);
     233            0 :   rxSizeExpected = sizeof(dunedaq::sspmodules::CtrlHeader);
     234              : 
     235            0 :   for (i = 0; i < size; i++) {
     236            0 :     tx.data[i] = data[i];
     237              :   }
     238              : 
     239            0 :   SendReceive(tx, rx, txSize, rxSizeExpected, 3);
     240            0 : }
     241              : 
     242              : //==============================================================================
     243              : // Support Functions
     244              : //==============================================================================
     245              : 
     246              : void
     247            0 : dunedaq::sspmodules::EthernetDevice::SendReceive(dunedaq::sspmodules::CtrlPacket& tx,
     248              :                                                  dunedaq::sspmodules::CtrlPacket& rx,
     249              :                                                  unsigned int txSize,
     250              :                                                  unsigned int rxSizeExpected,
     251              :                                                  unsigned int retryCount)
     252              : {
     253            0 :   unsigned int timesTried = 0;
     254            0 :   bool success = false;
     255              : 
     256            0 :   while (!success) {
     257            0 :     try {
     258            0 :       SendEthernet(tx, txSize);
     259              :       // Insert small delay between send and receive on Linux
     260            0 :       usleep(100);
     261            0 :       ReceiveEthernet(rx, rxSizeExpected);
     262            0 :       usleep(2000);
     263              :       success = true;
     264            0 :     } catch (ETCPError&) {
     265            0 :       if (timesTried < retryCount) {
     266            0 :         DevicePurgeComm();
     267            0 :         ++timesTried;
     268              :         // dune::DAQLogger::LogWarning("SSP_EthernetDevice")<<"Send/receive failed "<<timesTried<<" times on Ethernet
     269              :         // link, retrying..."<<std::endl;
     270              :       } else {
     271              :         // dune::DAQLogger::LogError("SSP_EthernetDevice")<<"Send/receive failed on Ethernet link, giving
     272              :         // up."<<std::endl;
     273            0 :         throw;
     274              :       }
     275            0 :     }
     276              :   }
     277            0 : }
     278              : 
     279              : void
     280            0 : dunedaq::sspmodules::EthernetDevice::SendEthernet(dunedaq::sspmodules::CtrlPacket& tx, unsigned int txSize)
     281              : {
     282            0 :   unsigned int txSizeWritten = fCommSocket.write_some(boost::asio::buffer(static_cast<void*>(&tx), txSize));
     283            0 :   if (txSizeWritten != txSize) {
     284            0 :     throw(ETCPError(""));
     285              :   }
     286            0 : }
     287              : 
     288              : void
     289            0 : dunedaq::sspmodules::EthernetDevice::ReceiveEthernet(dunedaq::sspmodules::CtrlPacket& rx, unsigned int rxSizeExpected)
     290              : {
     291            0 :   unsigned int rxSizeReturned = fCommSocket.read_some(boost::asio::buffer(static_cast<void*>(&rx), rxSizeExpected));
     292            0 :   if (rxSizeReturned != rxSizeExpected) {
     293            0 :     throw(ETCPError(""));
     294              :   }
     295            0 : }
     296              : 
     297              : void
     298            0 : dunedaq::sspmodules::EthernetDevice::DevicePurge(boost::asio::ip::tcp::socket& socket)
     299              : {
     300            0 :   bool done = false;
     301            0 :   unsigned int bytesQueued = 0;
     302            0 :   unsigned int sleepTime = 0;
     303              : 
     304              :   // Keep getting data from channel until queue is empty
     305            0 :   do {
     306            0 :     bytesQueued = socket.available();
     307              : 
     308              :     // Read data from device, up to 256 bytes
     309            0 :     if (bytesQueued != 0) {
     310            0 :       sleepTime = 0;
     311            0 :       unsigned int bytesToGet = std::min((unsigned int)256, bytesQueued);
     312            0 :       std::vector<char> junkBuf(bytesToGet);
     313            0 :       socket.read_some(boost::asio::buffer(junkBuf, bytesToGet));
     314            0 :     } else {      // If queue is empty, wait a bit and check that it hasn't filled up again, then return
     315            0 :       usleep(1000); // 1ms
     316            0 :       sleepTime += 1000;
     317            0 :       bytesQueued = socket.available();
     318            0 :       if (bytesQueued == 0 && sleepTime > 1000000) {
     319            0 :         done = 1;
     320              :       }
     321              :     }
     322            0 :   } while (!done);
     323            0 : }
     324              : 
     325              : #endif // SSPMODULES_SRC_ANLBOARD_ETHERNETDEVICE_CXX_
        

Generated by: LCOV version 2.0-1