g++ yourstuff -L$DAQLIB -Wl-rpath=$DAQLIB -llibUSB1 \ `pkg-config libusb-1.0 --libs` `pkg-config libusb-1.0 --cflags`
#include <XXUSBUtil.h> namespace XXUSBUtil { typedef std::pair<std::string, USBDevice*> XXUSBDevice; typedef std::vector<XXUSBDevice> XXUSBDevices; XXUSBDevices enumerateVMUSB(USB& context); XXUSBDevices enumerateCCUSB(USB& context); XXUSBDevices enumerateVendorAndProduct( USB& context, uint16_t vendor, uint16_t product ); int transaction( USBDevice* pDevice, void* writePacket, size_t writeSize, void* readPacket, size_t readMax, int msTimeout = 0 ); void writeActionRegister(USBDevice* pDevice, uint16_t data); void executeList( // VMUSB USBDevice* pDevice, const std::vector<uint32_t>& list, void* pReturnedData, size_t maxRead, size_t& bytesRead, int msTimeout = 0 ); void executeList( // CCUSB USBDevice* pDevice, const std::vector<uint16_t>& list, void* pReturnedData, size_t maxRead, size_t& bytesRead, int msTimeout = 0 ); uint8_t readEndpoint(); uint8_t writeEndpoint(); uint16_t vendorId(); uint16_t VMUSBProductId(); uint16_t CCUSBProductId(); // A few operations are somewhat device dependent: namespace VMUSB { void loadList( USBDevice* pDevice, uint8_t listNum, const std::vector<uint32_t>& list, size_t offset ); } namespace CCUSB { void loadList( USBDevice* pDevice, const std::vector<uint16_t>& list, bool scaler=false ); } }
Since the VMUSB and CCUSB controllers have similarities at the gross level, it's possible to factor opertions common to them into a stet of unbound functions. The XXUSBUtil package does exactly that; putting data types and functions into the XXUSBUtil namespace.
This manpage documents these functions and data types.
Note that all functions and methods are defined inide
the XXUSBUtil namespace so
e.g. the function documented as enumerateVMUSB
is actually nameed XXUSBUtil::enumerateVMUSB
.
XXUSBDevices enumerateVMUSB(USB& context);
Produces a list of VMUSB devices. See DATA TYPES for information about the XXUSBDevices data type. Note that all devices objects returned are dynamically allocated and have not claimed an interface. Unused devices must be deleted. See the first example.
context
is the USB
context within which to locate the devices.
Note that in the XXUSBReadout programs,
the controller objects have methods to return
a singleton instance
pointer to a USB
object.
XXUSBDevices enumerateCCUSB(USB& context);
Same as enumerateVMUSB
but the CCUSB contollers are enumerated.
XXUSBDevices enumerateVendorAndProduct(USB& context, uint16_t vendor, uint16_t product);
This method enumerates devices that match
an arbitraty vendor
and product
id.
Once more context
is the USB context.
int transaction(USBDevice* pDevice, void* writePacket, size_t writeSize, void* readPacket, size_t readMax, int msTimeout = 0);
Many operations on the XXUSB controllers are writes followed by reads. For example, immediate operation execution consists of sending a list of operations to the controller, followed by reading back the data the operations in the list generated.
This operation performs these transactions.
pDevice
, as a USB device
on which the transaction is performed. This is
normally gotten via one of the enumerate
operations above.
writePacket
contains
a pointer to the data to write. The number
of bytes of write data are
writeSize
.
readPacket
points to
a buffer into which the data read back from the
device is stored. It provides readMax
bytes of storage. The actual number of bytes
read is stored in bytesRead
.
msTimeout
is the maximum
number of milliseconds the function blocks
for the read. Note that the default value,
0, means there is no timeout.
The return value is the number of bytes read
if greater than zero. The value
LIBUSB_ERROR_TIMEOUT reports
a timeout, and you must then refer to bytesRead
to determine if a retry is approprate.
Any actual errors are signalled by throwing
a USBException
object.
void writeActionRegister(USBDevice* pDevice, uint16_t data);
Both the CCUSB and VMUSB have one write only register,
called the action register. All other registers
are accessible via immediate list operations.
This register is only accessible via
this function. pDevice
points to the USBDevice
object
that specifies which device we're writing.
data
specifies the data
to write to the action register. Note that the
bits in the action register may have
different meanings between the CC and VM USB
controllers. Refer to their manuals.
void executeList(USBDevice* pDevice, const std::vector<uint32_t>& list, void* pReturnedData, size_t maxRead, size_t& bytesRead, int msTimeout = 0);
Executes an immediate list of VME operations
for a VMUSB. VMUSB list elements are
uint32_t's. pDevice
,
as usual is the device on which the list is to be
executed.
The list is defined by list
which provides the list operations and the size of the
list. pReturnedData
is a pointer to a buffer into which data read by
the list will be read. maxRead
is the number of bytes available in
pReturnedData
.
bytesRead
will be written
with the number of bytes actually read from the
VME bus by the list. msTimeout
is the maximum number of milliseconds to block the
read in the transaction
this operation implies. Note that the default,
0 implies no timeout.
USBException
s are used to signal all errors.
void executeList(USBDevice* pDevice, const std::vector<uint16_t>& list, void* pReturnedData, size_t maxRead, size_t& bytesRead, int msTimeout = 0);
Same as previously, but the list is composed of uint16_t elements as the lists for a CCUSB are. Note that this will work perfectly fine on a VMUSB as long as the list is properly formatted.
See the prior overload of executeList
for a description of its parameters.
uint8_t readEndpoint();
Returns the endpoint number from which data should be read from an XXUSB controller.
uint8_t writeEndpoint();
Returns the endpoint number to which data should be writen for an XXUSB controller.
uint16_t vendorId();
Returns the vendor id assigned to Wiener for usb devices. This number was assigned by the USB-IF organization.
uint16_t VMUSBProductId();
Returns the product id assigned by Wiener/JTEC for the VMUSB USB VME controller.
uint16_t CCUSBProductId();
Returns the product ID assigned by Wiener/JTEC for the CCUSB USB CAMAC controller.
The VMUSB and CCUSB operate in data taking by triggering a list of operations on an appropriate trigger. These lists read data which are then blocked and buffered for maximum throughput. The mechanisms for loading a list for later execution, are different between the CCUSB and VMUSB. The CCUSB supports only two lists, an event list and a scaler list and has dedicaed memory for the two. The trigger for the event list is specified by writing appropriate bits in registers in the CCUSB (refer to the CCUSB manual). The VMUSB, supports 8 lists, numbered 0-7 inclusive. Each list can have an independent trigger, however the capability for periodic triggering makes list 1 especially useful as a scaler read list.
A pair of nested namespaces, support
loadList
methods for the
two conrollers. While the parameter signatures for
the two loadList
functions
are, in theory, sufficient to distinguish them
to the compiler, putting them in specific namespaces makes
unambiguously clear which method should be used when
loading lists for specific ontroller.
void
XXUSBUtil::VMUSB::loadList(USBDevice* pDevice, uint8_t listNum, const std::vector<uint32_t>& list, size_t offset);
Loads a list of operations into a VMUSB stack for triggered
execution in data taking mode.
pDevice
is the device object
connected to the VMUSB.
listNum
is the number
of the list to load [0-7].
list
is the list of operations. The CVMUSBReadoutList
can be used to create this list.
offset
is a value
that indicates where in list memory the list
should be loaded. The offset to use depends on
the sizes of the lists prior to the given list.
Each list requires
(list.size()
+ 2)*sizeof(uint32_t)/sizeof(uint16_t))
'words' of stack space. That is the number of 16bit words required
for the list and a two long word header inserted
by the firmware.
void XXUSBUtil::CCUSB::loadList(USBDevice* pDevice, const std::vector<uint16_t>& list, bool scaler = false);
Loads a CCUSB readout list. pDevice
is the device that's open on the device. list
is the list to load and scaler
is a flag that, if true, indicates that the
list should be loaded as a scaler list.
The XXUSBUtil namespace exports two data types:
This type is an
std::pair<std::string, USBDevice*>.
The first element of the pair is the serial number
of a USB device and the second elemet a pointer to
a dynamically allocated USBDevice
that's open on that device.
Just a vector of XXUSBDevice. This type is returned from the enumertion methods.
Enumerating and selecting a VMUSB by serial number.
Note that the process is the same for a CCUSB, thought
enumerateCCUSB
must be used
below instead of enumerateVMUSB
.
#include <XXUSBUtil.h> #include <USBDevice.h> #include <string> USBDevice* findVMUSB(const std::stringamp; serial, USB* pContext) { auto devices = XXUSBUtil::enumerateVMUSB(*pContext); USBDevice* pResult for (int i=0; i < devices.size(); i++) { if (serial == devices[i].first) { pResult = devices[i].second; } else { delete devices[i].second; } } if (!pResult) { throw std::string("No matching VMUSB in findVMUSB"); } return pResult; }
In the context of the CCUSB program, here's how to load a CCUSB list into a CCUSB controller.
#include <CCUSBReaoutList.h> #include <XXUSBUtil.h> #include <USBDevice.h> /// code fragment to load a CCUSB event readout list: USB usb; CCCUSBReadoutList eventList; USBDevice* pCCUSB = findDevice(usb); //... do stuff needed to stuff the eventList /... XXUSBUtil::CCUSB::loadList(pDevice, eventList.get(), false); ....