USBDeviceInfo

Name

USBDeviceInfo -- Provide information about a USB device.

Synopsis


         g++ yourstuff -L$DAQLIB -Wl-rpath=$DAQLIB -llibUSB1 \
   `pkg-config libusb-1.0 --libs` `pkg-config libusb-1.0 --cflags`         
      

#include <USBDeviceInfo.h>
class USBDeviceInfo
{
public:
    USBDeviceInfo();
    USBDeviceInfo(libusb_device* pDevice);
    USBDeviceInfo(const USBDeviceInfo& rhs);
    virtual ~USBDeviceInfo();
    USBDeviceInfo& operator=(const USBDeviceInfo& rhs);
    libusb_device* getHandle() { return m_pDevice; }
    uint8_t getBus();
    uint8_t getPort();
    uint16_t getVendor();
    uint16_t getProduct();
    USBDevice* open();
    
};
      

DESCRIPTION

Provides information about a device that does not require opening a connection to the device to obtain. This information includes the location of the device in the USB subsystem as well as information about the device itself.

Finally, the open method provides a USBDevice which can then be used to interact with the device itself.

The libusb-1.0 implementation just provides a wrapper for an instance of a libusb_device*. libusb-1.0 manages these structs using reference counting. Destruction of a USBDeviceInfo object decrements the reference count. Copy construction and assignment are implemented using the device reference count so that the destruction of the last object referencing libusb_device will cause libusb-1.0 to destroy the struct.

METHODS

USBDeviceInfo();

This constructor does not create a functioning object as it does not encapsulate a device object. Use this constructor prior to assigning from an existing object that has been well constructed.

See the examples for more.

USBDeviceInfo(libusb_device* pDevice);

Constructs this object from a USB device object from the underlying libusb-1.0 library. Normally you won't actually directly create an object like this either but you'll obtain an object from the enumerate method of the USB class.

See Examples for more.

USBDeviceInfo(const USBDeviceInfo& rhs);

Copy construction is supported. The underlying object's reference count is incremented.

USBDeviceInfo& operator(const USBDeviceInfo& rhs);

Assignment operator. If the left hand side of the operation is not the same as the right, the encapsulated object on the left hand side is dereferenced (reference count decremented) and the object on the rhs referenced (referenc cont incremented).

The method returns a reference to the lhs after the assignment is complete to support operation chaining.

libusb_device* getHandle();

Returns the libusb-1.0 libusb_device* this object encapsulates. If you have to do this you should aks the operations you need to perform be added to this class. If you intend to hold on to the pointer longer than the lifetime of the USBDeviceInfo object from which it came you should increment the reference count.

See the examples for more information.

uint8_t getBus();

Returns the number of the USB bus to which this device is connected. This is one part of the physical location of the device in the USB's subsystem.

uint8_t getPort();

Returns the port on the USB bus to which the device is connected. Each USB bus controller (what you get from getBus). can have up to 255 attached devices. The devices are attached to numbered ports. This method returns a device's port number.

uint16_t getVendor();

Returns the device's vendor id. Each USB device vendor is assigned a vendor identification number. Their devices identify to the system using that number. This method returns that vendor Id for the devices.

uint16_t getProduct();

Returns the device's product id. The product id is a number assigned to identify device models produced by a USB vendor. For example, if a vendor produces keyboards and mice, their mouse will have a distinct product id from the keyboard so that software can tell the difference.

USBDevice* open();

Opens the device for use returning a pointer to a dynamically allocated USBDevice object. Further operations on the device are performed through this object. Destroying the USBDevice returned by this method will also close access to the device.

The USBDevice object returned by this method provides an implicit reference to the device information object wrapped by this class. It is therefore safe to destroy the object on whic you called open immediately if it's no longer needed.

EXAMPLES

The first example shows how and when to use the default constructor. In the example below, the function selectDevice choses the 'correct' USB device from amongst the ones connected to the system, and is assumed to be implemented somewhere else in the application.


#include <USB.h>
#include <USBDevice.h>
#include <stdlib.h>
#include <iostream>
#include <stdexcept>
...

try {
   USB usb;
   auto devices = usb.enumerate();
   USBDeviceInfo* pDevice = selectDevice(devices);
   USBDeviceInfo u;
   u = *pDevice;
   
   // Do more stuff.
   ...
   
}
catch (std::exception& e) {
   std::cerr << "Some error occured: "  <<  e.what()
       <<  std::endl;
   exit(EXIT_FAILURE);
}
         

In this case, the default constructor is used to "turn" the USBDeviceInfo pointer into an object. This could just as easily be done with copy construction or construction on the return value of getHandle.

Using enumerate to get a USBDeviceInfo object. Normally, our USB programs need to operate on a specific USB device. The first cut for determining the device is usually a match on the vendor and product id of the devices in question. Throughout our examples, we have been doing this selection inside a function named selectDevice. This example shows one possible implementation of this function. Note that XXUSBUtil contains enumeration methods that make it unecessar to code your own selectDevice for XXUSB controllers.

Our example will locate and return the last VMUSB device it finds and throw an exception if none are found.


#include <stdint.h>
#include <USBDeviceInfo.h>
#include <stdexcept>
#include <vector>

static const uint16_t WIENERID(0x16dc);  // Wiener vendor id.
static const uint16_t VMUSBID(0xb);      // VMUSB product id.

USBDeviceInfo*
selectDevice(const std::vector<USBDeviceInfo*>& devices)
{
   USBDeviceInfo* result(nullptr);
   for (int i = 0; i < devices.size(); i++) {
      if ((WIENERID == devices[i]->getVendor()) &&
          (VMUSBID  == devices[i]->getProduct())) {
         delete result;    // In case we already found one.
         result = devices[i];
      } else {
         delete devices[i];
      }
   }
   if (!result) {
      throw std::runtime_error(
         "There are no VMUSB devices attached to the system"
      );
   }
   return result;
}

         

If you intende to hold on to a libusb_device pointer for longer than the life time of the the USBDeviceInfo object from which it came you need to properly handle its reference count as shown below. Note again, however, if you find yourself using a libusb_device to do what you can't otherwise do, you should reques the missing functionality be added to libUSB1.


#include <libusb.h>
#include <USBDeviceInfo>

...

USBDeviceInfo* pDevice = getDevice();   // Somehow.

libusb_device* pRawDevice = pDevice->getHandle();
libusb_ref_device(pRawDevice);

delete pDevice;

//   ... do stuff with the device until no longer needed:

libusb_unref_device(pRawDevice);
...

         

Note that if the call to libusb_ref_device is performed after pDevice is deleted, and pDevice is the last reference to that handle, lib usb will destroy the struture pointed to by pRawDevice because the destructor for USBDeviceInfo* calls libusb_unref_device.