summaryrefslogtreecommitdiff
path: root/usr.bin/usbhidaction
diff options
context:
space:
mode:
authorMatthew N. Dodd <mdodd@FreeBSD.org>2003-04-09 23:19:50 +0000
committerMatthew N. Dodd <mdodd@FreeBSD.org>2003-04-09 23:19:50 +0000
commitf5a4d3f069840127871b8d16482b5e75eb1af71a (patch)
tree5930add24db0626d56070cdbaf1081b88d9b30b4 /usr.bin/usbhidaction
parent68d25868d06a1198ec5e57a6940c66bd503d9803 (diff)
downloadsrc-test-f5a4d3f069840127871b8d16482b5e75eb1af71a.tar.gz
src-test-f5a4d3f069840127871b8d16482b5e75eb1af71a.zip
- Implement debounce support.
- Clean up examples. - Call deamon(3) after we open the PID file. Submitted by: Mathew Kanner <mat@cnd.mcgill.ca>
Notes
Notes: svn path=/head/; revision=113309
Diffstat (limited to 'usr.bin/usbhidaction')
-rw-r--r--usr.bin/usbhidaction/usbhidaction.153
-rw-r--r--usr.bin/usbhidaction/usbhidaction.c64
2 files changed, 86 insertions, 31 deletions
diff --git a/usr.bin/usbhidaction/usbhidaction.1 b/usr.bin/usbhidaction/usbhidaction.1
index b0b491e3d32aa..b83eb407b203c 100644
--- a/usr.bin/usbhidaction/usbhidaction.1
+++ b/usr.bin/usbhidaction/usbhidaction.1
@@ -43,12 +43,10 @@
.Nd perform actions according to USB HID controls
.Sh SYNOPSIS
.Nm
+.Op Fl diev
.Fl c Ar config-file
-.Op Fl d
-.Op Fl i
.Fl f Ar device
.Op Fl p Ar pidfile
-.Op Fl v
.Ar arg ...
.Sh DESCRIPTION
.Nm
@@ -60,12 +58,19 @@ die when the USB device is unplugged.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl c Ar config-file
-Specify a path name for the config file.
.It Fl d
Toggle the daemon flag.
+.It Fl e
+Instruct
+.Nm
+to die early. Useful when specified with multiple
+verbose options to see how files are parsed.
.It Fl i
Ignore HID items in the config file that does not exist in the device.
+.It Fl v
+Be verbose, and do not become a daemon.
+.It Fl c Ar config-file
+Specify a path name for the config file.
.It Fl f Ar device
Specify a path name for the device to operate on.
If
@@ -77,8 +82,6 @@ path, it is taken to be the name of the device under
An absolute path is taken to be the literal device pathname.
.It Fl p Ar pidfile
Specify an alternate file in which to store the process ID.
-.It Fl v
-Be verbose, and do not become a daemon.
.El
.Pp
The config file will be re-read if the process gets a HUP signal.
@@ -89,8 +92,8 @@ action; if a line begins with a whitespace it is considered a continuation
of the previous line.
Lines beginning with `#' are considered as comments.
.Pp
-Each line has three parts: a name of a USB HID item, a value for that item,
-and an action.
+Each line has four parts: a name of a USB HID item, a value for that item,
+a debounce value, and an action.
There must be whitespace between the parts.
.Pp
The item names are similar to those used by
@@ -102,6 +105,12 @@ When the item reports this value
the action will be performed.
If the value is `*' it will match any value.
.Pp
+The debouce value is an integer not less than 0. The value of 0
+indicates that no debouncing should occur. A value of 1 will only
+execute the action when the state changes. Values greater than one
+specify that an action should be performed only when the value
+changes by that amount.
+.Pp
The action is a normal command that is executed with
.Xr system 3 .
Before it is executed some substitution will occur:
@@ -111,7 +120,7 @@ of the HID item, `$N' will be replaced by the name
of the control, and `$H' will be replaced by the name
of the HID device.
.Sh FILES
-.Bl -tag -indent
+.Bl -tag -width indent
.It Pa /usr/share/misc/usb_hid_usages
The HID usage table.
.It Pa /var/run/usbaction.pid
@@ -122,22 +131,26 @@ The following configuration file can be used to control a pair
of Philips USB speakers with the HID controls on the speakers.
.Bd -literal -offset indent
# Configuration for various Philips USB speakers
-Consumer:Consumer_Control.Consumer:Volume_Up 1
- mixerctl -f $1 -n -w fea8-i7-master++
-Consumer:Consumer_Control.Consumer:Volume_Down 1
- mixerctl -f $1 -n -w fea8-i7-master--
-Consumer:Consumer_Control.Consumer:Mute 1
- mixerctl -f $1 -n -w fea8-i7-mute++
-Consumer:Consumer_Control.Consumer:Channel_Top.Microsoft:Base_Up 1
- mixerctl -f $1 -n -w fea8-i7-bass++
-Consumer:Consumer_Control.Consumer:Channel_Top.Microsoft:Base_Down 1
- mixerctl -f $1 -n -w fea8-i7-bass--
+Consumer:Volume_Up 1 0 mixer -f $1 vol +1
+Consumer:Volume_Down 1 0 mixer -f $1 vol -1
+# mute not supported
+#Consumer:Mute 1 0 mixer -f $1 mute
+Consumer:Channel_Top.Microsoft:Base_Up 1 0 mixer -f $1 bass +1
+Consumer:Channel_Top.Microsoft:Base_Down 1 0 mixer -f $1 bass -1
.Ed
.Pp
A sample invocation using this configuration would be
.Bd -literal -offset indent
usbhidaction -f /dev/uhid1 -c conf /dev/mixer1
.Ed
+.Pp
+The following example controls the mixer volume using a Logitech Wingman.
+Notice the debouce of 1 for buttons and 5 for the slider.
+.Bd -literal -offset indent
+Button:Button_1 1 1 mixer vol +10
+Button:Button_2 1 1 mixer vol -10
+Generic_Desktop:Z * 5 mixer vol `echo $V | awk '{print int($$1/255*100)}'`
+.Ed
.Sh SEE ALSO
.Xr usbhidctl 1 ,
.Xr usbhid 3 ,
diff --git a/usr.bin/usbhidaction/usbhidaction.c b/usr.bin/usbhidaction/usbhidaction.c
index 22868b138a21b..b05de5ba7e849 100644
--- a/usr.bin/usbhidaction/usbhidaction.c
+++ b/usr.bin/usbhidaction/usbhidaction.c
@@ -66,6 +66,9 @@ struct command {
struct hid_item item;
int value;
+ int lastseen;
+ int lastused;
+ int debounce;
char anyvalue;
char *name;
char *action;
@@ -91,7 +94,7 @@ main(int argc, char **argv)
const char *conf = NULL;
const char *dev = NULL;
int fd, fp, ch, sz, n, val, i;
- int demon, ignore;
+ int demon, ignore, dieearly;
report_desc_t repd;
char buf[100];
char devnamebuf[PATH_MAX];
@@ -100,7 +103,8 @@ main(int argc, char **argv)
demon = 1;
ignore = 0;
- while ((ch = getopt(argc, argv, "c:df:ip:v")) != -1) {
+ dieearly = 0;
+ while ((ch = getopt(argc, argv, "c:def:ip:v")) != -1) {
switch(ch) {
case 'c':
conf = optarg;
@@ -108,6 +112,9 @@ main(int argc, char **argv)
case 'd':
demon ^= 1;
break;
+ case 'e':
+ dieearly = 1;
+ break;
case 'i':
ignore++;
break;
@@ -161,8 +168,6 @@ main(int argc, char **argv)
(void)signal(SIGHUP, sighup);
if (demon) {
- if (daemon(0, 0) < 0)
- err(1, "daemon()");
fp = open(pidfile, O_WRONLY|O_CREAT, S_IRUSR|S_IRGRP|S_IROTH);
if (fp >= 0) {
sz=snprintf(buf,100, "%d\n", getpid());
@@ -170,6 +175,8 @@ main(int argc, char **argv)
close(fp);
} else
err(1, "%s", pidfile);
+ if (daemon(0, 0) < 0)
+ err(1, "daemon()");
isdemon = 1;
}
@@ -194,9 +201,28 @@ main(int argc, char **argv)
#endif
for (cmd = commands; cmd; cmd = cmd->next) {
val = hid_get_data(buf, &cmd->item);
- if (cmd->value == val || cmd->anyvalue)
+ if (cmd->value != val && cmd->anyvalue == 0)
+ goto next;
+ if ((cmd->debounce == 0) ||
+ (cmd->debounce && ((cmd->lastseen == -1) ||
+ (cmd->lastseen != val)))) {
docmd(cmd, val, dev, argc, argv);
+ goto next;
+ }
+ if ((cmd->debounce > 1) &&
+ ((cmd->lastused == -1) ||
+ (abs(cmd->lastused - val) >= cmd->debounce))) {
+ docmd(cmd, val, dev, argc, argv);
+ cmd->lastused = val;
+ goto next;
+ }
+next:
+ cmd->lastseen = val;
}
+
+ if (dieearly)
+ exit(0);
+
if (reparse) {
struct command *cmds =
parse_conf(conf, repd, reportid, ignore);
@@ -215,8 +241,8 @@ void
usage(void)
{
- fprintf(stderr, "Usage: %s -c config_file [-d] -f hid_dev "
- "[-i] [-p pidfile] [-v]\n", getprogname());
+ fprintf(stderr, "Usage: %s [-deiv] -c config_file -f hid_dev "
+ "[-p pidfile]\n", getprogname());
exit(1);
}
@@ -237,7 +263,7 @@ parse_conf(const char *conf, report_desc_t repd, int reportid, int ignore)
FILE *f;
char *p;
int line;
- char buf[SIZE], name[SIZE], value[SIZE], action[SIZE];
+ char buf[SIZE], name[SIZE], value[SIZE], debounce[SIZE], action[SIZE];
char usage[SIZE], coll[SIZE];
struct command *cmd, *cmds;
struct hid_data *d;
@@ -263,7 +289,8 @@ parse_conf(const char *conf, report_desc_t repd, int reportid, int ignore)
}
if (p)
*p = 0;
- if (sscanf(buf, "%s %s %[^\n]", name, value, action) != 3) {
+ if (sscanf(buf, "%s %s %s %[^\n]",
+ name, value, debounce, action) != 4) {
if (isdemon) {
syslog(LOG_WARNING, "config file `%s', line %d"
", syntax error: %s", conf, line, buf);
@@ -290,18 +317,33 @@ parse_conf(const char *conf, report_desc_t repd, int reportid, int ignore)
if (isdemon) {
syslog(LOG_WARNING,
"config file `%s', line %d, "
- "bad value: %s\n",
+ "bad value: %s (should be * or a number)\n",
conf, line, value);
freecommands(cmds);
return (NULL);
} else {
errx(1, "config file `%s', line %d, "
- "bad value: %s\n",
+ "bad value: %s (should be * or a number)\n",
conf, line, value);
}
}
}
+ if (sscanf(debounce, "%d", &cmd->debounce) != 1) {
+ if (isdemon) {
+ syslog(LOG_WARNING,
+ "config file `%s', line %d, "
+ "bad value: %s (should be a number >= 0)\n",
+ conf, line, debounce);
+ freecommands(cmds);
+ return (NULL);
+ } else {
+ errx(1, "config file `%s', line %d, "
+ "bad value: %s (should be a number >= 0)\n",
+ conf, line, debounce);
+ }
+ }
+
coll[0] = 0;
for (d = hid_start_parse(repd, 1 << hid_input, reportid);
hid_get_item(d, &h); ) {