mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Restructured Lightpack device (fix bug concerning the lifecycle of the libusb context)
Former-commit-id: ef7187e9117d75208e4d79b9f64839f88044a3c2
This commit is contained in:
parent
d60cca9e20
commit
409b800a8e
@ -1 +1 @@
|
|||||||
5031f4b1d3a2682b6df94ba6671bcc97f9b5a4d1
|
5078baeb33a6dca64d20161907b9638aeb047ffb
|
@ -89,8 +89,8 @@ LedDevice* Hyperion::createDevice(const Json::Value& deviceConfig)
|
|||||||
{
|
{
|
||||||
const std::string output = deviceConfig.get("output", "").asString();
|
const std::string output = deviceConfig.get("output", "").asString();
|
||||||
|
|
||||||
LedDeviceLightpack* deviceLightpack = new LedDeviceLightpack(output);
|
LedDeviceLightpack* deviceLightpack = new LedDeviceLightpack();
|
||||||
deviceLightpack->open();
|
deviceLightpack->open(output);
|
||||||
|
|
||||||
device = deviceLightpack;
|
device = deviceLightpack;
|
||||||
}
|
}
|
||||||
|
@ -32,13 +32,13 @@ enum DATA_VERSION_INDEXES{
|
|||||||
INDEX_FW_VER_MINOR
|
INDEX_FW_VER_MINOR
|
||||||
};
|
};
|
||||||
|
|
||||||
LedDeviceLightpack::LedDeviceLightpack(const std::string &serialNumber) :
|
LedDeviceLightpack::LedDeviceLightpack() :
|
||||||
LedDevice(),
|
LedDevice(),
|
||||||
_libusbContext(nullptr),
|
_libusbContext(nullptr),
|
||||||
_deviceHandle(nullptr),
|
_deviceHandle(nullptr),
|
||||||
_busNumber(-1),
|
_busNumber(-1),
|
||||||
_addressNumber(-1),
|
_addressNumber(-1),
|
||||||
_serialNumber(serialNumber),
|
_serialNumber(""),
|
||||||
_firmwareVersion({-1,-1}),
|
_firmwareVersion({-1,-1}),
|
||||||
_ledCount(-1),
|
_ledCount(-1),
|
||||||
_bitsPerChannel(-1),
|
_bitsPerChannel(-1),
|
||||||
@ -64,7 +64,7 @@ LedDeviceLightpack::~LedDeviceLightpack()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int LedDeviceLightpack::open()
|
int LedDeviceLightpack::open(const std::string & serialNumber)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ int LedDeviceLightpack::open()
|
|||||||
for (ssize_t i = 0 ; i < deviceCount; ++i)
|
for (ssize_t i = 0 ; i < deviceCount; ++i)
|
||||||
{
|
{
|
||||||
// try to open and initialize the device
|
// try to open and initialize the device
|
||||||
error = open(deviceList[i]);
|
error = testAndOpen(deviceList[i], serialNumber);
|
||||||
|
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
{
|
{
|
||||||
@ -113,7 +113,7 @@ int LedDeviceLightpack::open()
|
|||||||
return _deviceHandle == nullptr ? -1 : 0;
|
return _deviceHandle == nullptr ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LedDeviceLightpack::open(libusb_device * device)
|
int LedDeviceLightpack::testAndOpen(libusb_device * device, const std::string & requestedSerialNumber)
|
||||||
{
|
{
|
||||||
libusb_device_descriptor deviceDescriptor;
|
libusb_device_descriptor deviceDescriptor;
|
||||||
int error = libusb_get_device_descriptor(device, &deviceDescriptor);
|
int error = libusb_get_device_descriptor(device, &deviceDescriptor);
|
||||||
@ -147,22 +147,10 @@ int LedDeviceLightpack::open(libusb_device * device)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the firmware version
|
std::cout << "Lightpack device found: bus=" << busNumber << " address=" << addressNumber << " serial=" << serialNumber << std::endl;
|
||||||
Version version = {-1,-1};
|
|
||||||
try
|
|
||||||
{
|
|
||||||
version = LedDeviceLightpack::getVersion(device);
|
|
||||||
}
|
|
||||||
catch (int e)
|
|
||||||
{
|
|
||||||
std::cerr << "unable to retrieve firmware version number from Lightpack device(" << e << "): " << libusb_error_name(e) << std::endl;
|
|
||||||
version = {-1,-1};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Lightpack device found: bus=" << busNumber << " address=" << addressNumber << " serial=" << serialNumber << " version=" << version.majorVersion << "." << version.minorVersion << std::endl;
|
|
||||||
|
|
||||||
// check if this is the device we are looking for
|
// check if this is the device we are looking for
|
||||||
if (_serialNumber.empty() || _serialNumber == serialNumber)
|
if (requestedSerialNumber.empty() || requestedSerialNumber == serialNumber)
|
||||||
{
|
{
|
||||||
// This is it!
|
// This is it!
|
||||||
try
|
try
|
||||||
@ -174,6 +162,25 @@ int LedDeviceLightpack::open(libusb_device * device)
|
|||||||
|
|
||||||
std::cout << "Lightpack device successfully opened" << std::endl;
|
std::cout << "Lightpack device successfully opened" << std::endl;
|
||||||
|
|
||||||
|
// get the firmware version
|
||||||
|
uint8_t buffer[256];
|
||||||
|
error = libusb_control_transfer(
|
||||||
|
_deviceHandle,
|
||||||
|
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
|
||||||
|
0x01,
|
||||||
|
0x0100,
|
||||||
|
0,
|
||||||
|
buffer, sizeof(buffer), 1000);
|
||||||
|
if (error < 3)
|
||||||
|
{
|
||||||
|
std::cerr << "Unable to retrieve firmware version number from Lightpack device(" << error << "): " << libusb_error_name(error) << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_firmwareVersion.majorVersion = buffer[INDEX_FW_VER_MAJOR];
|
||||||
|
_firmwareVersion.minorVersion = buffer[INDEX_FW_VER_MINOR];
|
||||||
|
}
|
||||||
|
|
||||||
// FOR TESTING PURPOSE: FORCE MAJOR VERSION TO 6
|
// FOR TESTING PURPOSE: FORCE MAJOR VERSION TO 6
|
||||||
_firmwareVersion.majorVersion = 6;
|
_firmwareVersion.majorVersion = 6;
|
||||||
|
|
||||||
@ -206,6 +213,7 @@ int LedDeviceLightpack::open(libusb_device * device)
|
|||||||
_ledBuffer[0] = CMD_UPDATE_LEDS;
|
_ledBuffer[0] = CMD_UPDATE_LEDS;
|
||||||
|
|
||||||
// return success
|
// return success
|
||||||
|
std::cout << "Lightpack device opened: bus=" << _busNumber << " address=" << _addressNumber << " serial=" << _serialNumber << " version=" << _firmwareVersion.majorVersion << "." << _firmwareVersion.minorVersion << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch(int e)
|
catch(int e)
|
||||||
@ -347,31 +355,3 @@ std::string LedDeviceLightpack::getString(libusb_device * device, int stringDesc
|
|||||||
libusb_close(handle);
|
libusb_close(handle);
|
||||||
return std::string(buffer, error);
|
return std::string(buffer, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
LedDeviceLightpack::Version LedDeviceLightpack::getVersion(libusb_device *device)
|
|
||||||
{
|
|
||||||
libusb_device_handle * handle = nullptr;
|
|
||||||
|
|
||||||
int error = libusb_open(device, &handle);
|
|
||||||
if (error != LIBUSB_SUCCESS)
|
|
||||||
{
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t buffer[256];
|
|
||||||
error = libusb_control_transfer(
|
|
||||||
handle,
|
|
||||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
|
|
||||||
0x01,
|
|
||||||
0x0100,
|
|
||||||
0,
|
|
||||||
buffer, sizeof(buffer), 1000);
|
|
||||||
if (error < 3)
|
|
||||||
{
|
|
||||||
libusb_close(handle);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
libusb_close(handle);
|
|
||||||
return Version{buffer[INDEX_FW_VER_MAJOR], buffer[INDEX_FW_VER_MINOR]};
|
|
||||||
}
|
|
||||||
|
@ -20,7 +20,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// Constructs the LedDeviceLightpack
|
/// Constructs the LedDeviceLightpack
|
||||||
///
|
///
|
||||||
LedDeviceLightpack(const std::string & serialNumber = "");
|
LedDeviceLightpack();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Destructor of the LedDevice; closes the output device if it is open
|
/// Destructor of the LedDevice; closes the output device if it is open
|
||||||
@ -32,14 +32,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @return Zero on succes else negative
|
/// @return Zero on succes else negative
|
||||||
///
|
///
|
||||||
int open();
|
int open(const std::string & serialNumber = "");
|
||||||
|
|
||||||
///
|
|
||||||
/// Opens and configures the output device with the sepcified device
|
|
||||||
///
|
|
||||||
/// @return Zero on succes else negative
|
|
||||||
///
|
|
||||||
int open(libusb_device * device);
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Writes the RGB-Color values to the leds.
|
/// Writes the RGB-Color values to the leds.
|
||||||
@ -74,6 +67,13 @@ public:
|
|||||||
int getLedCount() const;
|
int getLedCount() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
///
|
||||||
|
/// Test if the device is a (or the) lightpack we are looking for
|
||||||
|
///
|
||||||
|
/// @return Zero on succes else negative
|
||||||
|
///
|
||||||
|
int testAndOpen(libusb_device * device, const std::string & requestedSerialNumber);
|
||||||
|
|
||||||
/// write bytes to the device
|
/// write bytes to the device
|
||||||
int writeBytes(uint8_t *data, int size);
|
int writeBytes(uint8_t *data, int size);
|
||||||
|
|
||||||
@ -88,7 +88,6 @@ private:
|
|||||||
|
|
||||||
static libusb_device_handle * openDevice(libusb_device * device);
|
static libusb_device_handle * openDevice(libusb_device * device);
|
||||||
static std::string getString(libusb_device * device, int stringDescriptorIndex);
|
static std::string getString(libusb_device * device, int stringDescriptorIndex);
|
||||||
static Version getVersion(libusb_device * device);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// libusb context
|
/// libusb context
|
||||||
|
@ -6,6 +6,12 @@
|
|||||||
// Local Hyperion includes
|
// Local Hyperion includes
|
||||||
#include "LedDeviceMultiLightpack.h"
|
#include "LedDeviceMultiLightpack.h"
|
||||||
|
|
||||||
|
// from USB_ID.h (http://code.google.com/p/light-pack/source/browse/CommonHeaders/USB_ID.h)
|
||||||
|
#define USB_OLD_VENDOR_ID 0x03EB
|
||||||
|
#define USB_OLD_PRODUCT_ID 0x204F
|
||||||
|
#define USB_VENDOR_ID 0x1D50
|
||||||
|
#define USB_PRODUCT_ID 0x6022
|
||||||
|
|
||||||
bool compareLightpacks(LedDeviceLightpack * lhs, LedDeviceLightpack * rhs)
|
bool compareLightpacks(LedDeviceLightpack * lhs, LedDeviceLightpack * rhs)
|
||||||
{
|
{
|
||||||
return lhs->getSerialNumber() < rhs->getSerialNumber();
|
return lhs->getSerialNumber() < rhs->getSerialNumber();
|
||||||
@ -27,49 +33,28 @@ LedDeviceMultiLightpack::~LedDeviceMultiLightpack()
|
|||||||
|
|
||||||
int LedDeviceMultiLightpack::open()
|
int LedDeviceMultiLightpack::open()
|
||||||
{
|
{
|
||||||
int error;
|
// retrieve a list with Lightpack serials
|
||||||
|
std::list<std::string> serialList = getLightpackSerials();
|
||||||
// initialize the usb context
|
|
||||||
libusb_context * libusbContext;
|
|
||||||
if ((error = libusb_init(&libusbContext)) != LIBUSB_SUCCESS)
|
|
||||||
{
|
|
||||||
std::cerr << "Error while initializing USB context(" << error << "): " << libusb_error_name(error) << std::endl;
|
|
||||||
libusbContext = nullptr;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
//libusb_set_debug(_libusbContext, 3);
|
|
||||||
std::cout << "USB context initialized in multi Lightpack device" << std::endl;
|
|
||||||
|
|
||||||
// retrieve the list of usb devices
|
|
||||||
libusb_device ** deviceList;
|
|
||||||
ssize_t deviceCount = libusb_get_device_list(libusbContext, &deviceList);
|
|
||||||
|
|
||||||
// iterate the list of devices
|
|
||||||
for (ssize_t i = 0 ; i < deviceCount; ++i)
|
|
||||||
{
|
|
||||||
// try to open the device as a Lightpack
|
|
||||||
LedDeviceLightpack * device = new LedDeviceLightpack();
|
|
||||||
error = device->open(deviceList[i]);
|
|
||||||
|
|
||||||
if (error == 0)
|
|
||||||
{
|
|
||||||
// Device is successfully opened as Lightpack
|
|
||||||
std::cout << "Lightpack with serial " << device->getSerialNumber() << " added to set of Lightpacks" << std::endl;
|
|
||||||
_lightpacks.push_back(device);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No Lightpack...
|
|
||||||
delete device;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the list of Lightpacks based on the serial to get a fixed order
|
// sort the list of Lightpacks based on the serial to get a fixed order
|
||||||
std::sort(_lightpacks.begin(), _lightpacks.end(), compareLightpacks);
|
std::sort(_lightpacks.begin(), _lightpacks.end(), compareLightpacks);
|
||||||
|
|
||||||
// free the device list
|
// open each lightpack device
|
||||||
libusb_free_device_list(deviceList, 1);
|
for (const std::string & serial : serialList)
|
||||||
libusb_exit(libusbContext);
|
{
|
||||||
|
LedDeviceLightpack * device = new LedDeviceLightpack();
|
||||||
|
int error = device->open(serial);
|
||||||
|
|
||||||
|
if (error == 0)
|
||||||
|
{
|
||||||
|
_lightpacks.push_back(device);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Error while creating Lightpack device with serial " << serial << std::endl;
|
||||||
|
delete device;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_lightpacks.size() == 0)
|
if (_lightpacks.size() == 0)
|
||||||
{
|
{
|
||||||
@ -117,3 +102,90 @@ int LedDeviceMultiLightpack::switchOff()
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::list<std::string> LedDeviceMultiLightpack::getLightpackSerials()
|
||||||
|
{
|
||||||
|
std::list<std::string> serialList;
|
||||||
|
|
||||||
|
std::cout << "Getting list of Lightpack serials" << std::endl;
|
||||||
|
|
||||||
|
// initialize the usb context
|
||||||
|
libusb_context * libusbContext;
|
||||||
|
int error = libusb_init(&libusbContext);
|
||||||
|
if (error != LIBUSB_SUCCESS)
|
||||||
|
{
|
||||||
|
std::cerr << "Error while initializing USB context(" << error << "): " << libusb_error_name(error) << std::endl;
|
||||||
|
libusbContext = nullptr;
|
||||||
|
return serialList;
|
||||||
|
}
|
||||||
|
//libusb_set_debug(_libusbContext, 3);
|
||||||
|
std::cout << "USB context initialized in multi Lightpack device" << std::endl;
|
||||||
|
|
||||||
|
// retrieve the list of usb devices
|
||||||
|
libusb_device ** deviceList;
|
||||||
|
ssize_t deviceCount = libusb_get_device_list(libusbContext, &deviceList);
|
||||||
|
|
||||||
|
// iterate the list of devices
|
||||||
|
for (ssize_t i = 0 ; i < deviceCount; ++i)
|
||||||
|
{
|
||||||
|
libusb_device_descriptor deviceDescriptor;
|
||||||
|
error = libusb_get_device_descriptor(deviceList[i], &deviceDescriptor);
|
||||||
|
if (error != LIBUSB_SUCCESS)
|
||||||
|
{
|
||||||
|
std::cerr << "Error while retrieving device descriptor(" << error << "): " << libusb_error_name(error) << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((deviceDescriptor.idVendor == USB_VENDOR_ID && deviceDescriptor.idProduct == USB_PRODUCT_ID) ||
|
||||||
|
(deviceDescriptor.idVendor == USB_OLD_VENDOR_ID && deviceDescriptor.idProduct == USB_OLD_PRODUCT_ID))
|
||||||
|
{
|
||||||
|
std::cout << "Found a lightpack device. Retrieving serial..." << std::endl;
|
||||||
|
|
||||||
|
// get the serial number
|
||||||
|
std::string serialNumber;
|
||||||
|
if (deviceDescriptor.iSerialNumber != 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
serialNumber = LedDeviceMultiLightpack::getString(deviceList[i], deviceDescriptor.iSerialNumber);
|
||||||
|
}
|
||||||
|
catch (int e)
|
||||||
|
{
|
||||||
|
std::cerr << "Unable to retrieve serial number(" << e << "): " << libusb_error_name(e) << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Lightpack device found with serial " << serialNumber << std::endl;
|
||||||
|
serialList.push_back(serialNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// free the device list
|
||||||
|
libusb_free_device_list(deviceList, 1);
|
||||||
|
libusb_exit(libusbContext);
|
||||||
|
|
||||||
|
return serialList;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LedDeviceMultiLightpack::getString(libusb_device * device, int stringDescriptorIndex)
|
||||||
|
{
|
||||||
|
libusb_device_handle * handle = nullptr;
|
||||||
|
|
||||||
|
int error = libusb_open(device, &handle);
|
||||||
|
if (error != LIBUSB_SUCCESS)
|
||||||
|
{
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
error = libusb_get_string_descriptor_ascii(handle, stringDescriptorIndex, reinterpret_cast<unsigned char *>(buffer), sizeof(buffer));
|
||||||
|
if (error <= 0)
|
||||||
|
{
|
||||||
|
libusb_close(handle);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
libusb_close(handle);
|
||||||
|
return std::string(buffer, error);
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
// libusb include
|
// libusb include
|
||||||
#include <libusb.h>
|
#include <libusb.h>
|
||||||
@ -51,6 +52,10 @@ public:
|
|||||||
///
|
///
|
||||||
virtual int switchOff();
|
virtual int switchOff();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::list<std::string> getLightpackSerials();
|
||||||
|
static std::string getString(libusb_device * device, int stringDescriptorIndex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// buffer for led data
|
/// buffer for led data
|
||||||
std::vector<LedDeviceLightpack *> _lightpacks;
|
std::vector<LedDeviceLightpack *> _lightpacks;
|
||||||
|
Loading…
Reference in New Issue
Block a user