summaryrefslogtreecommitdiff
path: root/usr.bin/radioctl/radioctl.c
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2001-12-05 19:40:47 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2001-12-05 19:40:47 +0000
commite76bdef1fa868c260c322b2072596f3603fc6933 (patch)
tree9589208e613092fa5326a51790fc341a64ae4a0b /usr.bin/radioctl/radioctl.c
parentfccb74255cce70c84f027d500b6e6f7c5f7d27c1 (diff)
update from Nsk dudes
Diffstat (limited to 'usr.bin/radioctl/radioctl.c')
-rw-r--r--usr.bin/radioctl/radioctl.c538
1 files changed, 281 insertions, 257 deletions
diff --git a/usr.bin/radioctl/radioctl.c b/usr.bin/radioctl/radioctl.c
index 9ce81729cc1..209ad8c5d91 100644
--- a/usr.bin/radioctl/radioctl.c
+++ b/usr.bin/radioctl/radioctl.c
@@ -1,5 +1,4 @@
-/* $OpenBSD: radioctl.c,v 1.2 2001/10/04 22:43:45 gluk Exp $ */
-/* $RuOBSD: radioctl.c,v 1.1 2001/10/03 05:53:35 gluk Exp $ */
+/* $RuOBSD: radioctl.c,v 1.4 2001/10/20 18:09:10 pva Exp $ */
/*
* Copyright (c) 2001 Vladimir Popov <jumbo@narod.ru>
@@ -27,7 +26,10 @@
*/
#include <sys/ioctl.h>
+#include "/sys/sys/radioio.h"
+#if 0
#include <sys/radioio.h>
+#endif
#include <err.h>
#include <fcntl.h>
@@ -61,24 +63,42 @@ const char *varname[] = {
#define OPTION_NONE ~0u
#define VALUE_NONE ~0ul
+struct opt_t {
+ char *string;
+ int option;
+ int sign;
+#define SIGN_NONE 0
+#define SIGN_PLUS 1
+#define SIGN_MINUS -1
+ u_int32_t value;
+};
+
extern char *__progname;
const char *onchar = "on";
#define ONCHAR_LEN 2
const char *offchar = "off";
#define OFFCHAR_LEN 3
-u_long caps;
+static struct radio_info ri;
+
+static int parse_opt(char *, struct opt_t *);
+
+static void print_vars(int);
+static void do_ioctls(int, struct opt_t *, int);
-static void usage(void);
-static void print_vars(int, int);
-static void write_param(int, char *, int);
-static u_int parse_option(const char *);
-static u_long get_value(int, u_int);
-static void set_value(int, u_int, u_long);
-static u_long read_value(char *, u_int);
-static void print_value(int, u_int);
-static void warn_unsupported(u_int);
-static void ext_print(int, u_int, int);
+static void print_value(int);
+static void change_value(const struct opt_t);
+static void update_value(int, u_long *, u_long);
+
+static void warn_unsupported(int);
+static void usage(void);
+
+static void show_verbose(const char *, int);
+static void show_int_val(u_long, const char *, char *, int);
+static void show_float_val(float, const char *, char *, int);
+static void show_char_val(const char *, const char *, int);
+static int str_to_opt(const char *);
+static u_long str_to_long(char *, int);
/*
* Control behavior of a FM tuner - set frequency, volume etc
@@ -86,14 +106,20 @@ static void ext_print(int, u_int, int);
int
main(int argc, char **argv)
{
+ struct opt_t opt;
+
char *radiodev = NULL;
+ int rd = -1;
+
char optchar;
char *param = NULL;
- int rd = -1;
+
int show_vars = 0;
int set_param = 0;
int silent = 0;
+ int optv = 0;
+
if (argc < 2) {
usage();
exit(1);
@@ -107,45 +133,51 @@ main(int argc, char **argv)
switch (optchar) {
case 'a':
show_vars = 1;
- optind = 1;
+ optv = 1;
break;
case 'f':
radiodev = optarg;
- optind = 2;
+ optv = 2;
break;
case 'n':
silent = 1;
- optind = 1;
+ optv = 1;
break;
case 'w':
set_param = 1;
param = optarg;
- optind = 2;
+ optv = 2;
break;
default:
usage();
/* NOTREACHED */
}
- argc -= optind;
- argv += optind;
+ argc -= optv;
+ argv += optv;
}
rd = open(radiodev, O_RDONLY);
if (rd < 0)
err(1, "%s open error", radiodev);
- if (ioctl(rd, RIOCGCAPS, &caps) < 0)
- err(1, "RIOCGCAPS");
+ if (ioctl(rd, RIOCGINFO, &ri) < 0)
+ err(1, "RIOCGINFO");
if (argc > 1)
- ext_print(rd, parse_option(*(argv + 1)), silent);
+ if (parse_opt(*(argv + 1), &opt)) {
+ show_verbose(varname[opt.option], silent);
+ print_value(opt.option);
+ free(opt.string);
+ putchar('\n');
+ }
if (set_param)
- write_param(rd, param, silent);
+ if (parse_opt(param, &opt))
+ do_ioctls(rd, &opt, silent);
if (show_vars)
- print_vars(rd, silent);
+ print_vars(silent);
if (close(rd) < 0)
warn("%s close error", radiodev);
@@ -160,148 +192,116 @@ usage(void)
__progname);
}
-/*
- * Print all available parameters
- */
static void
-print_vars(int fd, int silent)
+show_verbose(const char *nick, int silent)
{
- u_long var;
-
- ext_print(fd, OPTION_VOLUME, silent);
- ext_print(fd, OPTION_FREQUENCY, silent);
- ext_print(fd, OPTION_MUTE, silent);
-
- if (caps & RADIO_CAPS_REFERENCE_FREQ)
- ext_print(fd, OPTION_REFERENCE, silent);
- if (caps & RADIO_CAPS_LOCK_SENSITIVITY)
- ext_print(fd, OPTION_SENSITIVITY, silent);
-
- if (ioctl(fd, RIOCGINFO, &var) < 0)
- warn("RIOCGINFO");
- if (caps & RADIO_CAPS_DETECT_SIGNAL)
- if (!silent)
- printf("%s=", "signal");
- printf("%s\n", var & RADIO_INFO_SIGNAL ? onchar : offchar);
- if (caps & RADIO_CAPS_DETECT_STEREO) {
- if (!silent)
- printf("%s=", varname[OPTION_STEREO]);
- printf("%s\n", var & RADIO_INFO_STEREO ? onchar : offchar);
- }
-
if (!silent)
- puts("card capabilities:");
- if (caps & RADIO_CAPS_SET_MONO)
- puts("\tmanageable mono/stereo");
- if (caps & RADIO_CAPS_HW_SEARCH)
- puts("\thardware search");
- if (caps & RADIO_CAPS_HW_AFC)
- puts("\thardware AFC");
+ printf("%s=", nick);
}
-/*
- * Set new value of a parameter
- */
static void
-write_param(int fd, char *param, int silent)
+warn_unsupported(int optval)
{
- int paramlen = 0;
- int namelen = 0;
- char *topt = NULL;
- const char *badvalue = "bad value `%s'";
- u_int optval = OPTION_NONE;
- u_long var = VALUE_NONE;
- u_long addvar = VALUE_NONE;
- u_char sign = 0;
+ warnx("driver does not support `%s'", varname[optval]);
+}
- if (param == NULL || *param == '\0')
+static void
+do_ioctls(int fd, struct opt_t *o, int silent)
+{
+ int oval;
+
+ if (fd < 0 || o == NULL)
return;
- paramlen = strlen(param);
- namelen = strcspn(param, "=");
- if (namelen > paramlen - 2) {
- warnx(badvalue, param);
+ if (o->option == OPTION_SEARCH && !(ri.caps & RADIO_CAPS_HW_SEARCH)) {
+ warn_unsupported(o->option);
return;
}
- paramlen -= ++namelen;
+ oval = o->option == OPTION_SEARCH ? OPTION_FREQUENCY : o->option;
+ if (!silent)
+ printf("%s: ", varname[oval]);
+
+ print_value(o->option);
+ printf(" -> ");
+
+ if (o->option == OPTION_SEARCH) {
+
+ if (ioctl(fd, RIOCSSRCH, &o->value) < 0) {
+ warn("RIOCSSRCH");
+ return;
+ }
+
+ } else {
+
+ change_value(*o);
+ if (ioctl(fd, RIOCSINFO, &ri) < 0) {
+ warn("RIOCSINFO");
+ return;
+ }
- if ((topt = (char *)malloc(namelen)) == NULL) {
- warn("memory allocation error");
- return;
}
- strlcpy(topt, param, namelen);
- optval = parse_option(topt);
- if (optval == OPTION_NONE) {
- free(topt);
+ if (ioctl(fd, RIOCGINFO, &ri) < 0) {
+ warn("RIOCGINFO");
return;
}
- if (!silent)
- printf("%s: ", topt);
+ print_value(o->option);
+ putchar('\n');
+}
- free(topt);
+static void
+change_value(const struct opt_t o)
+{
+ int unsupported = 0;
- topt = &param[namelen];
- switch (*topt) {
- case '+':
- case '-':
- if ((addvar = read_value(topt + 1, optval)) == VALUE_NONE)
- break;
- if ((var = get_value(fd, optval)) == VALUE_NONE)
- break;
- sign++;
- if (*topt == '+')
- var += addvar;
- else
- var -= addvar;
+ if (o.value == VALUE_NONE)
+ return;
+
+ switch (o.option) {
+ case OPTION_VOLUME:
+ update_value(o.sign, (u_long *)&ri.volume, o.value);
break;
- case 'o':
- if (strncmp(topt, offchar,
- paramlen > OFFCHAR_LEN ? paramlen : OFFCHAR_LEN) == 0)
- var = 0;
+ case OPTION_FREQUENCY:
+ update_value(o.sign, (u_long *)&ri.freq, o.value);
+ break;
+ case OPTION_REFERENCE:
+ if (ri.caps & RADIO_CAPS_REFERENCE_FREQ)
+ update_value(o.sign, (u_long *)&ri.rfreq, o.value);
else
- if (strncmp(topt, onchar,
- paramlen > ONCHAR_LEN ? paramlen : ONCHAR_LEN) == 0)
- var = 1;
+ unsupported++;
break;
- case 'u':
- if (strncmp(topt, "up", paramlen > 2 ? paramlen : 2) == 0)
- var = 1;
+ case OPTION_MONO:
+ /* FALLTHROUGH */
+ case OPTION_STEREO:
+ if (ri.caps & RADIO_CAPS_SET_MONO)
+ ri.stereo = o.option == OPTION_MONO ? !o.value : o.value;
+ else
+ unsupported++;
break;
- case 'd':
- if (strncmp(topt, "down", paramlen > 4 ? paramlen : 4) == 0)
- var = 0;
+ case OPTION_SENSITIVITY:
+ if (ri.caps & RADIO_CAPS_LOCK_SENSITIVITY)
+ update_value(o.sign, (u_long *)&ri.lock, o.value);
+ else
+ unsupported++;
break;
- default:
- if (*topt > 47 && *topt < 58)
- var = read_value(topt, optval);
+ case OPTION_MUTE:
+ ri.mute = o.value;
break;
}
- if (var == VALUE_NONE || (sign && addvar == VALUE_NONE)) {
- warnx(badvalue, topt);
- return;
- }
-
- print_value(fd, optval);
- printf(" -> ");
-
- set_value(fd, optval, var);
-
- print_value(fd, optval);
- putchar('\n');
+ if ( unsupported )
+ warn_unsupported(o.option);
}
/*
* Convert string to integer representation of a parameter
*/
-static u_int
-parse_option(const char *topt)
+static int
+str_to_opt(const char *topt)
{
- u_int res;
- int toptlen, varlen, len, varsize;
+ int res, toptlen, varlen, len, varsize;
if (topt == NULL || *topt == '\0')
return OPTION_NONE;
@@ -320,114 +320,27 @@ parse_option(const char *topt)
return OPTION_NONE;
}
-/*
- * Returns current value of parameter optval
- */
-static u_long
-get_value(int fd, u_int optval)
-{
- u_long var = VALUE_NONE;
-
- switch (optval) {
- case OPTION_VOLUME:
- if (ioctl(fd, RIOCGVOLU, &var) < 0)
- warn("RIOCGVOLU");
- break;
- case OPTION_FREQUENCY:
- if (ioctl(fd, RIOCGFREQ, &var) < 0)
- warn("RIOCGFREQ");
- break;
- case OPTION_REFERENCE:
- if (caps & RADIO_CAPS_REFERENCE_FREQ)
- if (ioctl(fd, RIOCGREFF, &var) < 0)
- warn("RIOCGREFF");
- break;
- case OPTION_MONO:
- /* FALLTHROUGH */
- case OPTION_STEREO:
- if (caps & RADIO_CAPS_SET_MONO)
- if (ioctl(fd, RIOCGMONO, &var) < 0)
- warn("RIOCGMONO");
- break;
- case OPTION_SENSITIVITY:
- if (caps & RADIO_CAPS_LOCK_SENSITIVITY)
- if (ioctl(fd, RIOCGLOCK, &var) < 0)
- warn("RIOCGLOCK");
- break;
- case OPTION_MUTE:
- if (ioctl(fd, RIOCGMUTE, &var) < 0)
- warn("RIOCGMUTE");
- break;
- }
-
- if (var == VALUE_NONE)
- warn_unsupported(optval);
-
- return var;
-}
-
-/*
- * Set card parameter optval to value var
- */
static void
-set_value(int fd, u_int optval, u_long var)
+update_value(int sign, u_long *value, u_long update)
{
- int unsupported = 0;
-
- if (var == VALUE_NONE)
- return;
-
- switch (optval) {
- case OPTION_VOLUME:
- if (ioctl(fd, RIOCSVOLU, &var) < 0)
- warn("RIOCSVOLU");
+ switch (sign) {
+ case SIGN_NONE:
+ *value = update;
break;
- case OPTION_FREQUENCY:
- if (ioctl(fd, RIOCSFREQ, &var) < 0)
- warn("RIOCSFREQ");
+ case SIGN_PLUS:
+ *value += update;
break;
- case OPTION_REFERENCE:
- if (caps & RADIO_CAPS_REFERENCE_FREQ) {
- if (ioctl(fd, RIOCSREFF, &var) < 0)
- warn("RIOCSREFF");
- } else unsupported++;
- break;
- case OPTION_STEREO:
- var = !var;
- /* FALLTHROUGH */
- case OPTION_MONO:
- if (caps & RADIO_CAPS_SET_MONO) {
- if (ioctl(fd, RIOCSMONO, &var) < 0)
- warn("RIOCSMONO");
- } else unsupported++;
- break;
- case OPTION_SENSITIVITY:
- if (caps & RADIO_CAPS_LOCK_SENSITIVITY) {
- if (ioctl(fd, RIOCSLOCK, &var) < 0)
- warn("RIOCSLOCK");
- } else unsupported++;
- break;
- case OPTION_SEARCH:
- if (caps & RADIO_CAPS_HW_SEARCH) {
- if (ioctl(fd, RIOCSSRCH, &var) < 0)
- warn("RIOCSSRCH");
- } else unsupported++;
- break;
- case OPTION_MUTE:
- if (ioctl(fd, RIOCSMUTE, &var) < 0)
- warn("RIOCSMUTE");
+ case SIGN_MINUS:
+ *value -= update;
break;
}
-
- if ( unsupported )
- warn_unsupported(optval);
}
/*
- * Convert string to float or unsigned integer
+ * Convert string to unsigned integer
*/
static u_long
-read_value(char *str, u_int optval)
+str_to_long(char *str, int optval)
{
u_long val;
@@ -443,66 +356,177 @@ read_value(char *str, u_int optval)
}
/*
+ * parse string s into struct opt_t
+ * return true on success, false on failure
+ */
+static int
+parse_opt(char *s, struct opt_t *o) {
+ const char *badvalue = "bad value `%s'";
+ char *topt = NULL;
+ int slen, optlen;
+
+ if (s == NULL || *s == '\0' || o == NULL)
+ return 0;
+
+ o->string = NULL;
+ o->option = OPTION_NONE;
+ o->value = VALUE_NONE;
+ o->sign = SIGN_NONE;
+
+ slen = strlen(s);
+ optlen = strcspn(s, "=");
+
+ /* Set only o->optval, the rest is missing */
+ if (slen == optlen) {
+ o->option = str_to_opt(s);
+ return o->option == OPTION_NONE ? 0 : 1;
+ }
+
+ if (optlen > slen - 2) {
+ warnx(badvalue, s);
+ return 0;
+ }
+
+ slen -= ++optlen;
+
+ if ((topt = (char *)malloc(optlen)) == NULL) {
+ warn("memory allocation error");
+ return 0;
+ }
+ strlcpy(topt, s, optlen);
+
+ if ((o->option = str_to_opt(topt)) == OPTION_NONE) {
+ free(topt);
+ return 0;
+ }
+ o->string = topt;
+
+ topt = &s[optlen];
+ switch (*topt) {
+ case '+':
+ case '-':
+ o->sign = (*topt == '+') ? SIGN_PLUS : SIGN_MINUS;
+ o->value = str_to_long(&topt[1], o->option);
+ break;
+ case 'o':
+ if (strncmp(topt, offchar,
+ slen > OFFCHAR_LEN ? slen : OFFCHAR_LEN) == 0)
+ o->value = 0;
+ else if (strncmp(topt, onchar,
+ slen > ONCHAR_LEN ? slen : ONCHAR_LEN) == 0)
+ o->value = 1;
+ break;
+ case 'u':
+ if (strncmp(topt, "up", slen > 2 ? slen : 2) == 0)
+ o->value = 1;
+ break;
+ case 'd':
+ if (strncmp(topt, "down", slen > 4 ? slen : 4) == 0)
+ o->value = 0;
+ break;
+ default:
+ if (*topt > 47 && *topt < 58)
+ o->value = str_to_long(topt, o->option);
+ break;
+ }
+
+ if (o->value == VALUE_NONE) {
+ warnx(badvalue, topt);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
* Print current value of the parameter.
*/
static void
-print_value(int fd, u_int optval)
+print_value(int optval)
{
- u_long var, mhz;
-
if (optval == OPTION_NONE)
return;
- if ( optval == OPTION_SEARCH)
- var = get_value(fd, OPTION_FREQUENCY);
- else
- var = get_value(fd, optval);
-
- if (var == VALUE_NONE)
- return;
-
switch (optval) {
case OPTION_SEARCH:
/* FALLTHROUGH */
case OPTION_FREQUENCY:
- mhz = var / 1000;
- printf("%u.%uMHz", (u_int)mhz,
- (u_int)var / 10 - (u_int)mhz * 100);
+ printf("%.2fMHz", (float)ri.freq / 1000.);
break;
case OPTION_REFERENCE:
- printf("%ukHz", (u_int)var);
+ printf("%ukHz", ri.rfreq);
break;
case OPTION_SENSITIVITY:
- printf("%umkV", (u_int)var);
+ printf("%umkV", ri.lock);
break;
case OPTION_MUTE:
- /* FALLTHROUGH */
+ printf(ri.mute ? onchar : offchar);
+ break;
case OPTION_MONO:
- printf("%s", var ? onchar : offchar);
+ printf(ri.stereo ? offchar : onchar);
break;
case OPTION_STEREO:
- printf("%s", var ? offchar : onchar);
+ printf(ri.stereo ? onchar : offchar);
break;
+ case OPTION_VOLUME:
default:
- printf("%u", (u_int)var);
+ printf("%u", ri.volume);
break;
}
}
static void
-warn_unsupported(u_int optval)
+show_int_val(u_long val, const char *nick, char *append, int silent)
{
- warnx("driver does not support `%s'", varname[optval]);
+ show_verbose(nick, silent);
+ printf("%lu%s\n", val, append);
}
static void
-ext_print(int fd, u_int optval, int silent)
+show_float_val(float val, const char *nick, char *append, int silent)
{
- if (optval == OPTION_NONE)
- return;
+ show_verbose(nick, silent);
+ printf("%.2f%s\n", val, append);
+}
+
+static void
+show_char_val(const char *val, const char *nick, int silent)
+{
+ show_verbose(nick, silent);
+ printf("%s\n", val);
+}
+
+/*
+ * Print all available parameters
+ */
+static void
+print_vars(int silent)
+{
+ show_int_val(ri.volume, varname[OPTION_VOLUME], "", silent);
+ show_float_val((float)ri.freq / 1000., varname[OPTION_FREQUENCY],
+ "MHz", silent);
+ show_char_val(ri.mute ? onchar : offchar, varname[OPTION_MUTE], silent);
+
+ if (ri.caps & RADIO_CAPS_REFERENCE_FREQ)
+ show_int_val(ri.rfreq, varname[OPTION_REFERENCE], "kHz", silent);
+ if (ri.caps & RADIO_CAPS_LOCK_SENSITIVITY)
+ show_int_val(ri.lock, varname[OPTION_SENSITIVITY], "mkV", silent);
+
+ if (ri.caps & RADIO_CAPS_DETECT_SIGNAL) {
+ show_verbose("signal", silent);
+ printf("%s\n", ri.info & RADIO_INFO_SIGNAL ? onchar : offchar);
+ }
+ if (ri.caps & RADIO_CAPS_DETECT_STEREO) {
+ show_verbose(varname[OPTION_STEREO], silent);
+ printf("%s\n", ri.info & RADIO_INFO_STEREO ? onchar : offchar);
+ }
if (!silent)
- printf("%s=", varname[optval]);
- print_value(fd, optval);
- putchar('\n');
+ puts("card capabilities:");
+ if (ri.caps & RADIO_CAPS_SET_MONO)
+ puts("\tmanageable mono/stereo");
+ if (ri.caps & RADIO_CAPS_HW_SEARCH)
+ puts("\thardware search");
+ if (ri.caps & RADIO_CAPS_HW_AFC)
+ puts("\thardware AFC");
}