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();
|
||||
|
||||
LedDeviceLightpack* deviceLightpack = new LedDeviceLightpack(output);
|
||||
deviceLightpack->open();
|
||||
LedDeviceLightpack* deviceLightpack = new LedDeviceLightpack();
|
||||
deviceLightpack->open(output);
|
||||
|
||||
device = deviceLightpack;
|
||||
}
|
||||
|
@ -32,13 +32,13 @@ enum DATA_VERSION_INDEXES{
|
||||
INDEX_FW_VER_MINOR
|
||||
};
|
||||
|
||||
LedDeviceLightpack::LedDeviceLightpack(const std::string &serialNumber) :
|
||||
LedDeviceLightpack::LedDeviceLightpack() :
|
||||
LedDevice(),
|
||||
_libusbContext(nullptr),
|
||||
_deviceHandle(nullptr),
|
||||
_busNumber(-1),
|
||||
_addressNumber(-1),
|
||||
_serialNumber(serialNumber),
|
||||
_serialNumber(""),
|
||||
_firmwareVersion({-1,-1}),
|
||||
_ledCount(-1),
|
||||
_bitsPerChannel(-1),
|
||||
@ -64,7 +64,7 @@ LedDeviceLightpack::~LedDeviceLightpack()
|
||||
}
|
||||
}
|
||||
|
||||
int LedDeviceLightpack::open()
|
||||
int LedDeviceLightpack::open(const std::string & serialNumber)
|
||||
{
|
||||
int error;
|
||||
|
||||
@ -86,7 +86,7 @@ int LedDeviceLightpack::open()
|
||||
for (ssize_t i = 0 ; i < deviceCount; ++i)
|
||||
{
|
||||
// try to open and initialize the device
|
||||
error = open(deviceList[i]);
|
||||
error = testAndOpen(deviceList[i], serialNumber);
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
@ -113,7 +113,7 @@ int LedDeviceLightpack::open()
|
||||
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;
|
||||
int error = libusb_get_device_descriptor(device, &deviceDescriptor);
|
||||
@ -147,22 +147,10 @@ int LedDeviceLightpack::open(libusb_device * device)
|
||||
}
|
||||
}
|
||||
|
||||
// get the firmware version
|
||||
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;
|
||||
std::cout << "Lightpack device found: bus=" << busNumber << " address=" << addressNumber << " serial=" << serialNumber << std::endl;
|
||||
|
||||
// check if this is the device we are looking for
|
||||
if (_serialNumber.empty() || _serialNumber == serialNumber)
|
||||
if (requestedSerialNumber.empty() || requestedSerialNumber == serialNumber)
|
||||
{
|
||||
// This is it!
|
||||
try
|
||||
@ -174,6 +162,25 @@ int LedDeviceLightpack::open(libusb_device * device)
|
||||
|
||||
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
|
||||
_firmwareVersion.majorVersion = 6;
|
||||
|
||||
@ -206,6 +213,7 @@ int LedDeviceLightpack::open(libusb_device * device)
|
||||
_ledBuffer[0] = CMD_UPDATE_LEDS;
|
||||
|
||||
// return success
|
||||
std::cout << "Lightpack device opened: bus=" << _busNumber << " address=" << _addressNumber << " serial=" << _serialNumber << " version=" << _firmwareVersion.majorVersion << "." << _firmwareVersion.minorVersion << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch(int e)
|
||||
@ -347,31 +355,3 @@ std::string LedDeviceLightpack::getString(libusb_device * device, int stringDesc
|
||||
libusb_close(handle);
|
||||
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
|
||||
///
|
||||
LedDeviceLightpack(const std::string & serialNumber = "");
|
||||
LedDeviceLightpack();
|
||||
|
||||
///
|
||||
/// Destructor of the LedDevice; closes the output device if it is open
|
||||
@ -32,14 +32,7 @@ public:
|
||||
///
|
||||
/// @return Zero on succes else negative
|
||||
///
|
||||
int open();
|
||||
|
||||
///
|
||||
/// Opens and configures the output device with the sepcified device
|
||||
///
|
||||
/// @return Zero on succes else negative
|
||||
///
|
||||
int open(libusb_device * device);
|
||||
int open(const std::string & serialNumber = "");
|
||||
|
||||
///
|
||||
/// Writes the RGB-Color values to the leds.
|
||||
@ -74,6 +67,13 @@ public:
|
||||
int getLedCount() const;
|
||||
|
||||
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
|
||||
int writeBytes(uint8_t *data, int size);
|
||||
|
||||
@ -88,7 +88,6 @@ private:
|
||||
|
||||
static libusb_device_handle * openDevice(libusb_device * device);
|
||||
static std::string getString(libusb_device * device, int stringDescriptorIndex);
|
||||
static Version getVersion(libusb_device * device);
|
||||
|
||||
private:
|
||||
/// libusb context
|
||||
|
@ -6,6 +6,12 @@
|
||||
// Local Hyperion includes
|
||||
#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)
|
||||
{
|
||||
return lhs->getSerialNumber() < rhs->getSerialNumber();
|
||||
@ -27,49 +33,28 @@ LedDeviceMultiLightpack::~LedDeviceMultiLightpack()
|
||||
|
||||
int LedDeviceMultiLightpack::open()
|
||||
{
|
||||
int error;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
// retrieve a list with Lightpack serials
|
||||
std::list<std::string> serialList = getLightpackSerials();
|
||||
|
||||
// sort the list of Lightpacks based on the serial to get a fixed order
|
||||
std::sort(_lightpacks.begin(), _lightpacks.end(), compareLightpacks);
|
||||
|
||||
// free the device list
|
||||
libusb_free_device_list(deviceList, 1);
|
||||
libusb_exit(libusbContext);
|
||||
// open each lightpack device
|
||||
for (const std::string & serial : serialList)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -117,3 +102,90 @@ int LedDeviceMultiLightpack::switchOff()
|
||||
|
||||
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 <cstdint>
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
// libusb include
|
||||
#include <libusb.h>
|
||||
@ -51,6 +52,10 @@ public:
|
||||
///
|
||||
virtual int switchOff();
|
||||
|
||||
private:
|
||||
static std::list<std::string> getLightpackSerials();
|
||||
static std::string getString(libusb_device * device, int stringDescriptorIndex);
|
||||
|
||||
private:
|
||||
/// buffer for led data
|
||||
std::vector<LedDeviceLightpack *> _lightpacks;
|
||||
|
Loading…
Reference in New Issue
Block a user