+
+/**
+ * sysfs_get_bus_device: Get specific device on bus using device's id
+ * @bus: bus to find device on
+ * @id: bus_id for device
+ * returns struct sysfs_device reference or NULL if not found.
+ */
+struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus,
+ unsigned char *id)
+{
+ if (bus == NULL || id == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ return (struct sysfs_device *)dlist_find_custom(bus->devices, id,
+ bus_device_id_equal);
+}
+
+/**
+ * sysfs_get_bus_driver: Get specific driver on bus using driver name
+ * @bus: bus to find driver on
+ * @drvname: name of driver
+ * returns struct sysfs_driver reference or NULL if not found.
+ */
+struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus,
+ unsigned char *drvname)
+{
+ if (bus == NULL || drvname == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ return (struct sysfs_driver *)dlist_find_custom(bus->drivers, drvname,
+ bus_driver_name_equal);
+}
+
+/**
+ * sysfs_get_bus_attributes: returns bus' dlist of attributes
+ * @bus: bus to get attributes for.
+ * returns dlist of attributes or NULL if there aren't any.
+ */
+struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus)
+{
+ if (bus == NULL || bus->directory == NULL)
+ return NULL;
+ return bus->directory->attributes;
+}
+
+/**
+ * sysfs_get_bus_attribute: gets a specific bus attribute, if buses had
+ * attributes.
+ * @bus: bus to retrieve attribute from
+ * @attrname: attribute name to retrieve
+ * returns reference to sysfs_attribute if found or NULL if not found
+ */
+struct sysfs_attribute *sysfs_get_bus_attribute(struct sysfs_bus *bus,
+ unsigned char *attrname)
+{
+ if (bus == NULL || bus->directory == NULL || attrname == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return sysfs_get_directory_attribute(bus->directory, attrname);
+}
+
+/**
+ * sysfs_open_bus_device: locates a device on a bus and returns it. Device
+ * must be closed using sysfs_close_device.
+ * @busname: Name of bus to search
+ * @dev_id: Id of device on bus.
+ * returns sysfs_device if found or NULL if not.
+ */
+struct sysfs_device *sysfs_open_bus_device(unsigned char *busname,
+ unsigned char *dev_id)
+{
+ struct sysfs_device *rdev = NULL;
+ char path[SYSFS_PATH_MAX];
+
+ if (busname == NULL || dev_id == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ memset(path, 0, SYSFS_PATH_MAX);
+ if (sysfs_get_mnt_path(path, SYSFS_PATH_MAX) != 0) {
+ dprintf("Error getting sysfs mount point\n");
+ return NULL;
+ }
+
+ strcat(path, SYSFS_BUS_DIR);
+ strcat(path, "/");
+ strcat(path, busname);
+ strcat(path, SYSFS_DEVICES_DIR);
+ strcat(path, "/");
+ strcat(path, dev_id);
+
+ rdev = sysfs_open_device(path);
+ if (rdev == NULL) {
+ dprintf("Error getting device %s on bus %s\n",
+ dev_id, busname);
+ return NULL;
+ }
+
+ return rdev;
+}
+
+/**
+ * sysfs_find_device_bus: locates the bus a device is on.
+ * @dev_id: device id.
+ * @busname: buffer to copy name to
+ * @bsize: buffer size
+ * returns 0 with success or -1 with error
+ */
+int sysfs_find_device_bus(const unsigned char *dev_id, unsigned char *busname,
+ size_t bsize)
+{
+ unsigned char subsys[SYSFS_NAME_LEN], *bus = NULL, *curdev = NULL;
+ struct dlist *buslist = NULL, *device_list = NULL;
+
+ if (dev_id == NULL || busname == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ strcpy(subsys, SYSFS_BUS_DIR); /* subsys = /bus */
+ buslist = sysfs_open_subsystem_list(subsys);
+ if (buslist != NULL) {
+ dlist_for_each_data(buslist, bus, char) {
+ device_list = sysfs_open_bus_devices_list(bus);
+ if (device_list != NULL) {
+ dlist_for_each_data(device_list,
+ curdev, char) {
+ if (strcmp(dev_id, curdev) == 0) {
+ strncpy(busname,
+ bus, bsize);
+ sysfs_close_list(device_list);
+ sysfs_close_list(buslist);
+ return 0;
+ }
+ }
+ sysfs_close_list(device_list);
+ }
+ }
+ sysfs_close_list(buslist);
+ }
+ return -1;
+}
+
+/**
+ * sysfs_find_driver_bus: locates the bus the driver is on.
+ * @driver: name of the driver to locate
+ * @busname: buffer to copy name to
+ * @bsize: buffer size
+ * returns 0 with success, -1 with error
+ */
+int sysfs_find_driver_bus(const unsigned char *driver, unsigned char *busname,
+ size_t bsize)
+{
+ unsigned char subsys[SYSFS_PATH_MAX], *bus = NULL, *curdrv = NULL;
+ struct dlist *buslist = NULL, *drivers = NULL;
+
+ if (driver == NULL || busname == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(subsys, 0, SYSFS_PATH_MAX);
+ strcpy(subsys, SYSFS_BUS_DIR);
+ buslist = sysfs_open_subsystem_list(subsys);
+ if (buslist != NULL) {
+ dlist_for_each_data(buslist, bus, char) {
+ memset(subsys, 0, SYSFS_PATH_MAX);
+ strcpy(subsys, SYSFS_BUS_DIR);
+ strcat(subsys, "/");
+ strcat(subsys, bus);
+ strcat(subsys, SYSFS_DRIVERS_DIR);
+ drivers = sysfs_open_subsystem_list(subsys);
+ if (drivers != NULL) {
+ dlist_for_each_data(drivers, curdrv, char) {
+ if (strcmp(driver, curdrv) == 0) {
+ strncpy(busname, bus, bsize);
+ sysfs_close_list(drivers);
+ sysfs_close_list(buslist);
+ return 0;
+ }
+ }
+ sysfs_close_list(drivers);
+ }
+ }
+ sysfs_close_list(buslist);
+ }
+ return -1;
+}
+