]>
git.ipfire.org Git - thirdparty/systemd.git/blob - libsysfs/sysfs_bus.c
4 * Generic bus utility functions for libsysfs
6 * Copyright (C) IBM Corp. 2003
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 static void sysfs_close_dev(void *dev
)
28 sysfs_close_device((struct sysfs_device
*)dev
);
31 static void sysfs_close_drv(void *drv
)
33 sysfs_close_driver((struct sysfs_driver
*)drv
);
37 * compares devices' bus ids.
38 * @a: device id looking for
39 * @b: sysfs_device comparing being compared
40 * returns 1 if a==b->bus_id or 0 not equal
42 static int bus_device_id_equal(void *a
, void *b
)
44 if (a
== NULL
|| b
== NULL
)
47 if (strcmp(((unsigned char *)a
), ((struct sysfs_device
*)b
)->bus_id
)
54 * compares drivers' names.
55 * @a: driver name looking for
56 * @b: sysfs_driver comparing being compared
57 * returns 1 if a==b->name or 0 not equal
59 static int bus_driver_name_equal(void *a
, void *b
)
61 if (a
== NULL
|| b
== NULL
)
64 if (strcmp(((unsigned char *)a
), ((struct sysfs_driver
*)b
)->name
) == 0)
70 * sysfs_close_bus: close single bus
73 void sysfs_close_bus(struct sysfs_bus
*bus
)
76 if (bus
->directory
!= NULL
)
77 sysfs_close_directory(bus
->directory
);
79 dlist_destroy(bus
->devices
);
81 dlist_destroy(bus
->drivers
);
87 * alloc_bus: mallocs new bus structure
88 * returns sysfs_bus_bus struct or NULL
90 static struct sysfs_bus
*alloc_bus(void)
92 return (struct sysfs_bus
*)calloc(1, sizeof(struct sysfs_bus
));
96 * sysfs_get_bus_devices: gets all devices for bus
97 * @bus: bus to get devices for
98 * returns dlist of devices with success and NULL with failure
100 struct dlist
*sysfs_get_bus_devices(struct sysfs_bus
*bus
)
102 struct sysfs_device
*bdev
= NULL
;
103 struct sysfs_directory
*devdir
= NULL
;
104 struct sysfs_link
*curl
= NULL
;
105 unsigned char path
[SYSFS_PATH_MAX
];
111 memset(path
, 0, SYSFS_PATH_MAX
);
112 strcpy(path
, bus
->path
);
114 strcat(path
, SYSFS_DEVICES_NAME
);
115 devdir
= sysfs_open_directory(path
);
119 if (sysfs_read_dir_links(devdir
) != 0) {
120 sysfs_close_directory(devdir
);
124 if (devdir
->links
!= 0) {
125 dlist_for_each_data(devdir
->links
, curl
, struct sysfs_link
) {
126 bdev
= sysfs_open_device_path(curl
->target
);
128 dprintf("Error opening device at %s\n",
132 if (bus
->devices
== NULL
)
133 bus
->devices
= dlist_new_with_delete
134 (sizeof(struct sysfs_device
),
136 dlist_unshift(bus
->devices
, bdev
);
139 sysfs_close_directory(devdir
);
141 return (bus
->devices
);
145 * sysfs_get_bus_drivers: get all pci drivers
146 * @bus: pci bus to add drivers to
147 * returns dlist of drivers with success and NULL with error
149 struct dlist
*sysfs_get_bus_drivers(struct sysfs_bus
*bus
)
151 struct sysfs_driver
*driver
= NULL
;
152 struct sysfs_directory
*drvdir
= NULL
;
153 struct sysfs_directory
*cursub
= NULL
;
154 unsigned char path
[SYSFS_PATH_MAX
];
160 memset(path
, 0, SYSFS_PATH_MAX
);
161 strcpy(path
, bus
->path
);
163 strcat(path
, SYSFS_DRIVERS_NAME
);
164 drvdir
= sysfs_open_directory(path
);
168 if (sysfs_read_dir_subdirs(drvdir
) != 0) {
169 sysfs_close_directory(drvdir
);
172 if (drvdir
->subdirs
!= NULL
) {
173 dlist_for_each_data(drvdir
->subdirs
, cursub
,
174 struct sysfs_directory
) {
175 driver
= sysfs_open_driver_path(cursub
->path
);
176 if (driver
== NULL
) {
177 dprintf("Error opening driver at %s\n",
181 if (bus
->drivers
== NULL
)
182 bus
->drivers
= dlist_new_with_delete
183 (sizeof(struct sysfs_driver
),
185 dlist_unshift(bus
->drivers
, driver
);
188 sysfs_close_directory(drvdir
);
189 return (bus
->drivers
);
193 * sysfs_open_bus: opens specific bus and all its devices on system
194 * returns sysfs_bus structure with success or NULL with error.
196 struct sysfs_bus
*sysfs_open_bus(const unsigned char *name
)
198 struct sysfs_bus
*bus
= NULL
;
199 unsigned char buspath
[SYSFS_PATH_MAX
];
206 memset(buspath
, 0, SYSFS_PATH_MAX
);
207 if ((sysfs_get_mnt_path(buspath
, SYSFS_PATH_MAX
)) != 0) {
208 dprintf("Sysfs not supported on this system\n");
212 strcat(buspath
, "/");
213 strcat(buspath
, SYSFS_BUS_NAME
);
214 strcat(buspath
, "/");
215 strcat(buspath
, name
);
216 if ((sysfs_path_is_dir(buspath
)) != 0) {
217 dprintf("Invalid path to bus: %s\n", buspath
);
222 dprintf("calloc failed\n");
225 strcpy(bus
->name
, name
);
226 strcpy(bus
->path
, buspath
);
227 if ((sysfs_remove_trailing_slash(bus
->path
)) != 0) {
228 dprintf("Incorrect path to bus %s\n", bus
->path
);
229 sysfs_close_bus(bus
);
237 * sysfs_get_bus_device: Get specific device on bus using device's id
238 * @bus: bus to find device on
239 * @id: bus_id for device
240 * returns struct sysfs_device reference or NULL if not found.
242 struct sysfs_device
*sysfs_get_bus_device(struct sysfs_bus
*bus
,
245 if (bus
== NULL
|| id
== NULL
) {
250 if (bus
->devices
== NULL
) {
251 bus
->devices
= sysfs_get_bus_devices(bus
);
252 if (bus
->devices
== NULL
)
256 return (struct sysfs_device
*)dlist_find_custom(bus
->devices
, id
,
257 bus_device_id_equal
);
261 * sysfs_get_bus_driver: Get specific driver on bus using driver name
262 * @bus: bus to find driver on
263 * @drvname: name of driver
264 * returns struct sysfs_driver reference or NULL if not found.
266 struct sysfs_driver
*sysfs_get_bus_driver(struct sysfs_bus
*bus
,
267 unsigned char *drvname
)
269 if (bus
== NULL
|| drvname
== NULL
) {
274 if (bus
->drivers
== NULL
) {
275 bus
->drivers
= sysfs_get_bus_drivers(bus
);
276 if (bus
->drivers
== NULL
)
280 return (struct sysfs_driver
*)dlist_find_custom(bus
->drivers
, drvname
,
281 bus_driver_name_equal
);
285 * sysfs_get_bus_attributes: returns bus' dlist of attributes
286 * @bus: bus to get attributes for.
287 * returns dlist of attributes or NULL if there aren't any.
289 struct dlist
*sysfs_get_bus_attributes(struct sysfs_bus
*bus
)
294 if (bus
->directory
== NULL
) {
295 bus
->directory
= sysfs_open_directory(bus
->path
);
296 if (bus
->directory
== NULL
)
299 if (bus
->directory
->attributes
== NULL
) {
300 if ((sysfs_read_dir_attributes(bus
->directory
)) != 0)
303 return bus
->directory
->attributes
;
307 * sysfs_refresh_bus_attributes: refreshes the bus's list of attributes
308 * @bus: sysfs_bus whose attributes to refresh
310 * NOTE: Upon return, prior references to sysfs_attributes for this bus
313 * Returns list of attributes on success and NULL on failure
315 struct dlist
*sysfs_refresh_bus_attributes(struct sysfs_bus
*bus
)
322 if (bus
->directory
== NULL
)
323 return (sysfs_get_bus_attributes(bus
));
325 if ((sysfs_refresh_dir_attributes(bus
->directory
)) != 0) {
326 dprintf("Error refreshing bus attributes\n");
330 return (bus
->directory
->attributes
);
334 * sysfs_get_bus_attribute: gets a specific bus attribute, if buses had
336 * @bus: bus to retrieve attribute from
337 * @attrname: attribute name to retrieve
338 * returns reference to sysfs_attribute if found or NULL if not found
340 struct sysfs_attribute
*sysfs_get_bus_attribute(struct sysfs_bus
*bus
,
341 unsigned char *attrname
)
343 struct dlist
*attrlist
= NULL
;
349 attrlist
= sysfs_get_bus_attributes(bus
);
350 if (attrlist
== NULL
)
353 return sysfs_get_directory_attribute(bus
->directory
, attrname
);
357 * sysfs_open_bus_device: locates a device on a bus and returns it. Device
358 * must be closed using sysfs_close_device.
359 * @busname: Name of bus to search
360 * @dev_id: Id of device on bus.
361 * returns sysfs_device if found or NULL if not.
363 struct sysfs_device
*sysfs_open_bus_device(unsigned char *busname
,
364 unsigned char *dev_id
)
366 struct sysfs_device
*rdev
= NULL
;
367 char path
[SYSFS_PATH_MAX
];
369 if (busname
== NULL
|| dev_id
== NULL
) {
374 memset(path
, 0, SYSFS_PATH_MAX
);
375 if (sysfs_get_mnt_path(path
, SYSFS_PATH_MAX
) != 0) {
376 dprintf("Error getting sysfs mount point\n");
381 strcat(path
, SYSFS_BUS_NAME
);
383 strcat(path
, busname
);
385 strcat(path
, SYSFS_DEVICES_NAME
);
387 strcat(path
, dev_id
);
389 rdev
= sysfs_open_device_path(path
);
391 dprintf("Error getting device %s on bus %s\n",
400 * sysfs_find_driver_bus: locates the bus the driver is on.
401 * @driver: name of the driver to locate
402 * @busname: buffer to copy name to
403 * @bsize: buffer size
404 * returns 0 with success, -1 with error
406 int sysfs_find_driver_bus(const unsigned char *driver
, unsigned char *busname
,
409 unsigned char subsys
[SYSFS_PATH_MAX
], *bus
= NULL
, *curdrv
= NULL
;
410 struct dlist
*buslist
= NULL
, *drivers
= NULL
;
412 if (driver
== NULL
|| busname
== NULL
) {
417 memset(subsys
, 0, SYSFS_PATH_MAX
);
419 strcpy(subsys
, SYSFS_BUS_NAME
);
420 buslist
= sysfs_open_subsystem_list(subsys
);
421 if (buslist
!= NULL
) {
422 dlist_for_each_data(buslist
, bus
, char) {
423 memset(subsys
, 0, SYSFS_PATH_MAX
);
425 strcpy(subsys
, SYSFS_BUS_NAME
);
429 strcat(subsys
, SYSFS_DRIVERS_NAME
);
430 drivers
= sysfs_open_subsystem_list(subsys
);
431 if (drivers
!= NULL
) {
432 dlist_for_each_data(drivers
, curdrv
, char) {
433 if (strcmp(driver
, curdrv
) == 0) {
434 strncpy(busname
, bus
, bsize
);
435 sysfs_close_list(drivers
);
436 sysfs_close_list(buslist
);
440 sysfs_close_list(drivers
);
443 sysfs_close_list(buslist
);