I want to use libusb library in my C++ application. I have created classes which wraps libusb functions. You can see that libusb API is split into 8 sections:
http://libusb.sourceforge.net/api-1.0/modules.html
For me the most necessary sections are:
- Device handling and enumeration
- Synchronous device I/O
- Library initialization/deinitialization
- Miscellaneous
I have also split "Device handling and enumeration" section to "Device Info" and "Device Handling". To use libusb functions it is need to initialize libusb library (call libusb_init
function), store somewhere its initialized libusb_context *
, next - call functions (libusb_get_device_list
, libusb_open_device_with_vid_pid
) to obtain and store somewhere "device pointer" (in libusb known as libusb_device*
or libusb_device_handle*
), and then finally call functions for obtaining device info or performing some USB transfers (for instance: libusb_set_configuration
, libusb_get_bus_number
). Note, that these functions require "device pointer": libusb_device_handle*
or libusb_device_*
as first parameter. You can see whole process of initializing/opening/controlling device here:
http://www.dreamincode.net/forums/topic/148707-introduction-to-using-libusb-10/
Currenlty my solution consists of following classes:
- LibusbInfoAPI: provides functions to obtain device info
- LibusbControlAPI: provides functions to control device
- LibusbHandlingAPI: creates devices, destroys, manages them, and stores
libusb_context *
,libusb_device *
,libusb_device_handle *
LibusbControlAPI header:
class LibusbControlAPI
{
public:
int GetConfiguration(DevHandlePtr deviceHandle, int& activeConfiguration);
int SetConfiguration(DevHandlePtr deviceHandle, int targetConfiguration);
int ClaimInterface(DevHandlePtr deviceHandle, int interfaceNumber);
int ReleaseInterface(DevHandlePtr deviceHandle, int interfaceNumber);
int SetInterfaceAlternateSetting(DevHandlePtr deviceHandle, int interfaceNumber, int alternateSetting);
int ClearHalt(DevHandlePtr deviceHandle, USBEndpoint endpoint);
int SendControlTransfer(DevHandlePtr deviceHandle,
uint8_t bmRequestType,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
unsigned char * buffer,
uint16_t wLength,
unsigned int timeout);
int SendInterruptTransfer(DevHandlePtr deviceHandle,
USBEndpoint endpoint,
unsigned char * buffer,
int length,
int & transferred,
unsigned int timeout);
int SendBlukTransfer(DevHandlePtr deviceHandle,
USBEndpoint endpoint,
unsigned char * buffer,
int length,
int & transferred,
unsigned int timeout);
};
Part of cpp file:
int LibusbControlAPI::GetConfiguration(DevHandlePtr deviceHandle, int & activeConfiguration)
{
int result;
int * configuration = nullptr;
if (!deviceHandle->m_opened)
return 1;
result = libusb_get_configuration(deviceHandle->m_libusbData->m_libusbDeviceHandle, configuration);
if (result != 0)
return 1;
activeConfiguration = *configuration;
return 0;
}
Similary for LibusbInfoAPI header i have:
class LibusbInfoAPI
{
public:
int GetBusNumber(DevHandlePtr deviceHandle, uint8_t& busNumber);
int GetPortNumber(DevHandlePtr deviceHandle, uint8_t& portNumber);
int GetDeviceAddress(DevHandlePtr deviceHandle, uint8_t& deviceAddress);
int GetDeviceSpeed(DevHandlePtr deviceHandle, USBSpeed& usbSpeed);
int GetMaxPacketSize(DevHandlePtr deviceHandle, USBEndpoint endpoint, int& maxPacketSize);
int GetMaxIsoPacketSize(DevHandlePtr deviceHandle, USBEndpoint endpoint, int& isoMaxPacketSize);
};
...and LibusbHandlingAPI (in this class I store libusb structures, in CreateDevice
function I return a pointer which I use for LibusbControlAPI
and LibusbInfoAPI
):
class LibusbHandlingAPI
{
private:
typedef std::vector<DevHandlePtr> DevHandlePtrVect;
DevHandlePtrVect m_deviceHandleVect;
LibusbContextPtr m_libusbContext;
public:
DevHandlePtr CreateDevice(uint16_t vendorId, uint16_t productId);
DevHandlePtr CreateDevice(uint16_t vendorId, uint16_t productId, uint8_t busNumber, uint8_t * portNumbers, int portNumbersLength);
void DestroyDevice(DevHandlePtr deviceHandle);
int OpenDevice(DevHandlePtr deviceHandle);
int CloseDevice(DevHandlePtr deviceHandle);
int InitializeLibrary(SystemLibraryLogLevel logLevel);
void DestroyLibrary(void);
};
So, my question is:
- Is it good solution/class design? What do you think?
- What are yours propositions/suggestions?
- How can I improve it, what should i change?
- What classes should I create/remove?
LibusbControlAPI
andLibusbInfoAPI
take aDevHandlePtr
as a parameter. You would think there would be a USB object that abstracted away the need to keep and store this handle. As it stands this is not a wrapper (it is simply a re-packaging). \$\endgroup\$libusb_device*
andlibusb_device_handle*
as keys to libusb API (packed intoDevHandlePtr
), and this code what I wrote only repeats/rewrites libusb API. So I think I need to create libusb API class (such thing likeLibusbInfoAPI
orLibusbControlAPI
but the first parameter for methods shouldn't be DevHandlePtr). In brief as I understand it, my wrapper code shouldn't remind or associate with libusb API. \$\endgroup\$LibusbControlAPI
(as I mentioned in comment above, withoutDevHadnlePtr
) and prepare constructor for injecting external object. Then I could call methods from such class without providingDevHadnlePtr
as first parameter. But the object I would pass to construtor needs to store reference tolibusb_device*
andlibusb_device_handle*
, such object would be some kind of facade. \$\endgroup\$