st/prober: Save usb path and product name

This commit is contained in:
Jakob Bornecrantz 2019-06-26 15:10:32 +01:00
parent 24d3dc45c8
commit 16f8b013ec
3 changed files with 150 additions and 35 deletions

View file

@ -267,6 +267,16 @@ teardown_devices(struct prober* p)
struct prober_device* pdev = &p->devices[i];
#ifdef XRT_OS_LINUX
if (pdev->usb.product != NULL) {
free((char*)pdev->usb.product);
pdev->usb.product = NULL;
}
if (pdev->usb.path != NULL) {
free((char*)pdev->usb.path);
pdev->usb.path = NULL;
}
for (size_t j = 0; j < pdev->num_v4ls; j++) {
struct prober_v4l* v4l = &pdev->v4ls[j];
free((char*)v4l->path);
@ -343,6 +353,14 @@ probe(struct xrt_prober* xp)
// Free old list first.
teardown_devices(p);
#ifdef XRT_HAVE_LIBUDEV
ret = p_udev_probe(p);
if (ret != 0) {
P_ERROR(p, "Failed to enumerate udev devices\n");
return -1;
}
#endif
#ifdef XRT_HAVE_LIBUSB
ret = p_libusb_probe(p);
if (ret != 0) {
@ -359,14 +377,6 @@ probe(struct xrt_prober* xp)
}
#endif
#ifdef XRT_HAVE_LIBUDEV
ret = p_udev_probe(p);
if (ret != 0) {
P_ERROR(p, "Failed to enumerate udev devices\n");
return -1;
}
#endif
return 0;
}

View file

@ -88,6 +88,11 @@ struct prober_device
uint16_t bus;
uint16_t addr;
#ifdef XRT_OS_LINUX
const char* product;
const char* path;
#endif
uint8_t ports[8];
uint32_t num_ports;

View file

@ -33,6 +33,14 @@
*
*/
static void
p_udev_enumerate_usb(struct prober* p, struct udev* udev);
static void
p_udev_add_usb(struct prober_device* pdev,
const char* product,
const char* path);
static void
p_udev_enumerate_v4l2(struct prober* p, struct udev* udev);
@ -80,9 +88,11 @@ p_udev_get_vendor_id_product(struct udev_device* usb_device_dev,
uint16_t* product_id);
static int
p_udev_get_usb_device_address(struct udev_device* usb_device_dev,
uint16_t* usb_bus,
uint16_t* usb_addr);
p_udev_get_usb_device_info(struct udev_device* usb_device_dev,
uint16_t* vendor_id,
uint16_t* product_id,
uint16_t* usb_bus,
uint16_t* usb_addr);
static int
p_udev_get_usb_device_address_path(struct udev_device* usb_dev,
@ -123,6 +133,8 @@ p_udev_probe(struct prober* p)
return -1;
}
p_udev_enumerate_usb(p, udev);
p_udev_enumerate_v4l2(p, udev);
p_udev_enumerate_hidraw(p, udev);
@ -139,6 +151,91 @@ p_udev_probe(struct prober* p)
*
*/
static void
p_udev_enumerate_usb(struct prober* p, struct udev* udev)
{
struct udev_enumerate* enumerate;
struct udev_list_entry *devices, *dev_list_entry;
enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "usb");
udev_enumerate_add_match_property(enumerate, "DEVTYPE", "usb_device");
udev_enumerate_scan_devices(enumerate);
devices = udev_enumerate_get_list_entry(enumerate);
udev_list_entry_foreach(dev_list_entry, devices)
{
struct prober_device* pdev = NULL;
struct udev_device* raw_dev = NULL;
const char* sysfs_path = NULL;
const char* dev_path = NULL;
const char* product = NULL;
uint16_t vendor_id = 0;
uint16_t product_id = 0;
uint16_t usb_bus = 0;
uint16_t usb_addr = 0;
int ret;
// Where in the sysfs is.
sysfs_path = udev_list_entry_get_name(dev_list_entry);
// Raw sysfs node.
raw_dev = udev_device_new_from_syspath(udev, sysfs_path);
// The thing we will open.
dev_path = udev_device_get_devnode(raw_dev);
// Product name.
product = udev_device_get_sysattr_value(raw_dev, "product");
ret = p_udev_get_usb_device_info(
raw_dev, &vendor_id, &product_id, &usb_bus, &usb_addr);
if (ret != 0) {
P_ERROR(p, "Failed to get usb device info");
goto next;
}
ret = p_dev_get_usb_dev(p, usb_bus, usb_addr, vendor_id,
product_id, &pdev);
P_SPEW(p,
"usb\n"
"\t\tptr: %p (%i)\n"
"\t\tsysfs_path: '%s'\n"
"\t\tdev_path: '%s'\n"
"\t\tvendor_id: %04x\n"
"\t\tproduct_id: %04x\n"
"\t\tusb_bus: %i\n"
"\t\tusb_addr: %i\n"
"\t\tproduct: '%s'",
(void*)pdev, ret, sysfs_path, dev_path, vendor_id,
product_id, usb_bus, usb_addr, product);
if (ret != 0) {
P_ERROR(p, "p_dev_get_usb_device failed!");
goto next;
}
// Add info to usb device.
p_udev_add_usb(pdev, product, dev_path);
next:
udev_device_unref(raw_dev);
}
enumerate = udev_enumerate_unref(enumerate);
}
static void
p_udev_add_usb(struct prober_device* pdev,
const char* product,
const char* path)
{
if (product != NULL) {
pdev->usb.product = strdup(product);
}
if (path != NULL) {
pdev->usb.path = strdup(path);
}
}
static void
p_udev_enumerate_v4l2(struct prober* p, struct udev* udev)
{
@ -364,9 +461,10 @@ p_udev_add_hidraw(struct prober_device* pdev,
static int
p_udev_get_usb_hid_address(struct udev_device* raw_dev,
uint32_t bus_type,
uint16_t* usb_bus,
uint16_t* usb_addr)
uint16_t* out_usb_bus,
uint16_t* out_usb_addr)
{
uint16_t dummy_vendor, dummy_product;
struct udev_device* usb_dev;
if (bus_type != HIDRAW_BUS_USB) {
@ -381,7 +479,8 @@ p_udev_get_usb_hid_address(struct udev_device* raw_dev,
return -1;
}
return p_udev_get_usb_device_address(usb_dev, usb_bus, usb_addr);
return p_udev_get_usb_device_info(
usb_dev, &dummy_vendor, &dummy_product, out_usb_bus, out_usb_addr);
}
static int
@ -496,9 +595,7 @@ p_udev_try_usb_relation_get_address(struct udev_device* raw_dev,
uint16_t* out_usb_bus,
uint16_t* out_usb_addr)
{
uint16_t vendor_id, product_id, usb_bus, usb_addr;
struct udev_device *parent_dev, *usb_interface, *usb_device;
int ret;
parent_dev = udev_device_get_parent(raw_dev);
usb_interface = udev_device_get_parent_with_subsystem_devtype(
@ -524,22 +621,9 @@ p_udev_try_usb_relation_get_address(struct udev_device* raw_dev,
return -1;
}
ret = p_udev_get_usb_device_address(usb_device, &usb_bus, &usb_addr);
if (ret != 0) {
return ret;
}
ret = p_udev_get_vendor_id_product(usb_device, &vendor_id, &product_id);
if (ret != 0) {
return ret;
}
*out_vendor_id = vendor_id;
*out_product_id = product_id;
*out_usb_bus = usb_bus;
*out_usb_addr = usb_addr;
return 0;
return p_udev_get_usb_device_info(usb_device, out_vendor_id,
out_product_id, out_usb_bus,
out_usb_addr);
}
static int
@ -567,19 +651,34 @@ p_udev_get_vendor_id_product(struct udev_device* usb_dev,
}
static int
p_udev_get_usb_device_address(struct udev_device* usb_dev,
uint16_t* out_usb_bus,
uint16_t* out_usb_addr)
p_udev_get_usb_device_info(struct udev_device* usb_dev,
uint16_t* out_vendor_id,
uint16_t* out_product_id,
uint16_t* out_usb_bus,
uint16_t* out_usb_addr)
{
uint16_t vendor_id, product_id;
int ret;
// First get the vendor and product ids.
ret = p_udev_get_vendor_id_product(usb_dev, &vendor_id, &product_id);
if (ret != 0) {
return ret;
}
// We emulate what libusb does with regards to device bus and address.
if (p_udev_get_usb_device_address_path(usb_dev, out_usb_bus,
out_usb_addr) == 0) {
*out_vendor_id = vendor_id;
*out_product_id = product_id;
return 0;
}
// If for some reason we can't read the dev path fallback to sysfs.
if (p_udev_get_usb_device_address_sysfs(usb_dev, out_usb_bus,
out_usb_addr) == 0) {
*out_vendor_id = vendor_id;
*out_product_id = product_id;
return 0;
}
@ -682,5 +781,6 @@ p_udev_dump_device(struct udev_device* udev_dev, const char* name)
fprintf(stderr, "\t\tsysnum: %s\n", udev_device_get_sysnum(udev_dev));
fprintf(stderr, "\t\tsyspath: %s\n", udev_device_get_syspath(udev_dev));
fprintf(stderr, "\t\tsubsystem: %s\n", udev_device_get_subsystem(udev_dev));
fprintf(stderr, "\t\tsysfs.product: %s\n", udev_device_get_sysattr_value(udev_dev, "product"));
// clang-format on
}