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];
42 memset(path, 0, SYSFS_PATH_MAX);
43 memset(devpath, 0, SYSFS_PATH_MAX);
44 safestrcpymax(path, dev->path, SYSFS_PATH_MAX);
45 safestrcatmax(path, "/driver", SYSFS_PATH_MAX);
46 if (!sysfs_path_is_link(path)) {
47 if (!sysfs_get_link(path, devpath, SYSFS_PATH_MAX)) {
48 if (sysfs_get_name_from_path(devpath,
49 dev->driver_name, SYSFS_NAME_LEN))
56 * Devices on on earlier kernels do not have the "driver" link.
57 * Look it up in the bus directory.
59 if (dev->bus[0] == '\0')
61 memset(path, 0, SYSFS_PATH_MAX);
62 memset(devpath, 0, SYSFS_PATH_MAX);
63 safestrcpy(path, dev->path);
64 c = strstr(path, SYSFS_DEVICES_NAME);
66 dprintf("Invalid path to device - %s\n", dev->path);
70 safestrcat(path, SYSFS_BUS_NAME);
71 safestrcat(path, "/");
72 safestrcat(path, dev->bus);
73 safestrcat(path, "/");
74 safestrcat(path, SYSFS_DRIVERS_NAME);
76 drvlist = sysfs_open_directory_list(path);
78 dlist_for_each_data(drvlist, drv, char) {
79 safestrcpy(devpath, path);
80 safestrcat(devpath, "/");
81 safestrcat(devpath, drv);
82 safestrcat(devpath, "/");
83 safestrcat(devpath, dev->bus_id);
84 if (sysfs_path_is_link(devpath) == 0) {
85 safestrcpy(dev->driver_name, drv);
86 sysfs_close_list(drvlist);
90 sysfs_close_list(drvlist);
96 * sysfs_get_device_bus: retrieves the bus name the device is on, checks path
97 * to bus' link to make sure it has correct device.
98 * @dev: device to get busname.
99 * returns 0 with success and -1 with error.
101 int sysfs_get_device_bus(struct sysfs_device *dev)
103 char devpath[SYSFS_PATH_MAX];
104 char subsys[SYSFS_NAME_LEN];
105 char path[SYSFS_PATH_MAX];
106 char target[SYSFS_PATH_MAX];
107 char *bus = NULL, *c;
108 struct dlist *buslist;
115 memset(path, 0, SYSFS_PATH_MAX);
116 memset(devpath, 0, SYSFS_PATH_MAX);
117 safestrcpymax(path, dev->path, SYSFS_PATH_MAX);
118 safestrcatmax(path, "/bus", SYSFS_PATH_MAX);
119 if (!sysfs_path_is_link(path)) {
120 if (!sysfs_get_link(path, devpath, SYSFS_PATH_MAX)) {
121 if (sysfs_get_name_from_path(devpath,
122 dev->bus, SYSFS_NAME_LEN))
129 * Devices on on earlier kernels do not have the "bus" link.
130 * Look it up in the bus directory.
132 memset(subsys, 0, SYSFS_NAME_LEN);
133 safestrcpy(subsys, dev->path);
134 c = strstr(subsys, SYSFS_DEVICES_NAME);
136 dprintf("Invalid path to device - %s\n", dev->path);
140 safestrcat(subsys, SYSFS_BUS_NAME);
141 buslist = sysfs_open_directory_list(subsys);
143 dlist_for_each_data(buslist, bus, char) {
144 memset(path, 0, SYSFS_PATH_MAX);
145 safestrcpy(path, subsys);
146 safestrcat(path, "/");
147 safestrcat(path, bus);
148 safestrcat(path, "/");
149 safestrcat(path, SYSFS_DEVICES_NAME);
150 safestrcat(path, "/");
151 safestrcat(path, dev->bus_id);
152 if ((sysfs_path_is_link(path)) == 0) {
153 memset(target, 0, SYSFS_PATH_MAX);
154 if (sysfs_get_link(path, target,
156 dprintf("Error getting link target\n");
157 sysfs_close_list(buslist);
160 if (!(strncmp(target, dev->path,
162 safestrcpy(dev->bus, bus);
163 sysfs_close_list(buslist);
168 sysfs_close_list(buslist);
174 * sysfs_close_device_tree: closes every device in the supplied tree,
175 * closing children only.
176 * @devroot: device root of tree.
178 void sysfs_close_device_tree(struct sysfs_device *devroot)
181 if (devroot->children) {
182 struct sysfs_device *child = NULL;
184 dlist_for_each_data(devroot->children, child,
185 struct sysfs_device) {
186 sysfs_close_device_tree(child);
189 sysfs_close_device(devroot);
194 * sysfs_close_device: closes and cleans up a device
195 * @dev = device to clean up
197 void sysfs_close_device(struct sysfs_device *dev)
201 sysfs_close_device(dev->parent);
202 if (dev->children && dev->children->count)
203 dlist_destroy(dev->children);
205 dlist_destroy(dev->attrlist);
211 * alloc_device: allocates and initializes device structure
212 * returns struct sysfs_device
214 static struct sysfs_device *alloc_device(void)
216 return (struct sysfs_device *) calloc(1, sizeof(struct sysfs_device));
220 * sysfs_open_device_path: opens and populates device structure
221 * @path: path to device, this is the /sys/devices/ path
222 * returns sysfs_device structure with success or NULL with error
224 struct sysfs_device *sysfs_open_device_path(const char *path)
226 struct sysfs_device *dev;
232 if (sysfs_path_is_dir(path)) {
233 dprintf("Incorrect path to device: %s\n", path);
236 dev = alloc_device();
238 dprintf("Error allocating device at %s\n", path);
241 if (sysfs_get_name_from_path(path, dev->bus_id, SYSFS_NAME_LEN)) {
243 dprintf("Error getting device bus_id\n");
244 sysfs_close_device(dev);
247 safestrcpy(dev->path, path);
248 if (sysfs_remove_trailing_slash(dev->path)) {
249 dprintf("Invalid path to device %s\n", dev->path);
250 sysfs_close_device(dev);
254 * The "name" attribute no longer exists... return the device's
255 * sysfs representation instead, in the "dev->name" field, which
256 * implies that the dev->name and dev->bus_id contain same data.
258 safestrcpy(dev->name, dev->bus_id);
260 if (sysfs_get_device_bus(dev))
261 dprintf("Could not get device bus\n");
263 if (get_dev_driver(dev)) {
264 dprintf("Could not get device %s's driver\n", dev->bus_id);
265 safestrcpy(dev->driver_name, SYSFS_UNKNOWN);
272 * sysfs_get_device_attr: searches dev's attributes by name
273 * @dev: device to look through
274 * @name: attribute name to get
275 * returns sysfs_attribute reference with success or NULL with error.
277 struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev,
284 return get_attribute(dev, (char *)name);
288 * sysfs_get_device_attributes: gets list of device attributes
289 * @dev: device whose attributes list is needed
290 * returns dlist of attributes on success or NULL on error
292 struct dlist *sysfs_get_device_attributes(struct sysfs_device *dev)
298 return get_attributes_list(dev);
302 * get_device_absolute_path: looks up the bus the device is on, gets
303 * absolute path to the device
304 * @device: device for which path is needed
305 * @path: buffer to store absolute path
306 * @psize: size of "path"
307 * Returns 0 on success -1 on failure
309 static int get_device_absolute_path(const char *device, const char *bus,
310 char *path, size_t psize)
312 char bus_path[SYSFS_PATH_MAX];
314 if (!device || !path) {
319 memset(bus_path, 0, SYSFS_PATH_MAX);
320 if (sysfs_get_mnt_path(bus_path, SYSFS_PATH_MAX)) {
321 dprintf ("Sysfs not supported on this system\n");
324 safestrcat(bus_path, "/");
325 safestrcat(bus_path, SYSFS_BUS_NAME);
326 safestrcat(bus_path, "/");
327 safestrcat(bus_path, bus);
328 safestrcat(bus_path, "/");
329 safestrcat(bus_path, SYSFS_DEVICES_NAME);
330 safestrcat(bus_path, "/");
331 safestrcat(bus_path, device);
333 * We now are at /sys/bus/"bus_name"/devices/"device" which is a link.
334 * Now read this link to reach to the device.
336 if (sysfs_get_link(bus_path, path, psize)) {
337 dprintf("Error getting to device %s\n", device);
344 * sysfs_open_device: open a device by id (use the "bus" subsystem)
345 * @bus: bus the device belongs to
346 * @bus_id: bus_id of the device to open - has to be the "bus_id" in
347 * /sys/bus/xxx/devices
348 * returns struct sysfs_device if found, NULL otherwise
350 * 1. Use sysfs_close_device to close the device
351 * 2. Bus the device is on must be supplied
352 * Use sysfs_find_device_bus to get the bus name
354 struct sysfs_device *sysfs_open_device(const char *bus, const char *bus_id)
356 char sysfs_path[SYSFS_PATH_MAX];
357 struct sysfs_device *device;
359 if (!bus_id || !bus) {
363 memset(sysfs_path, 0, SYSFS_PATH_MAX);
364 if (get_device_absolute_path(bus_id, bus, sysfs_path,
366 dprintf("Error getting to device %s\n", bus_id);
370 device = sysfs_open_device_path(sysfs_path);
372 dprintf("Error opening device %s\n", bus_id);
380 * sysfs_get_device_parent: opens up given device's parent and returns a
381 * reference to its sysfs_device
382 * @dev: sysfs_device whose parent is requested
383 * Returns sysfs_device of the parent on success and NULL on failure
385 struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev)
387 char ppath[SYSFS_PATH_MAX], *tmp;
395 return (dev->parent);
397 memset(ppath, 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);
415 * All "devices" have the "detach_state" attribute - validate here
417 safestrcat(ppath, "/detach_state");
418 if (sysfs_path_is_file(ppath)) {
419 dprintf("Device at %s does not have a parent\n", dev->path);
422 tmp = strrchr(ppath, '/');
424 dev->parent = sysfs_open_device_path(ppath);
426 dprintf("Error opening device %s's parent at %s\n",
430 return (dev->parent);