int read_attr_value(struct sysfs_device *dev, const char *name, const char *format) { char attrpath[SYSFS_PATH_MAX]; struct sysfs_attribute *attr; int num = 0; int ret; snprintf(attrpath, sizeof(attrpath), "%s/%s", dev->path, name); attr = sysfs_open_attribute(attrpath); if(!attr) { err("open attr %s", attrpath); return 0; } ret = sysfs_read_attribute(attr); if(ret < 0) { err("read attr"); goto err; } ret = sscanf(attr->value, format, &num); if(ret < 1) { err("sscanf"); goto err; } err: sysfs_close_attribute(attr); return num; }
// added by zl 2011-2-12 int read_attr_string(struct sysfs_device *dev, char * string, const char * name) { char attrpath[SYSFS_PATH_MAX]; struct sysfs_attribute *attr; int ret; int len = STRING_MAXLEN; string[0] = 0; snprintf(attrpath, sizeof(attrpath), "%s/%s", dev->path, name); attr = sysfs_open_attribute(attrpath); if(!attr) { err("open attr"); return 0; } ret = sysfs_read_attribute(attr); if(ret < 0) { err("read attr"); goto err; } len = (len < attr->len? len: attr->len); if(len > 0) { memcpy(string, attr->value, len); } err: sysfs_close_attribute(attr); return 0; }
/** * sysfs_read_attribute_value: given path to attribute, return its value. * values can be up to a pagesize, if buffer is smaller the value will * be truncated. * @attrpath: sysfs path to attribute * @value: buffer to put value * @vsize: size of value buffer * returns 0 with success and -1 with error. */ int sysfs_read_attribute_value(const char *attrpath, char *value, size_t vsize) { struct sysfs_attribute *attr = NULL; size_t length = 0; if (attrpath == NULL || value == NULL || vsize == 0) { errno = EINVAL; return -1; } attr = sysfs_open_attribute(attrpath); if (attr == NULL) { dprintf("Invalid attribute path %s\n", attrpath); errno = EINVAL; return -1; } if((sysfs_read_attribute(attr)) != 0 || attr->value == NULL) { dprintf("Error reading from attribute %s\n", attrpath); sysfs_close_attribute(attr); return -1; } length = strlen(attr->value); if (length > vsize) dprintf("Value length %d is larger than supplied buffer %d\n", length, vsize); safestrcpymax(value, attr->value, vsize); sysfs_close_attribute(attr); return 0; }
/** * add_attribute: open and add attribute at path to given directory * @dev: device whose attribute is to be added * @path: path to attribute * returns pointer to attr added with success and NULL with error. */ static struct sysfs_attribute *add_attribute(void *dev, const char *path) { struct sysfs_attribute *attr; attr = sysfs_open_attribute(path); if (!attr) { dprintf("Error opening attribute %s\n", path); return NULL; } if (attr->method & SYSFS_METHOD_SHOW) { if (sysfs_read_attribute(attr)) { dprintf("Error reading attribute %s\n", path); sysfs_close_attribute(attr); return NULL; } } if (!((struct sysfs_device *)dev)->attrlist) { ((struct sysfs_device *)dev)->attrlist = dlist_new_with_delete (sizeof(struct sysfs_attribute), sysfs_del_attribute); } dlist_unshift_sorted(((struct sysfs_device *)dev)->attrlist, attr, sort_list); return attr; }
int read_attr_speed(struct sysfs_device *dev) { char attrpath[SYSFS_PATH_MAX]; struct sysfs_attribute *attr; char speed[100]; int ret; snprintf(attrpath, sizeof(attrpath), "%s/%s", dev->path, "speed"); attr = sysfs_open_attribute(attrpath); if(!attr) { err("open attr"); return 0; } ret = sysfs_read_attribute(attr); if(ret < 0) { err("read attr"); goto err; } ret = sscanf(attr->value, "%s\n", speed); if(ret < 1) { err("sscanf"); goto err; } err: sysfs_close_attribute(attr); for(int i=0; speed_strings[i].speed != NULL; i++) { if(!strcmp(speed, speed_strings[i].speed)) return speed_strings[i].num; } return USB_SPEED_UNKNOWN; }
/* only the first interface value is true! */ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) { char attrpath[SYSFS_PATH_MAX]; struct sysfs_attribute *attr; int value = 0; int rc; struct stat s; int retries = SYSFS_OPEN_RETRIES; /* This access is racy! * * Just after detach, our driver removes the sysfs * files and recreates them. * * We may try and fail to open the usbip_status of * an exported device in the (short) window where * it has been removed and not yet recreated. * * This is a bug in the interface. Nothing we can do * except work around it here by polling for the sysfs * usbip_status to reappear. */ snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status", udev->path, udev->busid, udev->bConfigurationValue, 0); while (retries > 0) { if (stat(attrpath, &s) == 0) break; if (errno != ENOENT) { dbg("stat failed: %s", attrpath); return -1; } usleep(10000); /* 10ms */ retries--; } if (retries == 0) dbg("usbip_status not ready after %d retries", SYSFS_OPEN_RETRIES); else if (retries < SYSFS_OPEN_RETRIES) dbg("warning: usbip_status ready after %d retries", SYSFS_OPEN_RETRIES - retries); attr = sysfs_open_attribute(attrpath); if (!attr) { dbg("sysfs_open_attribute failed: %s", attrpath); return -1; } rc = sysfs_read_attribute(attr); if (rc) { dbg("sysfs_read_attribute failed: %s", attrpath); sysfs_close_attribute(attr); return -1; } value = atoi(attr->value); sysfs_close_attribute(attr); return value; }
int main(int argc, char *argv[]) { struct sysfs_class *sf_class; struct sysfs_device *sf_dev; struct sysfs_class_device *sf_cdev; struct dlist *sf_cdev_list = NULL; char buffer[64]; int port; struct sysfs_attribute *sf_attr; struct sysfs_attribute *sf_part; struct dlist *sf_part_list = NULL; sf_class = sysfs_open_class("block"); if (sf_class != NULL) { sf_cdev_list = sysfs_get_class_devices(sf_class); if (sf_cdev_list != NULL) { dlist_for_each_data(sf_cdev_list, sf_cdev, struct sysfs_class_device) { sf_dev = sysfs_get_classdev_device(sf_cdev); if (sf_dev != NULL) { port = *(strstr(sf_dev->path, "/usb1/") + 8) - 48; if ((port != 1) && (port != 2)) { port = -1; } printf("%s, USB port %d\n", sf_cdev->name, port); /* size */ snprintf(buffer, 64, "%s/size", sf_cdev->path); sf_attr = sysfs_open_attribute(buffer); if (sf_attr != NULL) { if (sysfs_read_attribute(sf_attr) == 0) { printf("size: %s", sf_attr->value); } sysfs_close_attribute(sf_attr); } /* vendor */ snprintf(buffer, 64, "%s/device/vendor", sf_cdev->path); sf_attr = sysfs_open_attribute(buffer); if (sf_attr != NULL) { if (sysfs_read_attribute(sf_attr) == 0) { printf("vendor: %s", sf_attr->value); } sysfs_close_attribute(sf_attr); } /* model */ snprintf(buffer, 64, "%s/device/model", sf_cdev->path); sf_attr = sysfs_open_attribute(buffer); if (sf_attr != NULL) { if (sysfs_read_attribute(sf_attr) == 0) { printf("model: %s", sf_attr->value); } sysfs_close_attribute(sf_attr); } sf_part_list = sysfs_open_directory_list(sf_cdev->path); if (sf_part_list != NULL) { dlist_for_each_data(sf_part_list, sf_part, struct sysfs_attribute) { if (strncmp("queue", (char *) sf_part, 5) != 0) { snprintf(buffer, 64, "%s/%s/size", sf_cdev->path, sf_part); sf_attr = sysfs_open_attribute(buffer); if (sf_attr != NULL) { if (sysfs_read_attribute(sf_attr) == 0) { printf("%s - size: %s", sf_part, sf_attr->value); } sysfs_close_attribute(sf_attr); } } } }
/** * sysfs_write_attribute: write value to the attribute * @sysattr: attribute to write * @new_value: value to write * @len: length of "new_value" * returns 0 with success and -1 with error. */ int sysfs_write_attribute(struct sysfs_attribute *sysattr, const char *new_value, size_t len) { int fd; int length; if (sysattr == NULL || new_value == NULL || len == 0) { errno = EINVAL; return -1; } if (!(sysattr->method & SYSFS_METHOD_STORE)) { dprintf ("Store method not supported for attribute %s\n", sysattr->path); errno = EACCES; return -1; } if (sysattr->method & SYSFS_METHOD_SHOW) { /* * read attribute again to see if we can get an updated value */ if ((sysfs_read_attribute(sysattr)) != 0) { dprintf("Error reading attribute\n"); return -1; } if ((strncmp(sysattr->value, new_value, sysattr->len)) == 0) { dprintf("Attr %s already has the requested value %s\n", sysattr->name, new_value); return 0; } } /* * open O_WRONLY since some attributes have no "read" but only * "write" permission */ if ((fd = open(sysattr->path, O_WRONLY)) < 0) { dprintf("Error reading attribute %s\n", sysattr->path); return -1; } length = write(fd, new_value, len); if (length < 0) { dprintf("Error writing to the attribute %s - invalid value?\n", sysattr->name); close(fd); return -1; } else if ((unsigned int)length != len) { dprintf("Could not write %d bytes to attribute %s\n", len, sysattr->name); /* * since we could not write user supplied number of bytes, * restore the old value if one available */ 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. Verify first if the attribute supports reading * (show method). If it does not, do not bother */ if (sysattr->method & SYSFS_METHOD_SHOW) { if (length != sysattr->len) { sysattr->value = (char *)realloc (sysattr->value, length); sysattr->len = length; safestrcpymax(sysattr->value, new_value, length); } else { /*"length" of the new value is same as old one */ safestrcpymax(sysattr->value, new_value, length); } } close(fd); return 0; }