[devel] [gmane.linux.hotplug.devel] [code] simple udev helper for firmware loading
Anton Farygin
=?iso-8859-1?q?rider_=CE=C1_altlinux=2Ecom?=
Чт Июл 21 09:55:15 MSD 2005
А нам такое надо ?
Мне проверят не на чем... кто-то у нас firmware использует ?
Rgds,
Rider
On Wed, 20 Jul 2005 23:33:05 -0400, Bill Nottingham wrote:
> As part of the move to newer udev releases, we've been getting rid of
> various hotplug agents instead of udev rules. While some (pci, scsi, usb)
> are simple transforms, firmware loading still needs a helper.
>
> Kay asked me to pass this along, so here it is.
>
> Compile is simply:
> gcc -options_of_choice -o firmware_helper firmware_helper.c
>
> It's invoked via a udev rule as such:
>
> ACTION=="add", SUBSYSTEM=="firmware", FIRMWARE="*", \
> RUN+="/sbin/firmware_helper"
>
> Potential improvements:
> - better logging of errors
> - support for sysfs mounted somewhere other than /sys (port to libsysfs?)
>
> But it should work fine as-is. Well, barring the inevitable bugs.
>
> Bill/*
> * A simple firmware helper program.
> *
> * Copyright 2005 Red Hat, Inc.
> *
> * This software may be freely redistributed under the terms of the GNU *
> public license.
> *
> * You should have received a copy of the GNU General Public License *
> along with this program; if not, write to the Free Software * Foundation,
> Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
> */
>
> #include <errno.h>
> #include <fcntl.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <syslog.h>
> #include <unistd.h>
>
> #include <sys/stat.h>
>
> #define FIRMWARE_PATH "/lib/firmware"
>
>
> void log_err(char *firmware, int err) {
> char *driver;
>
> driver = getenv("PHYSDEVDRIVER");
> if (!driver)
> driver = "(unknown)";
> openlog("firmware_helper",LOG_PID,LOG_USER); syslog(LOG_ERR,"Loading of
> %s for %s driver failed: %s",firmware, driver, strerror(err));
> closelog();
> }
> }
> /* Set the 'loading' attribute for a firmware device.
> * 1 == currently loading
> * 0 == done loading
> * -1 == error
> */
> int set_loading(char *device, int value) {
> char *path;
> int rc;
> FILE *f;
>
> path = alloca(strlen(device)+15);
> sprintf(path,"/sys/%s/loading", device); f = fopen(path, "w");
> if (!f)
> return 1;
> rc = fprintf(f, "%d", value);
> fclose(f);
> if (rc < 0)
> return rc;
> return 0;
> }
> }
>
> int main(int argc, char **argv) {
> char *devpath, *firmware, *action;
> struct stat sbuf;
> int fw_fd, count;
> int rc;
> char *fw_path, *data_path;
> char *fw_buffer;
>
> devpath = getenv("DEVPATH");
> if (!devpath) return 0;
>
> firmware = getenv("FIRMWARE");
> if (!firmware) return 0;
>
> action = getenv("ACTION");
> if (strcmp(action,"add"))
> return 0;
>
> set_loading(devpath, 1);
>
> fw_path = malloc(strlen(FIRMWARE_PATH) + strlen(firmware) + 2); if
> (!fw_path) {
> rc = errno;
> goto out_err;
> }
> }
> sprintf(fw_path,"%s/%s", FIRMWARE_PATH, firmware); fw_fd = open(fw_path,
> O_RDONLY);
> if (fw_fd == -1) {
> rc = errno;
> goto out_err;
> }
> }
> fstat(fw_fd, &sbuf);
> fw_buffer = malloc(sbuf.st_size);
> if (!fw_buffer) {
> rc = errno;
> goto out_err;
> }
> if (read(fw_fd, fw_buffer, sbuf.st_size) != sbuf.st_size) {
> rc = errno;
> goto out_err;
> }
> close(fw_fd);
>
> data_path = malloc(strlen(devpath) + 12); if (!data_path) {
> rc = errno;
> goto out_err;
> }
> }
> sprintf(data_path,"/sys/%s/data", devpath);
>
> fw_fd = open(data_path, O_RDWR);
> if (fw_fd == -1) {
> rc = errno;
> goto out_err;
> }
> }
> count = 0;
> while (count < sbuf.st_size) {
> int c;
>
> c = write(fw_fd,fw_buffer+count,sbuf.st_size-count); if (c <= 0) {
> rc = errno;
> goto out_err;
> }
> count += c;
> }
> close(fw_fd);
> set_loading(devpath, 0);
> return 0;
> out_err:
> close(fw_fd);
> set_loading(devpath, -1);
> log_err(fw_path, rc);
> return rc;
> }
Подробная информация о списке рассылки Devel