chiark / gitweb /
[PATCH] fix problem where usb devices can be either the main device or the interface
authorgreg@kroah.com <greg@kroah.com>
Fri, 13 Feb 2004 03:48:07 +0000 (19:48 -0800)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 04:32:27 +0000 (21:32 -0700)
This fixes the bug of a long delay for mouse devices

namedev.c
udevtest.c [new file with mode: 0644]

index e4e585b5cd64b5676a3261a736c6b620f3a6dad5..68ca5dd306811e5b9b4de4e386d9feca9523920f 100644 (file)
--- a/namedev.c
+++ b/namedev.c
@@ -260,12 +260,17 @@ static void apply_format(struct udevice *udev, unsigned char *string)
        }
 }
 
        }
 }
 
+/* 
+ * Note, we can have multiple files for different busses in here due
+ * to the mess that USB has for its device tree...
+ */
 static struct bus_file {
        char *bus;
        char *file;
 } bus_files[] = {
        { .bus = "scsi",        .file = "vendor" },
        { .bus = "usb",         .file = "idVendor" },
 static struct bus_file {
        char *bus;
        char *file;
 } bus_files[] = {
        { .bus = "scsi",        .file = "vendor" },
        { .bus = "usb",         .file = "idVendor" },
+       { .bus = "usb",         .file = "iInterface" },
        { .bus = "usb-serial",  .file = "detach_state" },
        { .bus = "ide",         .file = "detach_state" },
        { .bus = "pci",         .file = "vendor" },
        { .bus = "usb-serial",  .file = "detach_state" },
        { .bus = "ide",         .file = "detach_state" },
        { .bus = "pci",         .file = "vendor" },
@@ -285,30 +290,35 @@ static void wait_for_device_to_initialize(struct sysfs_device *sysfs_device)
         */
        struct bus_file *b = &bus_files[0];
        struct sysfs_attribute *tmpattr;
         */
        struct bus_file *b = &bus_files[0];
        struct sysfs_attribute *tmpattr;
-       int loop;
+       int found = 0;
+       int loop = SECONDS_TO_WAIT_FOR_FILE;
 
        while (1) {
 
        while (1) {
-               if (b->bus == NULL)
-                       break;
+               if (b->bus == NULL) {
+                       if (!found)
+                               break;
+                       /* sleep to give the kernel a chance to create the file */
+                       sleep(1);
+                       --loop;
+                       if (loop == 0)
+                               break;
+                       b = &bus_files[0];
+               }
                if (strcmp(sysfs_device->bus, b->bus) == 0) {
                if (strcmp(sysfs_device->bus, b->bus) == 0) {
-                       tmpattr = NULL;
-                       loop = SECONDS_TO_WAIT_FOR_FILE;
-                       while (loop--) {
-                               dbg("looking for file '%s' on bus '%s'", b->file, b->bus);
-                               tmpattr = sysfs_get_device_attr(sysfs_device, b->file);
-                               if (tmpattr) {
-                                       /* found it! */
-                                       goto exit;
-                               }
-                               /* sleep to give the kernel a chance to create the file */
-                               sleep(1);
+                       found = 1;
+                       dbg("looking for file '%s' on bus '%s'", b->file, b->bus);
+                       tmpattr = sysfs_get_device_attr(sysfs_device, b->file);
+                       if (tmpattr) {
+                               /* found it! */
+                               goto exit;
                        }
                        }
-                       dbg("timed out waiting for '%s' file, continuing on anyway...", b->file);
-                       goto exit;
+                       dbg("can't find '%s' file", b->file);
                }
                }
-               b++;
+               ++b;
        }
        }
-       dbg("did not find bus type '%s' on list of bus_id_files, contact greg@kroah.com", sysfs_device->bus);
+       if (!found)
+               dbg("did not find bus type '%s' on list of bus_id_files, "
+                   "contact greg@kroah.com", sysfs_device->bus);
 exit:
        return; /* here to prevent compiler warning... */
 }
 exit:
        return; /* here to prevent compiler warning... */
 }
diff --git a/udevtest.c b/udevtest.c
new file mode 100644 (file)
index 0000000..9f10cc2
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * udev.c
+ *
+ * Userspace devfs
+ *
+ * Copyright (C) 2003,2004 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ *     This program is free software; you can redistribute it and/or modify it
+ *     under the terms of the GNU General Public License as published by the
+ *     Free Software Foundation version 2 of the License.
+ * 
+ *     This program is distributed in the hope that it will be useful, but
+ *     WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *     General Public License for more details.
+ * 
+ *     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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include "udev.h"
+#include "udev_version.h"
+#include "udev_dbus.h"
+#include "logging.h"
+#include "namedev.h"
+#include "udevdb.h"
+#include "libsysfs/libsysfs.h"
+
+/* global variables */
+char **main_argv;
+char **main_envp;
+
+#ifdef LOG
+unsigned char logname[42];
+void log_message (int level, const char *format, ...)
+{
+       va_list args;
+
+       if (!udev_log)
+               return;
+
+       va_start(args, format);
+       vsyslog(level, format, args);
+       va_end(args);
+}
+#endif
+
+static void sig_handler(int signum)
+{
+       switch (signum) {
+               case SIGINT:
+               case SIGTERM:
+                       sysbus_disconnect();
+                       udevdb_exit();
+                       exit(20 + signum);
+               default:
+                       dbg("unhandled signal");
+       }
+}
+
+static inline char *get_action(void)
+{
+       char *action;
+
+       action = getenv("ACTION");
+       return action;
+}
+
+static inline char *get_devpath(void)
+{
+       char *devpath;
+
+       devpath = getenv("DEVPATH");
+       return devpath;
+}
+
+static inline char *get_seqnum(void)
+{
+       char *seqnum;
+
+       seqnum = getenv("SEQNUM");
+       return seqnum;
+}
+
+static char *subsystem_blacklist[] = {
+       "net",
+       "scsi_host",
+       "scsi_device",
+       "usb_host",
+       "pci_bus",
+       "",
+};
+
+static int udev_hotplug(int argc, char **argv)
+{
+       char *action;
+       char *devpath;
+       char *subsystem;
+       int retval = -EINVAL;
+       int i;
+       struct sigaction act;
+
+       action = get_action();
+       if (!action) {
+               dbg ("no action?");
+               goto exit;
+       }
+
+       devpath = get_devpath();
+       if (!devpath) {
+               dbg ("no devpath?");
+               goto exit;
+       }
+       dbg("looking at '%s'", devpath);
+
+       /* we only care about class devices and block stuff */
+       if (!strstr(devpath, "class") &&
+           !strstr(devpath, "block")) {
+               dbg("not a block or class device");
+               goto exit;
+       }
+
+       /* skip blacklisted subsystems */
+       subsystem = argv[1];
+       i = 0;
+       while (subsystem_blacklist[i][0] != '\0') {
+               if (strcmp(subsystem, subsystem_blacklist[i]) == 0) {
+                       dbg("don't care about '%s' devices", subsystem);
+                       goto exit;
+               }
+               i++;
+       }
+
+       /* connect to the system message bus */
+       sysbus_connect();
+
+       /* initialize our configuration */
+       udev_init_config();
+
+       /* initialize udev database */
+       retval = udevdb_init(UDEVDB_DEFAULT);
+       if (retval != 0) {
+               dbg("unable to initialize database");
+               goto exit_sysbus;
+       }
+
+       /* set up a default signal handler for now */
+       act.sa_handler = sig_handler;
+       sigemptyset (&act.sa_mask);
+       act.sa_flags = SA_RESTART;
+       sigaction(SIGINT, &act, NULL);
+       sigaction(SIGTERM, &act, NULL);
+
+       /* initialize the naming deamon */
+       namedev_init();
+
+       if (strcmp(action, "add") == 0)
+               retval = udev_add_device(devpath, subsystem);
+
+       else if (strcmp(action, "remove") == 0)
+               retval = udev_remove_device(devpath, subsystem);
+
+       else {
+               dbg("unknown action '%s'", action);
+               retval = -EINVAL;
+       }
+       udevdb_exit();
+
+exit_sysbus:
+       /* disconnect from the system message bus */
+       sysbus_disconnect();
+
+exit:
+       if (retval > 0)
+               retval = 0;
+
+       return -retval;
+}
+
+int main(int argc, char **argv, char **envp)
+{
+       main_argv = argv;
+       main_envp = envp;
+
+       init_logging("udev");
+       dbg("version %s", UDEV_VERSION);
+
+       return udev_hotplug(argc, argv);
+}
+
+