mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
[PATCH] fix problem where usb devices can be either the main device or the interface
This fixes the bug of a long delay for mouse devices
This commit is contained in:
parent
d026a35d74
commit
bb051f6657
50
namedev.c
50
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" },
|
||||
{ .bus = "usb", .file = "iInterface" },
|
||||
{ .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;
|
||||
int loop;
|
||||
int found = 0;
|
||||
int loop = SECONDS_TO_WAIT_FOR_FILE;
|
||||
|
||||
while (1) {
|
||||
if (b->bus == NULL)
|
||||
break;
|
||||
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);
|
||||
}
|
||||
dbg("timed out waiting for '%s' file, continuing on anyway...", b->file);
|
||||
goto exit;
|
||||
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];
|
||||
}
|
||||
b++;
|
||||
if (strcmp(sysfs_device->bus, b->bus) == 0) {
|
||||
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("can't find '%s' file", b->file);
|
||||
}
|
||||
++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... */
|
||||
}
|
||||
|
200
udevtest.c
Normal file
200
udevtest.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user