Add the ability to match on device names attached to.

If a device is attached to ums4, you can reference this devname in
the configuration file as ${DEVNAME} (a shell variable, yes).
This commit is contained in:
Nick Hibma 1999-11-28 21:27:31 +00:00
parent f27f6c0076
commit 33ba9f8fee
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=53856
3 changed files with 171 additions and 34 deletions

View File

@ -9,7 +9,7 @@ device "ActiveWire board, firmware download"
vendor 0x0854
product 0x0100
release 0x0000
attach "/usr/local/bin/ezdownload -f /usr/local/share/usb/firmware/0854.0100.0_01.hex"
attach "/usr/local/bin/ezdownload -f /usr/local/share/usb/firmware/0854.0100.0_01.hex ${DEVNAME}"
# The piece below has to be copied for every drive. It does not work for the
# generic case, the umass storage class uses interface drivers. The info for
@ -19,15 +19,14 @@ device "USB Zip drive"
vendor 0x059b
product 0x0001
release 0x0100
attach "/usr/bin/camcontrol rescan bus 0"
attach "/sbin/camcontrol rescan bus 0"
# The entry below is for the Logitech mouse. Replace the product and vendor
# id (and the device name of course) with the data for your mouse.
#
device "Logitech N48 USB mouse"
vendor 0x046d
product 0xc001
attach "/usr/sbin/moused -p /dev/ums0 -I /var/run/moused.ums0.pid"
device "Mouse"
devname "ums[0-9]+"
attach "/usr/sbin/moused -p /dev/${DEVNAME} -I /var/run/moused.${DEVNAME}.pid"
# The fallthrough entry: Nothing is specified, nothing is done. And it isn't
# necessary at all :-). Just for pretty printing in debugging mode.

View File

@ -60,6 +60,7 @@
#include <sys/errno.h>
#include <sys/queue.h>
#include <sys/wait.h>
#include <regex.h>
#include <dev/usb/usb.h>
@ -121,6 +122,7 @@ event_name_t event_names[] = {
#define CLASS_FIELD 4
#define SUBCLASS_FIELD 5
#define PROTOCOL_FIELD 6
#define DEVNAME_FIELD 7
#define ATTACH_FIELD 8 /* command fields */
#define DETACH_FIELD 9
@ -135,6 +137,8 @@ typedef struct action_s {
int class;
int subclass;
int protocol;
char *devname;
regex_t devname_regex;
char *attach; /* commands to execute */
char *detach;
@ -144,6 +148,11 @@ typedef struct action_s {
STAILQ_HEAD(action_list, action_s) actions = STAILQ_HEAD_INITIALIZER(actions);
typedef struct action_match_s {
action_t *action;
char *devname;
} action_match_t;
/* the function returns 0 for failure, 1 for all arguments found and 2 for
* arguments left over in trail.
@ -158,6 +167,7 @@ int set_release_field(action_t *action, char *args, char **trail);
int set_class_field(action_t *action, char *args, char **trail);
int set_subclass_field(action_t *action, char *args, char **trail);
int set_protocol_field(action_t *action, char *args, char **trail);
int set_devname_field(action_t *action, char *args, char **trail);
int set_attach_field(action_t *action, char *args, char **trail);
int set_detach_field(action_t *action, char *args, char **trail);
@ -177,6 +187,7 @@ config_field_t config_fields[] = {
{CLASS_FIELD, "class", set_class_field},
{SUBCLASS_FIELD, "subclass", set_subclass_field},
{PROTOCOL_FIELD, "protocol", set_protocol_field},
{DEVNAME_FIELD, "devname", set_devname_field},
{ATTACH_FIELD, "attach", set_attach_field},
{DETACH_FIELD, "detach", set_detach_field},
@ -189,7 +200,8 @@ config_field_t config_fields[] = {
void print_event __P((struct usb_event *event));
void print_action __P((action_t *action, int i));
void print_actions __P((void));
action_t *find_action __P((struct usb_device_info *devinfo));
int find_action __P((struct usb_device_info *devinfo,
action_match_t *action_match));
void
@ -354,6 +366,38 @@ set_protocol_field(action_t *action, char *args, char **trail)
return(get_integer(args, &action->protocol, trail));
}
int
set_devname_field(action_t *action, char *args, char **trail)
{
int match = get_string(args, &action->devname, trail);
int len;
int error;
char *string;
# define ERRSTR_SIZE 100
char errstr[ERRSTR_SIZE];
if (match == 0)
return(0);
len = strlen(action->devname);
string = malloc(len + 14);
if (string == NULL)
return(0);
bcopy(action->devname, string+7, len); /* make some space for */
bcopy("[[:<:]]", string, 7); /* beginning of word */
bcopy("[[:>:]]", string+7+len, 7); /* and end of word */
error = regcomp(&action->devname_regex, string, REG_NOSUB|REG_EXTENDED);
if (error) {
errstr[0] = '\0';
regerror(error, &action->devname_regex, errstr, ERRSTR_SIZE);
fprintf(stderr, "%s:%d: %s\n", configfile, lineno, errstr);
return(0);
}
return(match);
}
int
set_attach_field(action_t *action, char *args, char **trail)
{
return(get_string(args, &action->attach, trail));
@ -468,6 +512,7 @@ read_configuration(void)
action->class = WILDCARD_INT;
action->subclass = WILDCARD_INT;
action->protocol = WILDCARD_INT;
action->devname = WILDCARD_STRING;
/* Add it to the end of the list to preserve order */
STAILQ_INSERT_TAIL(&actions, action, next);
@ -534,6 +579,20 @@ print_event(struct usb_event *event)
"clss=0x%04x subclss=0x%04x prtcl=0x%04x\n",
devinfo->vendorNo, devinfo->productNo, devinfo->releaseNo,
devinfo->class, devinfo->subclass, devinfo->protocol);
if (devinfo->devnames[0][0] != '\0') {
char c = ' ';
printf(" device names:");
for (i = 0; i < MAXDEVNAMES; i++) {
if (devinfo->devnames[i][0] == '\0')
break;
printf("%c%s", c, devinfo->devnames[i]);
c = ',';
}
printf("\n");
}
}
void
@ -571,13 +630,15 @@ print_action(action_t *action, int i)
action->subclass != WILDCARD_INT ||
action->protocol != WILDCARD_INT)
printf("\n");
if (action->devname != WILDCARD_STRING)
printf(" devname: %s\n", action->devname);
if (action->attach != NULL)
printf("%s: attach='%s'\n",
__progname, action->attach);
printf(" attach='%s'\n",
action->attach);
if (action->detach != NULL)
printf("%s: detach='%s'\n",
__progname, action->detach);
printf(" detach='%s'\n",
action->detach);
}
void
@ -592,10 +653,38 @@ print_actions()
printf("%s: %d action%s\n", __progname, i, (i == 1? "":"s"));
}
action_t *
find_action(struct usb_device_info *devinfo)
int
match_devname(action_t *action, struct usb_device_info *devinfo)
{
int i;
regmatch_t match;
int error;
for (i = 0; i < MAXDEVNAMES; i++) {
if (devinfo->devnames[i][0] == '\0')
break;
error = regexec(&action->devname_regex, devinfo->devnames[i],
1, &match, 0);
if (error == 0) {
if (verbose >= 2)
printf("%s: %s matches %s\n", __progname,
devinfo->devnames[i], action->devname);
return(i);
}
}
return(-1);
}
int
find_action(struct usb_device_info *devinfo, action_match_t *action_match)
{
action_t *action;
char *devname = NULL;
int match = -1;
STAILQ_FOREACH(action, &actions, next) {
if ((action->vendor == WILDCARD_INT ||
@ -609,24 +698,40 @@ find_action(struct usb_device_info *devinfo)
(action->subclass == WILDCARD_INT ||
action->subclass == devinfo->subclass) &&
(action->protocol == WILDCARD_INT ||
action->protocol == devinfo->protocol)) {
action->protocol == devinfo->protocol) &&
(action->devname == WILDCARD_STRING ||
(match = match_devname(action, devinfo)) != -1)) {
/* found match !*/
if (verbose)
printf("%s: Found action '%s' for %s, %s\n",
if (match != -1)
devname = devinfo->devnames[match];
else if (devinfo->devnames[0][0] != '\0' &&
devinfo->devnames[1][0] == '\0')
/* if we have exactly 1 device name */
devname = devinfo->devnames[0];
if (verbose) {
printf("%s: Found action '%s' for %s, %s",
__progname, action->name,
devinfo->product, devinfo->vendor);
return(action);
if (devname)
printf(" at %s", devname);
printf("\n");
}
action_match->action = action;
action_match->devname = devname;
return(1);
}
}
return NULL;
return(0);
}
void
execute_command(char *cmd)
{
pid_t pid;
int pstat;
struct sigaction ign, intact, quitact;
sigset_t newsigblock, oldsigblock;
int status;
@ -671,11 +776,12 @@ execute_command(char *cmd)
execl(_PATH_BSHELL, "sh", "-c", cmd, (char *)NULL);
/* should only be reached in case of error */
exit(127);
} else {
/* parent here */
do {
pid = waitpid(pid, &pstat, 0);
pid = waitpid(pid, &status, 0);
} while (pid == -1 && errno == EINTR);
}
(void) sigaction(SIGINT, &intact, NULL);
@ -701,8 +807,8 @@ execute_command(char *cmd)
} else if (WIFSIGNALED(status)) {
fprintf(stderr, "%s: '%s' caught signal %d\n",
__progname, cmd, WTERMSIG(status));
} else if (verbose) {
printf("%s: '%s' is done\n", __progname, cmd);
} else if (verbose >= 2) {
printf("%s: '%s' is ok\n", __progname, cmd);
}
}
}
@ -711,8 +817,9 @@ void
process_event_queue(int fd)
{
struct usb_event event;
int error;
int len;
action_t *action;
action_match_t action_match;
for (;;) {
len = read(fd, &event, sizeof(event));
@ -742,16 +849,28 @@ process_event_queue(int fd)
switch (event.ue_type) {
case USB_EVENT_ATTACH:
case USB_EVENT_DETACH:
action = find_action(&event.ue_device);
if (action == NULL)
if (find_action(&event.ue_device, &action_match) == 0)
/* nothing found */
break;
else if (verbose >= 2)
print_action(action, 0);
if (event.ue_type == USB_EVENT_ATTACH && action->attach)
execute_command(action->attach);
if (event.ue_type == USB_EVENT_DETACH && action->detach)
execute_command(action->detach);
if (verbose >= 2)
print_action(action_match.action, 0);
if (action_match.devname) {
if (verbose >= 2)
printf("%s: Setting DEVNAME='%s'\n",
__progname, action_match.devname);
error = setenv("DEVNAME", action_match.devname, 1);
if (error)
fprintf(stderr, "%s: setenv(\"DEVNAME\", \"%s\",1) failed, %s\n",
__progname, action_match.devname, strerror(errno));
}
if (event.ue_type == USB_EVENT_ATTACH && action_match.action->attach)
execute_command(action_match.action->attach);
if (event.ue_type == USB_EVENT_DETACH && action_match.action->detach)
execute_command(action_match.action->detach);
break;
default:

View File

@ -77,8 +77,14 @@ Device Class
Device Subclass
.It protocol Ar id
Device Protocol
.It devicenames Ar string
Device name, for example umass2, or ums0.
.It devname Ar string
Device name, for example umass2, or ums0. These device names can contain
regular expressions. See
.Xr regex 3
and
.Xr re_format 7 .
The device name that is matched can be used in the commands below
through adding ${DEVNAME} somewhere in that string.
.El
.Pp
String arguments may be quoted. If a string argument contains a space or
@ -102,9 +108,15 @@ and
.Fl -v
flags.
.Pp
Commands to be executed when the action is matched:
.Bl -tag -width devicename\ <Id>
.It attach Ar string
Shell command to execute when a device is attached.
.It detach Ar string
Shell command to execute when a device is detached.
.Sh EXAMPLES
A sample entry to rescan the SCSI bus on connection of a
.Tn "Iomega USB Zip Drive" .
.Tn "Iomega USB Zip Drive" :
.Bd -literal
device "USB Zip drive"
product 0x0001
@ -112,6 +124,13 @@ A sample entry to rescan the SCSI bus on connection of a
release 0x0100
attach "/usr/bin/camcontrol rescan bus 0"
.Ed
.Pp
To start up moused for a newly attached mouse:
.Bd -literal
device "Mouse"
devname "ums[0-9]+
attach "/usr/sbin/moused -p /dev/${DEVNAME} -I /var/run/moused.${DEVNAME}.pid"
.El
.Sh FILES
.Bl -tag -width /etc/pccard.conf -compact
.It Pa /etc/usbd.conf