diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-01-27 21:47:39 -0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-01-27 21:47:39 -0200 |
commit | 2c2c41eb10e9ce7b7ae1550615f1fb48fbaa9e10 (patch) | |
tree | e6b5d725d369e40071b12ce19509ef218ca5f0f9 /v4l2-apps/util | |
parent | 66be1e92cb9080a37ed87cba444d46cc84ea4f9b (diff) | |
download | mediapointer-dvb-s2-2c2c41eb10e9ce7b7ae1550615f1fb48fbaa9e10.tar.gz mediapointer-dvb-s2-2c2c41eb10e9ce7b7ae1550615f1fb48fbaa9e10.tar.bz2 |
Add a small utility for retrieving sysfs bus path
From: Mauro Carvalho Chehab <mchehab@redhat.com>
Thanks to Carsten Meier <cm@trexity.de> for providing us a c++ code
snippet for USB.
This code is capable of getting the bus info for both USB and PCI
devices. This is retrieved via bus_info returned by VIDIOC_QUERYCAP.
The utility will output the following info for a usb device:
bus info = usb-0000:00:1d.7-1
bus path = /sys/devices/pci0000:00/0000:00:1d.7/usb2/2-1
And, for PCI devices, it will output:
bus info = PCI:0000:01:02.0
bus path = /sys/devices/pci0000:00/0000:00:1e.0/0000:01:02.0
Notice: This will only work for devices that uses the standard
notation for the bus info:
on PCI:
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
or
sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
on USB:
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
Priority: normal
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'v4l2-apps/util')
-rw-r--r-- | v4l2-apps/util/Makefile | 10 | ||||
-rw-r--r-- | v4l2-apps/util/v4l2_sysfs_path.c | 159 |
2 files changed, 168 insertions, 1 deletions
diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile index b80de190b..f2c4c0a38 100644 --- a/v4l2-apps/util/Makefile +++ b/v4l2-apps/util/Makefile @@ -7,7 +7,7 @@ endif CPPFLAGS += -I../include -D_GNU_SOURCE LDFLAGS += -lm -binaries = v4l2-ctl v4l2-dbg v4l2-compliance ivtv-ctl cx18-ctl +binaries = v4l2-ctl v4l2-dbg v4l2-compliance ivtv-ctl cx18-ctl v4l2_sysfs_path ifeq ($(prefix),) prefix = /usr @@ -34,6 +34,14 @@ v4l2-dbg: v4l2-dbg.o v4l2-chipids.o v4l2-dbg.o: v4l2-dbg.h v4l2-dbg-bttv.h v4l2-dbg-em28xx.h v4l2-dbg-saa7134.h +v4l2_sysfs_path.o: v4l2_sysfs_path.c ../lib/v4l2_driver.h + +v4l2_sysfs_path: v4l2_sysfs_path.o ../lib/libv4l2.a + $(CC) $^ -o $@ -lsysfs + +../lib/libv4l2.a: + $(MAKE) -C ../lib libv4l2.a + install: mkdir -p $(prefix)/bin cp $(binaries) $(prefix)/bin diff --git a/v4l2-apps/util/v4l2_sysfs_path.c b/v4l2-apps/util/v4l2_sysfs_path.c new file mode 100644 index 000000000..c2d754ed2 --- /dev/null +++ b/v4l2-apps/util/v4l2_sysfs_path.c @@ -0,0 +1,159 @@ +/* + Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@redhat.com> + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 2 of the License. + + The sysfs logic were adapted from a C++/Boost snippet code sent by + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + +#include "../lib/v4l2_driver.h" +#include <sysfs/libsysfs.h> +#include <errno.h> +#include <malloc.h> +#include <stdio.h> +#include <string.h> + +#define USB_ID "usb-" +#define PCI_ID "PCI:" +#define PCIe_ID "PCIe:" + +char *obtain_bus_sysfs_path(const char *bus_info) +{ + struct sysfs_device *pcictl = NULL; + struct sysfs_bus *bus = NULL; + struct sysfs_device *busdev = NULL; + struct dlist *busdevs = NULL; + struct sysfs_device *pdev = NULL; + char *tmp = NULL, *busname, *buspath; + int pci; + + if (!strncmp(bus_info, USB_ID, strlen(USB_ID))) { + bus_info += strlen(USB_ID); + pci = 0; + } else if (!strncmp(bus_info, PCI_ID, strlen(PCI_ID))) { + bus_info += strlen(PCI_ID); + pci = 1; + } else if (!strncmp(bus_info, PCIe_ID, strlen(PCIe_ID))) { + bus_info += strlen(PCIe_ID); + pci = 1; + } else + return NULL; + + busname = strtok(bus_info, "-"); + if (!busname) + return NULL; + + buspath = strtok(NULL, "-"); + if (!buspath && !pci) + return NULL; + + /* open bus host controller */ + pcictl = sysfs_open_device("pci", busname); + if (!pcictl) + goto err; + + /* We have all we need for PCI devices */ + if (pci) { + char *name; + + asprintf(&name, "%s", pcictl->path); + return name; + } + + /* find matching usb bus */ + bus = sysfs_open_bus("usb"); + if (!bus) + goto err; + + busdevs = sysfs_get_bus_devices(bus); + if (!busdevs) + goto err; + + dlist_for_each_data(busdevs, busdev, struct sysfs_device) { + /* compare pathes of bus host controller and + parent of enumerated bus devices */ + + pdev = sysfs_get_device_parent(busdev); + if (!pdev) + continue; + + if (!strcmp(pcictl->path, pdev->path)) + break; + } + + if (!pdev) + goto err; + + sysfs_close_device(pcictl); + pcictl = NULL; + + /* assemble bus device path */ + if (busdev) { + struct sysfs_attribute *busnumattr; + unsigned int busnum; + char *name; + + busnumattr = sysfs_get_device_attr(busdev, "busnum"); + if (!busnumattr) + goto err; + + tmp = malloc(busnumattr->len + 1); + strncpy(tmp, busnumattr->value, busnumattr->len); + tmp[busnumattr->len] = '\0'; + + if (sscanf(tmp, "%u", &busnum) != 1) + goto err; + + asprintf(&name, "%s/%d-%s", busdev->path, + busnum, buspath); + + free(tmp); + sysfs_close_bus(bus); + + return name; + } + +err: + if (tmp) + free(tmp); + if (bus) + sysfs_close_bus(bus); + if (pcictl) + sysfs_close_device(pcictl); + + return NULL; +} + +int main(void) +{ + struct v4l2_driver drv; + char *path; + + if (v4l2_open("/dev/video0", 0, &drv) < 0) { + perror("open /dev/video0"); + return -1; + } + + printf("bus info = %s\n", drv.cap.bus_info); + path = obtain_bus_sysfs_path((char *)drv.cap.bus_info); + if (path) { + printf("bus path = %s\n", path); + free(path); + } + + v4l2_close(&drv); + + return 0; +} |