// stl includes #include #include #include // 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(); } LedDeviceMultiLightpack::LedDeviceMultiLightpack(const QJsonObject &deviceConfig) : LedDevice() , _lightpacks() { _devConfig = deviceConfig; _deviceReady = false; } LedDeviceMultiLightpack::~LedDeviceMultiLightpack() { for (LedDeviceLightpack * device : _lightpacks) { delete device; } } LedDevice* LedDeviceMultiLightpack::construct(const QJsonObject &deviceConfig) { return new LedDeviceMultiLightpack(deviceConfig); } int LedDeviceMultiLightpack::open() { int retval = -1; QString errortext; _deviceReady = false; // General initialisation and configuration of LedDevice if ( init(_devConfig) ) { // retrieve a list with Lightpack serials QStringList serialList = getLightpackSerials(); // sort the list of Lightpacks based on the serial to get a fixed order std::sort(_lightpacks.begin(), _lightpacks.end(), compareLightpacks); // open each lightpack device foreach (auto serial , serialList) { LedDeviceLightpack * device = new LedDeviceLightpack(serial); int error = device->open(); if (error == 0) { _lightpacks.push_back(device); } else { //Error(_log, "Error while creating Lightpack device with serial %s", QSTRING_CSTR(serial)); errortext = QString ("Error while creating Lightpack device with serial %1").arg( serial ); delete device; } } if (_lightpacks.size() == 0) { //Warning(_log, "No Lightpack devices were found"); errortext = QString ("No Lightpack devices were found"); } else { Info(_log, "%d Lightpack devices were found", _lightpacks.size()); // Everything is OK -> enable device _deviceReady = true; setEnable(true); retval = 0; } // On error/exceptions, set LedDevice in error if ( retval < 0 ) { this->setInError( errortext ); } } return retval; } int LedDeviceMultiLightpack::write(const std::vector &ledValues) { const ColorRgb * data = ledValues.data(); int size = ledValues.size(); for (LedDeviceLightpack * device : _lightpacks) { int count = qMin(static_cast( device->getLedCount()), size); if (count > 0) { device->write(data, count); data += count; size -= count; } else { Warning(_log, "Unable to write data to Lightpack device: no more led data available"); } } return 0; } int LedDeviceMultiLightpack::switchOff() { for (LedDeviceLightpack * device : _lightpacks) { device->switchOff(); } return 0; } QStringList LedDeviceMultiLightpack::getLightpackSerials() { QStringList serialList; Logger * log = Logger::getInstance("LedDevice"); Debug(log, "Getting list of Lightpack serials"); // initialize the usb context libusb_context * libusbContext; int error = libusb_init(&libusbContext); if (error != LIBUSB_SUCCESS) { Error(log,"Error while initializing USB context(%d): %s", error, libusb_error_name(error)); libusbContext = nullptr; return serialList; } //libusb_set_debug(_libusbContext, 3); Info(log, "USB context initialized in multi Lightpack device"); // 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) { Error(log, "Error while retrieving device descriptor(%d): %s", error, libusb_error_name(error)); continue; } if ((deviceDescriptor.idVendor == USB_VENDOR_ID && deviceDescriptor.idProduct == USB_PRODUCT_ID) || (deviceDescriptor.idVendor == USB_OLD_VENDOR_ID && deviceDescriptor.idProduct == USB_OLD_PRODUCT_ID)) { Info(log, "Found a lightpack device. Retrieving serial..."); // get the serial number QString serialNumber; if (deviceDescriptor.iSerialNumber != 0) { // TODO: Check, if exceptions via try/catch need to be replaced in Qt environment try { serialNumber = LedDeviceMultiLightpack::getString(deviceList[i], deviceDescriptor.iSerialNumber); } catch (int e) { Error(log,"Unable to retrieve serial number(%d): %s", e, libusb_error_name(e)); continue; } } Error(log, "Lightpack device found with serial %s", QSTRING_CSTR(serialNumber));; serialList.append(serialNumber); } } // free the device list libusb_free_device_list(deviceList, 1); libusb_exit(libusbContext); return serialList; } QString 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(buffer), sizeof(buffer)); if (error <= 0) { libusb_close(handle); throw error; } libusb_close(handle); return QString(QByteArray(buffer, error)); }