4 * Generic device utility functions for libsysfs
6 * Copyright (C) IBM Corp. 2003-2005
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
27 * get_dev_driver: fills in the dev->driver_name field
28 * Returns 0 on SUCCESS and -1 on error
30 static int get_dev_driver(struct sysfs_device *dev)
32 struct dlist *drvlist;
33 char path[SYSFS_PATH_MAX];
34 char devpath[SYSFS_PATH_MAX];
41 memset(path, 0, SYSFS_PATH_MAX);
42 memset(devpath, 0, SYSFS_PATH_MAX);
43 safestrcpymax(path, dev->path, SYSFS_PATH_MAX);
44 safestrcatmax(path, "/driver", SYSFS_PATH_MAX);
45 if (!sysfs_path_is_link(path)) {
46 if (!sysfs_get_link(path, devpath, SYSFS_PATH_MAX)) {
47 if (sysfs_get_name_from_path(devpath,
48 dev->driver_name, SYSFS_NAME_LEN))
55 * Devices on earlier kernels do not have the "driver" link.
56 * Look it up in the bus directory.
58 if (dev->bus[0] == '\0')
60 memset(path, 0, SYSFS_PATH_MAX);
61 memset(devpath, 0, SYSFS_PATH_MAX);
62 safestrcpy(path, dev->path);
63 c = strstr(path, SYSFS_DEVICES_NAME);
65 dprintf("Invalid path to device - %s\n", dev->path);
69 safestrcat(path, SYSFS_BUS_NAME);
70 safestrcat(path, "/");
71 safestrcat(path, dev->bus);
72 safestrcat(path, "/");
73 safestrcat(path, SYSFS_DRIVERS_NAME);
75 drvlist = sysfs_open_directory_list(path);
77 dlist_for_each_data(drvlist, drv, char) {
78 safestrcpy(devpath, path);
79 safestrcat(devpath, "/");
80 safestrcat(devpath, drv);
81 safestrcat(devpath, "/");
82 safestrcat(devpath, dev->bus_id);
83 if (!sysfs_path_is_link(devpath)) {
84 safestrcpy(dev->driver_name, drv);
85 sysfs_close_list(drvlist);
89 sysfs_close_list(drvlist);
95 * sysfs_get_device_bus: retrieves the bus name the device is on, checks path
96 * to bus' link to make sure it has correct device.
97 * @dev: device to get busname.
98 * returns 0 with success and -1 with error.
100 int sysfs_get_device_bus(struct sysfs_device *dev)
102 char devpath[SYSFS_PATH_MAX];
103 char subsys[SYSFS_NAME_LEN];
104 char path[SYSFS_PATH_MAX];
105 char target[SYSFS_PATH_MAX];
106 char *bus = NULL, *c;
107 struct dlist *buslist;
114 memset(path, 0, SYSFS_PATH_MAX);
115 memset(devpath, 0, SYSFS_PATH_MAX);
116 safestrcpymax(path, dev->path, SYSFS_PATH_MAX);
117 safestrcatmax(path, "/bus", SYSFS_PATH_MAX);
118 if (!sysfs_path_is_link(path)) {
119 if (!sysfs_get_link(path, devpath, SYSFS_PATH_MAX)) {
120 if (sysfs_get_name_from_path(devpath,
121 dev->bus, SYSFS_NAME_LEN))
128 * Devices on on earlier kernels do not have the "bus" link.
129 * Look it up in the bus directory.
131 memset(subsys, 0, SYSFS_NAME_LEN);
132 safestrcpy(subsys, dev->path);
133 c = strstr(subsys, SYSFS_DEVICES_NAME);
135 dprintf("Invalid path to device - %s\n", dev->path);
139 safestrcat(subsys, SYSFS_BUS_NAME);
140 buslist = sysfs_open_directory_list(subsys);
142 dlist_for_each_data(buslist, bus, char) {
143 memset(path, 0, SYSFS_PATH_MAX);
144 safestrcpy(path, subsys);
145 safestrcat(path, "/");
146 safestrcat(path, bus);
147 safestrcat(path, "/");
148 safestrcat(path, SYSFS_DEVICES_NAME);
149 safestrcat(path, "/");
150 safestrcat(path, dev->bus_id);
151 if (!sysfs_path_is_link(path)) {
152 memset(target, 0, SYSFS_PATH_MAX);
153 if (sysfs_get_link(path, target,
155 dprintf("Error getting link target\n");
156 sysfs_close_list(buslist);
159 if (!(strncmp(target, dev->path,
161 safestrcpy(dev->bus, bus);
162 sysfs_close_list(buslist);
167 sysfs_close_list(buslist);
173 * sysfs_close_device_tree: closes every device in the supplied tree,
174 * closing children only.
175 * @devroot: device root of tree.
177 void sysfs_close_device_tree(struct sysfs_device *devroot)
180 if (devroot->children) {
181 struct sysfs_device *child = NULL;
183 dlist_for_each_data(devroot->children, child,
184 struct sysfs_device) {
185 sysfs_close_device_tree(child);
188 sysfs_close_device(devroot);
193 * sysfs_close_device: closes and cleans up a device
194 * @dev = device to clean up
196 void sysfs_close_device(struct sysfs_device *dev)
200 sysfs_close_device(dev->parent);
201 if (dev->children && dev->children->count)
202 dlist_destroy(dev->children);
204 dlist_destroy(dev->attrlist);
210 * alloc_device: allocates and initializes device structure
211 * returns struct sysfs_device
213 static struct sysfs_device *alloc_device(void)
215 return (struct sysfs_device *) calloc(1, sizeof(struct sysfs_device));
219 * sysfs_open_device_path: opens and populates device structure
220 * @path: path to device, this is the /sys/devices/ path
221 * returns sysfs_device structure with success or NULL with error
223 struct sysfs_device *sysfs_open_device_path(const char *path)
225 struct sysfs_device *dev;
231 if (sysfs_path_is_dir(path)) {
232 dprintf("Incorrect path to device: %s\n", path);
235 dev = alloc_device();
237 dprintf("Error allocating device at %s\n", path);
240 if (sysfs_get_name_from_path(path, dev->bus_id, SYSFS_NAME_LEN)) {
242 dprintf("Error getting device bus_id\n");
243 sysfs_close_device(dev);
246 safestrcpy(dev->path, path);
247 if (sysfs_remove_trailing_slash(dev->path)) {
248 dprintf("Invalid path to device %s\n", dev->path);
249 sysfs_close_device(dev);
253 * The "name" attribute no longer exists... return the device's
254 * sysfs representation instead, in the "dev->name" field, which
255 * implies that the dev->name and dev->bus_id contain same data.
257 safestrcpy(dev->name, dev->bus_id);
259 if (sysfs_get_device_bus(dev))
260 dprintf("Could not get device bus\n");
262 if (get_dev_driver(dev)) {
263 dprintf("Could not get device %s's driver\n", dev->bus_id);
264 safestrcpy(dev->driver_name, SYSFS_UNKNOWN);
271 * sysfs_get_device_attr: searches dev's attributes by name
272 * @dev: device to look through
273 * @name: attribute name to get
274 * returns sysfs_attribute reference with success or NULL with error.
276 struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev,
283 return get_attribute(dev, (char *)name);
287 * sysfs_get_device_attributes: gets list of device attributes
288 * @dev: device whose attributes list is needed
289 * returns dlist of attributes on success or NULL on error
291 struct dlist *sysfs_get_device_attributes(struct sysfs_device *dev)
297 return get_attributes_list(dev);
301 * get_device_absolute_path: looks up the bus the device is on, gets
302 * absolute path to the device
303 * @device: device for which path is needed
304 * @path: buffer to store absolute path
305 * @psize: size of "path"
306 * Returns 0 on success -1 on failure
308 static int get_device_absolute_path(const char *device, const char *bus,
309 char *path, size_t psize)
311 char bus_path[SYSFS_PATH_MAX];
313 if (!device || !path) {
318 memset(bus_path, 0, SYSFS_PATH_MAX);
319 if (sysfs_get_mnt_path(bus_path, SYSFS_PATH_MAX)) {
320 dprintf ("Sysfs not supported on this system\n");
323 safestrcat(bus_path, "/");
324 safestrcat(bus_path, SYSFS_BUS_NAME);
325 safestrcat(bus_path, "/");
326 safestrcat(bus_path, bus);
327 safestrcat(bus_path, "/");
328 safestrcat(bus_path, SYSFS_DEVICES_NAME);
329 safestrcat(bus_path, "/");
330 safestrcat(bus_path, device);
332 * We now are at /sys/bus/"bus_name"/devices/"device" which is a link.
333 * Now read this link to reach to the device.
335 if (sysfs_get_link(bus_path, path, psize)) {
336 dprintf("Error getting to device %s\n", device);
343 * sysfs_open_device: open a device by id (use the "bus" subsystem)
344 * @bus: bus the device belongs to
345 * @bus_id: bus_id of the device to open - has to be the "bus_id" in
346 * /sys/bus/xxx/devices
347 * returns struct sysfs_device if found, NULL otherwise
349 * 1. Use sysfs_close_device to close the device
350 * 2. Bus the device is on must be supplied
351 * Use sysfs_find_device_bus to get the bus name
353 struct sysfs_device *sysfs_open_device(const char *bus, const char *bus_id)
355 char sysfs_path[SYSFS_PATH_MAX];
356 struct sysfs_device *device;
358 if (!bus_id || !bus) {
362 memset(sysfs_path, 0, SYSFS_PATH_MAX);
363 if (get_device_absolute_path(bus_id, bus, sysfs_path,
365 dprintf("Error getting to device %s\n", bus_id);
369 device = sysfs_open_device_path(sysfs_path);
371 dprintf("Error opening device %s\n", bus_id);
379 * sysfs_get_device_parent: opens up given device's parent and returns a
380 * reference to its sysfs_device
381 * @dev: sysfs_device whose parent is requested
382 * Returns sysfs_device of the parent on success and NULL on failure
384 struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev)
386 char ppath[SYSFS_PATH_MAX], dpath[SYSFS_PATH_MAX], *tmp;
394 return (dev->parent);
396 memset(ppath, 0, SYSFS_PATH_MAX);
397 memset(dpath, 0, SYSFS_PATH_MAX);
398 safestrcpy(ppath, dev->path);
399 tmp = strrchr(ppath, '/');
401 dprintf("Invalid path to device %s\n", ppath);
404 if (*(tmp + 1) == '\0') {
406 tmp = strrchr(tmp, '/');
408 dprintf("Invalid path to device %s\n", ppath);
414 /* Make sure we're not at the top of the device tree */
415 sysfs_get_mnt_path(dpath, SYSFS_PATH_MAX);
416 safestrcat(dpath, "/" SYSFS_DEVICES_NAME);
417 if (strcmp(dpath, ppath) == 0) {
418 dprintf("Device at %s does not have a parent\n", dev->path);
422 dev->parent = sysfs_open_device_path(ppath);
424 dprintf("Error opening device %s's parent at %s\n",
428 return (dev->parent);