4 * Generic class utility functions for libsysfs
6 * Copyright (C) 2003 International Business Machines, Inc.
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 * sysfs_close_class_device: closes a single class device.
28 * @dev: class device to close.
30 void sysfs_close_class_device(struct sysfs_class_device *dev)
33 if (dev->directory != NULL)
34 sysfs_close_directory(dev->directory);
35 if (dev->sysdevice != NULL)
36 sysfs_close_device(dev->sysdevice);
37 if (dev->driver != NULL)
38 sysfs_close_driver(dev->driver);
44 * sysfs_close_class: close single class
45 * @class: class structure
47 void sysfs_close_class(struct sysfs_class *cls)
49 struct sysfs_class_device *cur = NULL, *next = NULL;
52 if (cls->directory != NULL)
53 sysfs_close_directory(cls->directory);
54 for (cur = cls->devices; cur != NULL; cur = next) {
56 sysfs_close_class_device(cur);
63 * alloc_class_device: mallocs and initializes new class device struct.
64 * returns sysfs_class_device or NULL.
66 static struct sysfs_class_device *alloc_class_device(void)
68 return (struct sysfs_class_device *)
69 calloc(1, sizeof(struct sysfs_class_device));
73 * alloc_class: mallocs new class structure
74 * returns sysfs_class struct or NULL
76 static struct sysfs_class *alloc_class(void)
78 return (struct sysfs_class *)calloc(1, sizeof(struct sysfs_class));
82 * open_class_dir: opens up sysfs class directory
83 * returns sysfs_directory struct with success and NULL with error
85 static struct sysfs_directory *open_class_dir(const char *name)
87 struct sysfs_directory *classdir = NULL;
88 char classpath[SYSFS_PATH_MAX];
95 memset(classpath, 0, SYSFS_PATH_MAX);
96 if ((sysfs_get_mnt_path(classpath, SYSFS_PATH_MAX)) != 0) {
97 dprintf(stderr, "Sysfs not supported on this system\n");
101 strcat(classpath, SYSFS_CLASS_DIR);
102 strcat(classpath, "/");
103 strcat(classpath, name);
104 classdir = sysfs_open_directory(classpath);
105 if (classdir == NULL) {
107 dprintf(stderr,"Class %s not supported on this system\n",
111 if ((sysfs_read_directory(classdir)) != 0) {
112 dprintf(stderr, "Error reading %s class dir %s\n", name,
114 sysfs_close_directory(classdir);
122 * sysfs_open_class_device: Opens and populates class device
123 * @path: path to class device.
124 * returns struct sysfs_class_device with success and NULL with error.
126 struct sysfs_class_device *sysfs_open_class_device(const char *path)
128 struct sysfs_class_device *cdev = NULL;
129 struct sysfs_directory *dir = NULL, *cur = NULL;
130 struct sysfs_dlink *curl = NULL;
131 struct sysfs_device *sdev = NULL;
132 struct sysfs_driver *drv = NULL;
133 char temp[SYSFS_NAME_LEN];
139 cdev = alloc_class_device();
144 memset(temp, 0, SYSFS_NAME_LEN);
145 if ((sysfs_get_name_from_path(path, temp, SYSFS_NAME_LEN)) != 0) {
147 dprintf(stderr, "Invalid class device path %s\n", path);
148 sysfs_close_class_device(cdev);
151 strcpy(cdev->name, temp);
153 dir = sysfs_open_directory(path);
155 dprintf(stderr, "Error opening class device at %s\n", path);
156 sysfs_close_class_device(cdev);
159 if ((sysfs_read_directory(dir)) != 0) {
160 dprintf(stderr, "Error reading class device at %s\n", path);
161 sysfs_close_directory(dir);
162 sysfs_close_class_device(cdev);
165 cdev->directory = dir;
167 cur = cdev->directory->subdirs;
169 sysfs_read_directory(cur);
172 /* get driver and device, if implemented */
173 curl = cdev->directory->links;
174 while (curl != NULL) {
175 if (strncmp(curl->name, SYSFS_DEVICES_NAME, 6) == 0) {
176 sdev = sysfs_open_device(curl->target->path);
178 cdev->sysdevice = sdev;
179 if (cdev->driver != NULL)
180 sdev->driver = cdev->driver;
182 } else if (strncmp(curl->name, SYSFS_DRIVERS_NAME, 6) == 0) {
183 drv = sysfs_open_driver(curl->target->path);
186 if (cdev->sysdevice != NULL)
187 drv->device = cdev->sysdevice;
196 * add_dev_to_class: adds a class device to class list
197 * @class: class to add the device
198 * @dev: device to add
200 static void add_dev_to_class(struct sysfs_class *cls,
201 struct sysfs_class_device *dev)
203 if (cls != NULL && dev != NULL) {
204 dev->next = cls->devices;
210 * get_all_class_devices: gets all devices for class
211 * @class: class to get devices for
212 * returns 0 with success and -1 with failure
214 static int get_all_class_devices(struct sysfs_class *cls)
216 struct sysfs_class_device *dev = NULL;
217 struct sysfs_directory *cur = NULL, *next = NULL;
219 if (cls == NULL || cls->directory == NULL) {
223 for (cur = cls->directory->subdirs; cur != NULL; cur = next) {
225 dev = sysfs_open_class_device(cur->path);
227 dprintf(stderr, "Error opening device at %s\n",
231 add_dev_to_class(cls, dev);
238 * sysfs_open_class: opens specific class and all its devices on system
239 * returns sysfs_class structure with success or NULL with error.
241 struct sysfs_class *sysfs_open_class(const char *name)
243 struct sysfs_class *cls = NULL;
244 struct sysfs_directory *classdir = NULL;
256 strcpy(cls->name, name);
257 classdir = open_class_dir(name);
258 if (classdir == NULL) {
260 "Invalid class, %s not supported on this system\n",
262 sysfs_close_class(cls);
265 cls->directory = classdir;
266 if ((get_all_class_devices(cls)) != 0) {
267 dprintf(stderr, "Error reading %s class devices\n", name);
268 sysfs_close_class(cls);