summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormananth <mananth>2003-10-20 11:53:53 +0000
committermananth <mananth>2003-10-20 11:53:53 +0000
commit35d0758e6dc564de3c2dd1571a7455985eaf7bb6 (patch)
treebeaf56ac10fcb19af20f81b16571eed278b3ce4f
parent3e9eb3ce145daf9b79402073a461d793f69d031c (diff)
downloadsysfsutils-35d0758e6dc564de3c2dd1571a7455985eaf7bb6.tar.gz
Install headers, add read_attr routines, fix bugs in sysfs_dir.c
-rw-r--r--ChangeLog10
-rw-r--r--Makefile.am1
-rw-r--r--Makefile.in54
-rw-r--r--include/libsysfs.h6
-rw-r--r--lib/sysfs_class.c53
-rw-r--r--lib/sysfs_device.c133
-rw-r--r--lib/sysfs_dir.c84
-rw-r--r--lib/sysfs_driver.c126
8 files changed, 394 insertions, 73 deletions
diff --git a/ChangeLog b/ChangeLog
index b737a14..a034368 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,14 @@
+10/20/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com>
+ * Added code to install header files (from include dir)
+ to /usr/local/include/ directory
+ * Added "read_attr" functions for device, driver and
+ class; simplified "write_attr" handling
+ * Made sysfs_get_directory_attribute() recurse subdirs
+ * Fixed potential bugs in sysfs_dir.c
+
10/17/2003 - Daniel Stekloff <dsteklof@us.ibm.com>
- * Add "path" to device in sysfs_device structure
+ * Added "path" to device in sysfs_device structure
10/15/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com>
* Fixed bug in sysfs_block.c (initrd)
diff --git a/Makefile.am b/Makefile.am
index ead8a23..b48ca6d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,6 @@
EXTRA_DIST = docs include
SUBDIRS = lib cmd test
+include_HEADERS = include/libsysfs.h include/dlist.h
dist-hook:
rm -rf `find $(distdir)/docs -name CVS`
diff --git a/Makefile.in b/Makefile.in
index 5382b28..0510d3e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -85,21 +85,24 @@ am__quote = @am__quote@
install_sh = @install_sh@
EXTRA_DIST = docs include
SUBDIRS = lib cmd test
+include_HEADERS = include/libsysfs.h include/dlist.h
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
DIST_SOURCES =
+HEADERS = $(include_HEADERS)
+
RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \
uninstall-info-recursive all-recursive install-data-recursive \
install-exec-recursive installdirs-recursive install-recursive \
uninstall-recursive check-recursive installcheck-recursive
-DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
- Makefile.in NEWS TODO aclocal.m4 config.guess config.h.in \
- config.sub configure configure.ac depcomp install-sh ltmain.sh \
- missing mkinstalldirs
+DIST_COMMON = README $(include_HEADERS) AUTHORS COPYING ChangeLog \
+ INSTALL Makefile.am Makefile.in NEWS TODO aclocal.m4 \
+ config.guess config.h.in config.sub configure configure.ac \
+ depcomp install-sh ltmain.sh missing mkinstalldirs
DIST_SUBDIRS = $(SUBDIRS)
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
@@ -148,6 +151,24 @@ clean-libtool:
distclean-libtool:
-rm -f libtool
uninstall-info-am:
+includeHEADERS_INSTALL = $(INSTALL_HEADER)
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(includedir)
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f="`echo $$p | sed -e 's|^.*/||'`"; \
+ echo " $(includeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(includedir)/$$f"; \
+ $(includeHEADERS_INSTALL) $$d$$p $(DESTDIR)$(includedir)/$$f; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ f="`echo $$p | sed -e 's|^.*/||'`"; \
+ echo " rm -f $(DESTDIR)$(includedir)/$$f"; \
+ rm -f $(DESTDIR)$(includedir)/$$f; \
+ done
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
@@ -260,6 +281,7 @@ distcleancheck_listfiles = find . -type f -print
distdir: $(DISTFILES)
$(am__remove_distdir)
mkdir $(distdir)
+ $(mkinstalldirs) $(distdir)/include
@list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
@@ -350,9 +372,10 @@ distcleancheck: distclean
exit 1; } >&2
check-am: all-am
check: check-recursive
-all-am: Makefile config.h
+all-am: Makefile $(HEADERS) config.h
installdirs: installdirs-recursive
installdirs-am:
+ $(mkinstalldirs) $(DESTDIR)$(includedir)
install: install-recursive
install-exec: install-exec-recursive
@@ -395,7 +418,7 @@ info: info-recursive
info-am:
-install-data-am:
+install-data-am: install-includeHEADERS
install-exec-am:
@@ -414,7 +437,7 @@ mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
-uninstall-am: uninstall-info-am
+uninstall-am: uninstall-includeHEADERS uninstall-info-am
uninstall-info: uninstall-info-recursive
@@ -425,14 +448,15 @@ uninstall-info: uninstall-info-recursive
distcleancheck distdir dvi dvi-am dvi-recursive info info-am \
info-recursive install install-am install-data install-data-am \
install-data-recursive install-exec install-exec-am \
- install-exec-recursive install-info install-info-am \
- install-info-recursive install-man install-recursive \
- install-strip installcheck installcheck-am installdirs \
- installdirs-am installdirs-recursive maintainer-clean \
- maintainer-clean-generic maintainer-clean-recursive mostlyclean \
- mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \
- tags tags-recursive uninstall uninstall-am uninstall-info-am \
- uninstall-info-recursive uninstall-recursive
+ install-exec-recursive install-includeHEADERS install-info \
+ install-info-am install-info-recursive install-man \
+ install-recursive install-strip installcheck installcheck-am \
+ installdirs installdirs-am installdirs-recursive \
+ maintainer-clean maintainer-clean-generic \
+ maintainer-clean-recursive mostlyclean mostlyclean-generic \
+ mostlyclean-libtool mostlyclean-recursive tags tags-recursive \
+ uninstall uninstall-am uninstall-includeHEADERS \
+ uninstall-info-am uninstall-info-recursive uninstall-recursive
dist-hook:
diff --git a/include/libsysfs.h b/include/libsysfs.h
index 819959e..980d91b 100644
--- a/include/libsysfs.h
+++ b/include/libsysfs.h
@@ -203,6 +203,8 @@ extern struct sysfs_driver *sysfs_open_driver_by_name
(const unsigned char *drv_name, const unsigned char *bus, size_t bsize);
extern int sysfs_write_driver_attr(unsigned char *drv, unsigned char *attrib,
unsigned char *value, size_t len);
+extern int sysfs_read_driver_attr(unsigned char *drv, unsigned char *attrib,
+ unsigned char *value, size_t len);
/* generic sysfs device access */
extern void sysfs_close_root_device(struct sysfs_root_device *root);
@@ -217,6 +219,8 @@ extern struct sysfs_device *sysfs_open_device_by_id
(const unsigned char *bus_id, const unsigned char *bus, size_t bsize);
extern int sysfs_write_device_attr(unsigned char *dev, unsigned char *attrib,
unsigned char *value, size_t len);
+extern int sysfs_read_device_attr(unsigned char *dev, unsigned char *attrib,
+ unsigned char *value, size_t len);
/* generic sysfs bus access */
extern void sysfs_close_bus(struct sysfs_bus *bus);
@@ -253,6 +257,8 @@ extern struct sysfs_attribute *sysfs_get_classdev_attr
(struct sysfs_class_device *clsdev, const unsigned char *name);
extern int sysfs_write_classdev_attr(unsigned char *dev, unsigned char *attrib,
unsigned char *value, size_t len);
+extern int sysfs_read_classdev_attr(unsigned char *dev, unsigned char *attrib,
+ unsigned char *value, size_t len);
/* generic sysfs block access */
extern void sysfs_close_block_device(struct sysfs_block_device *block);
diff --git a/lib/sysfs_class.c b/lib/sysfs_class.c
index 37c5243..cb6ca9d 100644
--- a/lib/sysfs_class.c
+++ b/lib/sysfs_class.c
@@ -413,7 +413,7 @@ int sysfs_find_device_class(const unsigned char *bus_id,
* @name: attribute name to get
* returns sysfs_attribute reference with success or NULL with error
*/
-struct sysfs_attribute *sysfs_get_classdev_attribute
+struct sysfs_attribute *sysfs_get_classdev_attr
(struct sysfs_class_device *clsdev, const unsigned char *name)
{
struct sysfs_attribute *cur = NULL;
@@ -438,6 +438,7 @@ struct sysfs_attribute *sysfs_get_classdev_attribute
* @dev: class device name for which the attribute has to be changed
* @attrib: attribute to change
* @value: value to change to
+ * @len: size of buffer at "value"
* Returns 0 on success and -1 on error
*/
int sysfs_write_classdev_attr(unsigned char *dev, unsigned char *attrib,
@@ -478,3 +479,53 @@ int sysfs_write_classdev_attr(unsigned char *dev, unsigned char *attrib,
sysfs_close_class_device(clsdev);
return 0;
}
+
+/**
+ * sysfs_read_classdev_attr: read an attribute for a given class device
+ * @dev: class device name for which the attribute has to be read
+ * @attrib: attribute to read
+ * @value: buffer to return value to user
+ * @len: size of buffer at "value"
+ * Returns 0 on success and -1 on error
+ */
+int sysfs_read_classdev_attr(unsigned char *dev, unsigned char *attrib,
+ unsigned char *value, size_t len)
+{
+ struct sysfs_class_device *clsdev = NULL;
+ struct sysfs_attribute *attribute = NULL;
+ unsigned char class_name[SYSFS_NAME_LEN];
+
+ if (dev == NULL || attrib == NULL || value == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(class_name, 0, SYSFS_NAME_LEN);
+ if ((sysfs_find_device_class(dev,
+ class_name, SYSFS_NAME_LEN)) < 0) {
+ dprintf("Class device %s not found\n", dev);
+ return -1;
+ }
+ clsdev = sysfs_open_class_device_by_name(class_name, dev);
+ if (clsdev == NULL) {
+ dprintf("Error opening %s in class %s\n", dev, class_name);
+ return -1;
+ }
+ attribute = sysfs_get_directory_attribute(clsdev->directory, attrib);
+ if (attribute == NULL) {
+ dprintf("Attribute %s not defined for device %s on class %s\n",
+ attrib, dev, class_name);
+ sysfs_close_class_device(clsdev);
+ return -1;
+ }
+ if (attribute->len > len) {
+ dprintf("Value length %d is greater that suppled buffer %d\n",
+ attribute->len, len);
+ sysfs_close_class_device(clsdev);
+ return -1;
+ }
+ strncpy(value, attribute->value, attribute->len);
+ value[(attribute->len)+1] = 0;
+ sysfs_close_class_device(clsdev);
+ return 0;
+}
diff --git a/lib/sysfs_device.c b/lib/sysfs_device.c
index 635ba64..89704dc 100644
--- a/lib/sysfs_device.c
+++ b/lib/sysfs_device.c
@@ -388,6 +388,51 @@ struct sysfs_device *sysfs_open_device_by_id(const unsigned char *bus_id,
}
/**
+ * get_device_absolute_path: looks up the bus the device is on, gets
+ * absolute path to the device
+ * @device: device for which path is needed
+ * @path: buffer to store absolute path
+ * @psize: size of "path"
+ * Returns 0 on success -1 on failure
+ */
+static int get_device_absolute_path(const unsigned char *device,
+ unsigned char *path, size_t psize)
+{
+ unsigned char bus_name[SYSFS_NAME_LEN], bus_path[SYSFS_PATH_MAX];
+
+ if (device == NULL || path == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(bus_name, 0, SYSFS_NAME_LEN);
+ memset(bus_path, 0, SYSFS_NAME_LEN);
+ if ((sysfs_find_device_bus(device, bus_name, SYSFS_NAME_LEN)) != 0) {
+ dprintf("Device %s not found\n", device);
+ return -1;
+ }
+ if (sysfs_get_mnt_path(bus_path, SYSFS_PATH_MAX) != 0) {
+ dprintf ("Sysfs not supported on this system\n");
+ return -1;
+ }
+ strcat(bus_path, SYSFS_BUS_DIR);
+ strcat(bus_path, "/");
+ strcat(bus_path, bus_name);
+ strcat(bus_path, SYSFS_DEVICES_DIR);
+ strcat(bus_path, "/");
+ strcat(bus_path, device);
+ /*
+ * We now are at /sys/bus/"bus_name"/devices/"device" which is a link.
+ * Now read this link to reach to the device.
+ */
+ if ((sysfs_get_link(bus_path, path, SYSFS_PATH_MAX)) != 0) {
+ dprintf("Error getting to device %s\n", device);
+ return -1;
+ }
+ return 0;
+}
+
+/**
* sysfs_write_device_attr: modify a "writable" attribute for the given device
* @dev: device bus_id for which attribute has to be changed
* @attrib: attribute to change
@@ -398,38 +443,96 @@ struct sysfs_device *sysfs_open_device_by_id(const unsigned char *bus_id,
int sysfs_write_device_attr(unsigned char *dev, unsigned char *attrib,
unsigned char *value, size_t len)
{
- struct sysfs_device *device = NULL;
struct sysfs_attribute *attribute = NULL;
- unsigned char bus_name[SYSFS_NAME_LEN];
+ unsigned char devpath[SYSFS_PATH_MAX];
if (dev == NULL || attrib == NULL || value == NULL) {
errno = EINVAL;
return -1;
}
- memset(bus_name, 0, SYSFS_NAME_LEN);
- if ((sysfs_find_device_bus(dev, bus_name, SYSFS_NAME_LEN)) != 0) {
- dprintf("Device %s not found\n", dev);
+ memset(devpath, 0, SYSFS_PATH_MAX);
+ if ((get_device_absolute_path(dev, devpath, SYSFS_PATH_MAX)) != 0) {
+ dprintf("Error finding absolute path to device %s\n", dev);
return -1;
}
- device = sysfs_open_device_by_id(dev, bus_name, SYSFS_NAME_LEN);
- if (device == NULL) {
- dprintf("Error opening device %s\n", dev);
- return -1;
- }
- attribute = sysfs_get_directory_attribute(device->directory, attrib);
+ strcat(devpath, "/");
+ strcat(devpath, attrib);
+ attribute = sysfs_open_attribute(devpath);
if (attribute == NULL) {
- dprintf("Attribute %s not defined for device %s\n",
+ dprintf("Attribute %s could not be retrieved for device %s\n",
attrib, dev);
- sysfs_close_device(device);
return -1;
}
+ if (attribute->method & SYSFS_METHOD_SHOW) {
+ if ((sysfs_read_attribute(attribute)) != 0) {
+ dprintf("Error reading attribute %s for device %s\n",
+ attrib, dev);
+ sysfs_close_attribute(attribute);
+ return -1;
+ }
+ }
if ((sysfs_write_attribute(attribute, value, len)) < 0) {
dprintf("Error setting %s to %s\n", attrib, value);
- sysfs_close_device(device);
+ sysfs_close_attribute(attribute);
return -1;
}
- sysfs_close_device(device);
+ sysfs_close_attribute(attribute);
return 0;
}
+
+/**
+ * sysfs_read_device_attr: read an attribute of the given device
+ * @dev: device bus_id for which attribute has to be changed
+ * @attrib: attribute to read
+ * @value: buffer to return value in
+ * @len: size of buffer available
+ * Returns 0 on success -1 on error
+ */
+int sysfs_read_device_attr(unsigned char *dev, unsigned char *attrib,
+ unsigned char *value, size_t len)
+{
+ struct sysfs_attribute *attribute = NULL;
+ unsigned char devpath[SYSFS_PATH_MAX];
+
+ if (dev == NULL || attrib == NULL || value == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(devpath, 0, SYSFS_PATH_MAX);
+ if ((get_device_absolute_path(dev, devpath, SYSFS_PATH_MAX)) != 0) {
+ dprintf("Error finding absolute path to device %s\n", dev);
+ return -1;
+ }
+ strcat(devpath, "/");
+ strcat(devpath, attrib);
+ attribute = sysfs_open_attribute(devpath);
+ if (attribute == NULL) {
+ dprintf("Error opening attribute %s for device %s\n",
+ attrib, dev);
+ return -1;
+ }
+ if (!(attribute->method & SYSFS_METHOD_SHOW)) {
+ dprintf("Show method not supported for attribute %s\n",
+ attrib);
+ sysfs_close_attribute(attribute);
+ return -1;
+ }
+ if ((sysfs_read_attribute(attribute)) != 0) {
+ dprintf("Error reading attribute %s for device %s\n",
+ attrib, dev);
+ sysfs_close_attribute(attribute);
+ return -1;
+ }
+ if (attribute->len > len) {
+ dprintf("Value length %d is larger than supplied buffer %d\n",
+ attribute->len, len);
+ sysfs_close_attribute(attribute);
+ return -1;
+ }
+ strncpy(value, attribute->value, attribute->len);
+ value[(attribute->len)+1] = 0;
+ sysfs_close_attribute(attribute);
+ return 0;
+}
diff --git a/lib/sysfs_dir.c b/lib/sysfs_dir.c
index 77375f0..ff2edf4 100644
--- a/lib/sysfs_dir.c
+++ b/lib/sysfs_dir.c
@@ -149,8 +149,10 @@ struct sysfs_attribute *sysfs_open_attribute(const unsigned char *path)
}
strncpy(sysattr->path, path, sizeof(sysattr->path));
if ((stat(sysattr->path, &fileinfo)) != 0) {
- dprintf("stat failed\n");
+ dprintf("Stat failed: No such attribute?\n");
sysattr->method = 0;
+ free(sysattr);
+ sysattr = NULL;
} else {
if (fileinfo.st_mode & S_IRUSR)
sysattr->method |= SYSFS_METHOD_SHOW;
@@ -211,24 +213,30 @@ int sysfs_write_attribute(struct sysfs_attribute *sysattr,
len, sysattr->name);
/*
* since we could not write user supplied number of bytes,
- * restore the old value
+ * restore the old value if one available
*/
- length = write(fd, sysattr->value, sysattr->len);
- close(fd);
- return -1;
+ if (sysattr->method & SYSFS_METHOD_SHOW) {
+ length = write(fd, sysattr->value, sysattr->len);
+ close(fd);
+ return -1;
+ }
}
/*
* Validate length that has been copied. Alloc appropriate area
- * in sysfs_attribute
+ * in sysfs_attribute. Verify first if the attribute supports reading
+ * (show method). If it does not, do not bother
*/
- if (length != sysattr->len) {
- sysattr->value = (char *)realloc(sysattr->value, length);
- sysattr->len = length;
- strncpy(sysattr->value, new_value, length);
- } else {
- /*"length" of the new value is same as old one */
- strncpy(sysattr->value, new_value, length);
+ if (sysattr->method & SYSFS_METHOD_SHOW) {
+ if (length != sysattr->len) {
+ sysattr->value = (char *)realloc(sysattr->value,
+ length);
+ sysattr->len = length;
+ strncpy(sysattr->value, new_value, length);
+ } else {
+ /*"length" of the new value is same as old one */
+ strncpy(sysattr->value, new_value, length);
+ }
}
close(fd);
@@ -582,12 +590,30 @@ int sysfs_read_directory(struct sysfs_directory *sysdir)
struct sysfs_attribute *sysfs_get_directory_attribute
(struct sysfs_directory *dir, unsigned char *attrname)
{
+ struct sysfs_directory *sdir = NULL;
+ struct sysfs_attribute *attr = NULL;
+
if (dir == NULL || attrname == NULL) {
errno = EINVAL;
return NULL;
}
- return (struct sysfs_attribute *)dlist_find_custom(dir->attributes,
+
+ attr = (struct sysfs_attribute *)dlist_find_custom(dir->attributes,
attrname, dir_attribute_name_equal);
+ if (attr != NULL)
+ return attr;
+
+ if (dir->subdirs != NULL) {
+ dlist_for_each_data(dir->subdirs, sdir,
+ struct sysfs_directory) {
+ if (sdir->attributes == NULL)
+ continue;
+ attr = sysfs_get_directory_attribute(sdir, attrname);
+ if (attr != NULL)
+ return attr;
+ }
+ }
+ return NULL;
}
/**
@@ -627,12 +653,15 @@ struct sysfs_directory *sysfs_get_subdirectory(struct sysfs_directory *dir,
if (sub != NULL)
return sub;
- dlist_for_each_data(dir->subdirs, cursub, struct sysfs_directory) {
- if (cursub->subdirs == NULL)
- continue;
- sub = sysfs_get_subdirectory(cursub, subname);
- if (sub != NULL)
- return sub;
+ if (dir->subdirs != NULL) {
+ dlist_for_each_data(dir->subdirs, cursub,
+ struct sysfs_directory) {
+ if (cursub->subdirs == NULL)
+ continue;
+ sub = sysfs_get_subdirectory(cursub, subname);
+ if (sub != NULL)
+ return sub;
+ }
}
return NULL;
}
@@ -661,12 +690,15 @@ struct sysfs_link *sysfs_get_subdirectory_link(struct sysfs_directory *dir,
if (dir->subdirs == NULL)
return NULL;
- dlist_for_each_data(dir->subdirs, cursub, struct sysfs_directory) {
- if (cursub->subdirs == NULL)
- continue;
- ln = sysfs_get_subdirectory_link(cursub, linkname);
- if (ln != NULL)
- return ln;
+ if (dir->subdirs != NULL) {
+ dlist_for_each_data(dir->subdirs, cursub,
+ struct sysfs_directory) {
+ if (cursub->subdirs == NULL)
+ continue;
+ ln = sysfs_get_subdirectory_link(cursub, linkname);
+ if (ln != NULL)
+ return ln;
+ }
}
return NULL;
}
diff --git a/lib/sysfs_driver.c b/lib/sysfs_driver.c
index 51a9107..9d331cc 100644
--- a/lib/sysfs_driver.c
+++ b/lib/sysfs_driver.c
@@ -225,6 +225,43 @@ struct sysfs_driver *sysfs_open_driver_by_name(const unsigned char *drv_name,
}
/**
+ * get_driver_path: looks up the bus the driver is on and builds path to
+ * the driver.
+ * @drv: driver to look for
+ * @path: buffer to return path to driver
+ * @psize: size of "path"
+ * Returns 0 on success and -1 on error
+ */
+static int get_driver_path(const unsigned char *drv,
+ unsigned char *path, size_t psize)
+{
+ unsigned char bus_name[SYSFS_NAME_LEN];
+
+ if (drv == NULL || path == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(bus_name, 0, SYSFS_NAME_LEN);
+ memset(path, 0, SYSFS_PATH_MAX);
+ if ((sysfs_find_driver_bus(drv, bus_name, SYSFS_NAME_LEN)) < 0) {
+ dprintf("Driver %s not found\n", drv);
+ return -1;
+ }
+ if (sysfs_get_mnt_path(path, SYSFS_PATH_MAX) != 0) {
+ dprintf("Error getting sysfs mount path\n");
+ return -1;
+ }
+ strcat(path, SYSFS_BUS_DIR);
+ strcat(path, "/");
+ strcat(path, bus_name);
+ strcat(path, SYSFS_DRIVERS_DIR);
+ strcat(path, "/");
+ strcat(path, drv);
+ fprintf(stdout, "get_driver_path %s\n", path);
+ return 0;
+}
+
+/**
* sysfs_write_driver_attr: modify "writable" driver attribute
* @drv: driver whose attribute has to be modified
* @attrib: Attribute to be modified
@@ -234,38 +271,97 @@ struct sysfs_driver *sysfs_open_driver_by_name(const unsigned char *drv_name,
int sysfs_write_driver_attr(unsigned char *drv, unsigned char *attrib,
unsigned char *value, size_t len)
{
- struct sysfs_driver *driver = NULL;
struct sysfs_attribute *attribute = NULL;
- unsigned char busname[SYSFS_NAME_LEN];
+ unsigned char path[SYSFS_PATH_MAX];
if (drv == NULL || attrib == NULL || value == NULL) {
errno = EINVAL;
return -1;
}
- memset(busname, 0, SYSFS_NAME_LEN);
- if ((sysfs_find_driver_bus(drv, busname, SYSFS_NAME_LEN)) < 0) {
- dprintf("Driver %s not found\n", drv);
- return -1;
- }
- driver = sysfs_open_driver_by_name(drv, busname, SYSFS_NAME_LEN);
- if (driver == NULL) {
- dprintf("Could not open driverr %s\n", drv);
+ memset(path, 0, SYSFS_PATH_MAX);
+ if ((get_driver_path(drv, path, SYSFS_PATH_MAX)) != 0) {
+ dprintf("Error getting to driver %s\n", drv);
return -1;
}
- attribute = sysfs_get_directory_attribute(driver->directory, attrib);
+ strcat(path, "/");
+ strcat(path, attrib);
+ attribute = sysfs_open_attribute(path);
if (attribute == NULL) {
- dprintf("Attribute %s not defined for driver %s\n",
+ dprintf("Attribute %s could not be retrieved for driver %s\n",
attrib, drv);
- sysfs_close_driver_by_name(driver);
return -1;
}
+ if (attribute->method & SYSFS_METHOD_SHOW) {
+ if ((sysfs_read_attribute(attribute)) != 0) {
+ dprintf("Error reading attribute %s for driver %s\n",
+ attrib, drv);
+ sysfs_close_attribute(attribute);
+ return -1;
+ }
+ }
if ((sysfs_write_attribute(attribute, value, len)) < 0) {
dprintf("Error setting %s to %s\n", attrib, value);
- sysfs_close_driver_by_name(driver);
+ sysfs_close_attribute(attribute);
+ return -1;
+ }
+ sysfs_close_attribute(attribute);
+ return 0;
+}
+
+/**
+ * sysfs_read_driver_attr: read the user supplied driver attribute
+ * @drv: driver whose attribute has to be read
+ * @attrib: Attribute to be read
+ * @value: Buffer to return the read value
+ * @len: Length of the buffer "value"
+ * Returns 0 on success -1 on failure
+ */
+int sysfs_read_driver_attr(unsigned char *drv, unsigned char *attrib,
+ unsigned char *value, size_t len)
+{
+ struct sysfs_attribute *attribute = NULL;
+ unsigned char busname[SYSFS_NAME_LEN], path[SYSFS_PATH_MAX];
+
+ if (drv == NULL || attrib == NULL || value == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(path, 0, SYSFS_NAME_LEN);
+ if ((get_driver_path(drv, path, SYSFS_PATH_MAX)) != 0) {
+ dprintf("Error getting to driver %s\n", drv);
+ return -1;
+ }
+ strcat(path, "/");
+ strcat(path, attrib);
+ attribute = sysfs_open_attribute(path);
+ if (attribute == NULL) {
+ dprintf("Error opening attribute %s for driver %s\n",
+ attrib, drv);
+ return -1;
+ }
+ if (!(attribute->method & SYSFS_METHOD_SHOW)) {
+ dprintf("Show method not supported for attribute %s\n",
+ attrib);
+ sysfs_close_attribute(attribute);
+ return -1;
+ }
+ if ((sysfs_read_attribute(attribute)) != 0) {
+ dprintf("Error reading attribute %s for driver %s\n",
+ attrib, drv);
+ sysfs_close_attribute(attribute);
+ return -1;
+ }
+ if (attribute->len > len) {
+ dprintf("Value length %d is larger than supplied buffer %d\n",
+ attribute->len, len);
+ sysfs_close_attribute(attribute);
return -1;
}
- sysfs_close_driver_by_name(driver);
+ strncpy(value, attribute->value, attribute->len);
+ value[(attribute->len)+1] = 0;
+ sysfs_close_attribute(attribute);
return 0;
}