Skip to content

Commit 321123e

Browse files
committed
Merge pull request #29 from christiankerl/fix_device_enumeration
enhance device enumeration - implements the methods to get device serial numbers and to open a device identified by its serial number - resets device inside openDevice method
2 parents 1e73305 + 9e1f21d commit 321123e

File tree

2 files changed

+119
-40
lines changed

2 files changed

+119
-40
lines changed

examples/protonect/Protonect.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ int main(int argc, char *argv[])
9191
cv::imshow("depth", cv::Mat(depth->height, depth->width, CV_32FC1, depth->data) / 4500.0f);
9292

9393
int key = cv::waitKey(1);
94-
shutdown = key > 0 && ((key & 0xFF) == 27); // shutdown on escape
94+
shutdown = shutdown || (key > 0 && ((key & 0xFF) == 27)); // shutdown on escape
9595

9696
listener.release(frames);
9797
//libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(100));

examples/protonect/src/libfreenect2.cpp

Lines changed: 118 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class Freenect2DeviceImpl : public Freenect2Device
8282
Freenect2Device::IrCameraParams ir_camera_params_;
8383
Freenect2Device::ColorCameraParams rgb_camera_params_;
8484
public:
85-
Freenect2DeviceImpl(Freenect2Impl *context, libusb_device *usb_device, libusb_device_handle *usb_device_handle);
85+
Freenect2DeviceImpl(Freenect2Impl *context, libusb_device *usb_device, libusb_device_handle *usb_device_handle, const std::string &serial);
8686
virtual ~Freenect2DeviceImpl();
8787

8888
bool isSameUsbDevice(libusb_device* other);
@@ -104,14 +104,32 @@ class Freenect2DeviceImpl : public Freenect2Device
104104
virtual void close();
105105
};
106106

107+
struct PrintBusAndDevice
108+
{
109+
libusb_device *dev_;
110+
111+
PrintBusAndDevice(libusb_device *dev) : dev_(dev) {}
112+
};
113+
114+
std::ostream &operator<<(std::ostream &out, const PrintBusAndDevice& dev)
115+
{
116+
out << "@" << int(libusb_get_bus_number(dev.dev_)) << ":" << int(libusb_get_port_number(dev.dev_));
117+
return out;
118+
}
119+
107120
class Freenect2Impl
108121
{
109122
private:
110123
bool managed_usb_context_;
111124
libusb_context *usb_context_;
112125
EventLoop usb_event_loop_;
113126
public:
114-
typedef std::vector<libusb_device *> UsbDeviceVector;
127+
struct UsbDeviceWithSerial
128+
{
129+
libusb_device *dev;
130+
std::string serial;
131+
};
132+
typedef std::vector<UsbDeviceWithSerial> UsbDeviceVector;
115133
typedef std::vector<Freenect2DeviceImpl *> DeviceVector;
116134

117135
bool has_device_enumeration_;
@@ -203,7 +221,7 @@ class Freenect2Impl
203221
// free enumerated device pointers, this should not affect opened devices
204222
for(UsbDeviceVector::iterator it = enumerated_devices_.begin(); it != enumerated_devices_.end(); ++it)
205223
{
206-
libusb_unref_device(*it);
224+
libusb_unref_device(it->dev);
207225
}
208226

209227
enumerated_devices_.clear();
@@ -225,18 +243,57 @@ class Freenect2Impl
225243
libusb_device *dev = device_list[idx];
226244
libusb_device_descriptor dev_desc;
227245

228-
int r = libusb_get_device_descriptor(dev, &dev_desc);
229-
// TODO: error handling
246+
int r = libusb_get_device_descriptor(dev, &dev_desc); // this is always successful
230247

231248
if(dev_desc.idVendor == Freenect2Device::VendorId && (dev_desc.idProduct == Freenect2Device::ProductId || dev_desc.idProduct == Freenect2Device::ProductIdPreview))
232249
{
233-
// valid Kinect v2
234-
enumerated_devices_.push_back(dev);
235-
}
236-
else
237-
{
238-
libusb_unref_device(dev);
250+
Freenect2DeviceImpl *freenect2_dev;
251+
252+
// prevent error if device is already open
253+
if(tryGetDevice(dev, &freenect2_dev))
254+
{
255+
UsbDeviceWithSerial dev_with_serial;
256+
dev_with_serial.dev = dev;
257+
dev_with_serial.serial = freenect2_dev->getSerialNumber();
258+
259+
enumerated_devices_.push_back(dev_with_serial);
260+
continue;
261+
}
262+
else
263+
{
264+
libusb_device_handle *dev_handle;
265+
r = libusb_open(dev, &dev_handle);
266+
267+
if(r == LIBUSB_SUCCESS)
268+
{
269+
unsigned char buffer[1024];
270+
r = libusb_get_string_descriptor_ascii(dev_handle, dev_desc.iSerialNumber, buffer, sizeof(buffer));
271+
272+
if(r > LIBUSB_SUCCESS)
273+
{
274+
UsbDeviceWithSerial dev_with_serial;
275+
dev_with_serial.dev = dev;
276+
dev_with_serial.serial = std::string(reinterpret_cast<char *>(buffer), size_t(r));
277+
278+
std::cout << "[Freenect2Impl] found valid Kinect v2 " << PrintBusAndDevice(dev) << " with serial " << dev_with_serial.serial << std::endl;
279+
// valid Kinect v2
280+
enumerated_devices_.push_back(dev_with_serial);
281+
continue;
282+
}
283+
else
284+
{
285+
std::cout << "[Freenect2Impl] failed to get serial number of Kinect v2 " << PrintBusAndDevice(dev) << "!" << std::endl;
286+
}
287+
288+
libusb_close(dev_handle);
289+
}
290+
else
291+
{
292+
std::cout << "[Freenect2Impl] failed to open Kinect v2 " << PrintBusAndDevice(dev) << "!" << std::endl;
293+
}
294+
}
239295
}
296+
libusb_unref_device(dev);
240297
}
241298
}
242299

@@ -261,7 +318,7 @@ Freenect2Device::~Freenect2Device()
261318
{
262319
}
263320

264-
Freenect2DeviceImpl::Freenect2DeviceImpl(Freenect2Impl *context, libusb_device *usb_device, libusb_device_handle *usb_device_handle) :
321+
Freenect2DeviceImpl::Freenect2DeviceImpl(Freenect2Impl *context, libusb_device *usb_device, libusb_device_handle *usb_device_handle, const std::string &serial) :
265322
state_(Created),
266323
has_usb_interfaces_(false),
267324
context_(context),
@@ -276,7 +333,7 @@ Freenect2DeviceImpl::Freenect2DeviceImpl(Freenect2Impl *context, libusb_device *
276333
depth_packet_processor_(0),
277334
rgb_packet_parser_(&rgb_packet_processor_),
278335
depth_packet_parser_(&depth_packet_processor_),
279-
serial_("<unknown>"),
336+
serial_(serial),
280337
firmware_("<unknown>")
281338
{
282339
rgb_transfer_pool_.setCallback(&rgb_packet_parser_);
@@ -400,7 +457,12 @@ void Freenect2DeviceImpl::start()
400457
std::cout << GenericResponse(result.data, result.length).toString() << std::endl;
401458

402459
command_tx_.execute(ReadSerialNumberCommand(nextCommandSeq()), serial_result);
403-
serial_ = SerialNumberResponse(serial_result.data, serial_result.length).toString();
460+
std::string new_serial = SerialNumberResponse(serial_result.data, serial_result.length).toString();
461+
462+
if(serial_ != new_serial)
463+
{
464+
std::cout << "[Freenect2DeviceImpl] serial number reported by libusb " << serial_ << " differs from serial number " << new_serial << " in device protocol! " << std::endl;
465+
}
404466

405467
command_tx_.execute(ReadDepthCameraParametersCommand(nextCommandSeq()), result);
406468
DepthCameraParamsResponse *ir_p = reinterpret_cast<DepthCameraParamsResponse *>(result.data);
@@ -561,7 +623,7 @@ int Freenect2::enumerateDevices()
561623

562624
std::string Freenect2::getDeviceSerialNumber(int idx)
563625
{
564-
throw std::exception();
626+
return impl_->enumerated_devices_[idx].serial;
565627
}
566628

567629
std::string Freenect2::getDefaultDeviceSerialNumber()
@@ -572,51 +634,68 @@ std::string Freenect2::getDefaultDeviceSerialNumber()
572634
Freenect2Device *Freenect2::openDevice(int idx)
573635
{
574636
int num_devices = impl_->getNumDevices();
637+
Freenect2DeviceImpl *device = 0;
575638

576639
if(idx < num_devices)
577640
{
578-
libusb_device *dev = impl_->enumerated_devices_[idx];
641+
Freenect2Impl::UsbDeviceWithSerial &dev = impl_->enumerated_devices_[idx];
579642
libusb_device_handle *dev_handle;
580643

581-
Freenect2DeviceImpl *device;
582-
583-
if(impl_->tryGetDevice(dev, &device))
584-
{
585-
return device;
586-
}
587-
else
644+
if(!impl_->tryGetDevice(dev.dev, &device))
588645
{
589-
int r = libusb_open(dev, &dev_handle);
590-
// TODO: error handling
591-
592-
device = new Freenect2DeviceImpl(impl_, dev, dev_handle);
593-
impl_->addDevice(device);
646+
int r = libusb_open(dev.dev, &dev_handle);
594647

595-
if(device->open())
648+
if(r == LIBUSB_SUCCESS)
596649
{
597-
return device;
650+
r = libusb_reset_device(dev_handle);
651+
652+
if(r == LIBUSB_SUCCESS)
653+
{
654+
device = new Freenect2DeviceImpl(impl_, dev.dev, dev_handle, dev.serial);
655+
impl_->addDevice(device);
656+
657+
if(!device->open())
658+
{
659+
delete device;
660+
device = 0;
661+
662+
std::cout << "[Freenect2DeviceImpl] failed to open Kinect v2 " << PrintBusAndDevice(dev.dev) << "!" << std::endl;
663+
}
664+
}
665+
else
666+
{
667+
std::cout << "[Freenect2Impl] failed to reset Kinect v2 " << PrintBusAndDevice(dev.dev) << "!" << std::endl;
668+
}
598669
}
599670
else
600671
{
601-
std::cout << "[Freenect2DeviceImpl] Unable to open device: " << idx << std::endl;
602-
delete device;
603-
604-
// TODO: error handling
605-
return 0;
672+
std::cout << "[Freenect2Impl] failed to open Kinect v2 " << PrintBusAndDevice(dev.dev) << "!" << std::endl;
606673
}
607674
}
608675
}
609676
else
610677
{
611-
std::cout << "[Freenect2DeviceImpl] Requested device " << idx << " is not connected!" << std::endl;
612-
// TODO: error handling
613-
return 0;
678+
std::cout << "[Freenect2Impl] requested device " << idx << " is not connected!" << std::endl;
614679
}
680+
681+
return device;
615682
}
616683

617684
Freenect2Device *Freenect2::openDevice(const std::string &serial)
618685
{
619-
throw std::exception();
686+
Freenect2Device *device = 0;
687+
int num_devices = impl_->getNumDevices();
688+
689+
for(int idx = 0; idx < num_devices; ++idx)
690+
{
691+
if(impl_->enumerated_devices_[idx].serial == serial)
692+
{
693+
device = openDevice(idx);
694+
break;
695+
}
696+
}
697+
698+
return device;
620699
}
621700

622701
Freenect2Device *Freenect2::openDefaultDevice()

0 commit comments

Comments
 (0)