Skip to content

Commit

Permalink
Determine correct association between V4L device and USB device, inst…
Browse files Browse the repository at this point in the history
…ead of relying on a unique VID/PID match.

This should allow multiple F200 or SR300 devices to be connected at once.
  • Loading branch information
sgorsten committed Jan 26, 2016
1 parent 1b0041d commit bbf9e73
Showing 1 changed file with 19 additions and 12 deletions.
31 changes: 19 additions & 12 deletions src/uvc-v4l2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

#include <libusb.h>

#include <iostream>

namespace rsimpl
{
namespace uvc
Expand Down Expand Up @@ -72,9 +74,10 @@ namespace rsimpl

struct subdevice
{
std::string dev_name;
int vid, pid, mi;
int fd;
std::string dev_name; // Device name (typically of the form /dev/video*)
int busnum, devnum; // USB device bus number and device number (needed for F200/SR300 direct USB controls)
int vid, pid, mi; // Vendor ID, product ID, and multiple interface index
int fd; // File descriptor for this device
std::vector<buffer> buffers;

int width, height, format, fps;
Expand All @@ -91,6 +94,14 @@ namespace rsimpl
}
if(!S_ISCHR(st.st_mode)) throw std::runtime_error(dev_name + " is no device");

// TODO: Might not always be exactly three dirs up, might need to walk upwards until we find busnum and devnum
std::ostringstream ss; ss << "/sys/dev/char/" << major(st.st_rdev) << ":" << minor(st.st_rdev) << "/";
auto path = ss.str();
if(!(std::ifstream(path + "../../../busnum") >> busnum))
throw std::runtime_error("Failed to read busnum");
if(!(std::ifstream(path + "../../../devnum") >> devnum))
throw std::runtime_error("Failed to read devnum");

std::string modalias;
if(!(std::ifstream("/sys/class/video4linux/" + name + "/device/modalias") >> modalias))
throw std::runtime_error("Failed to read modalias");
Expand Down Expand Up @@ -529,18 +540,14 @@ namespace rsimpl
for(int i=0; list[i]; ++i)
{
libusb_device * usb_device = list[i];
int busnum = libusb_get_bus_number(usb_device);
int devnum = libusb_get_device_address(usb_device);

libusb_device_descriptor desc;
status = libusb_get_device_descriptor(usb_device, &desc);
if(status < 0) throw std::runtime_error(to_string() << "libusb_get_device_descriptor(...) returned " << libusb_error_name(status));

// Look for a video device whose busnum/devnum matches this USB device
for(auto & dev : devices)
{
if(desc.idVendor == get_vendor_id(*dev) && desc.idProduct == get_product_id(*dev))
{
if(busnum == dev->subdevices[0]->busnum && devnum == dev->subdevices[0]->devnum)
{
// todo - Also make sure that we are sitting on the right bus/address
// libusb_get_bus_number(usb_device);
// libusb_get_device_address(usb_device);
dev->usb_device = usb_device;
libusb_ref_device(usb_device);
break;
Expand Down

0 comments on commit bbf9e73

Please sign in to comment.