From b2800660f8c3e839cd6c1c53d68e2fc7f1f3d637 Mon Sep 17 00:00:00 2001 From: Jacob Meuser Date: Mon, 4 Jul 2005 21:10:27 +0000 Subject: - tunerctl is a program for controlling /dev/tunerN devices associated with bktr(4) devices ok deraadt@ --- usr.bin/tunerctl/Makefile | 6 + usr.bin/tunerctl/tunerctl.1 | 129 ++++++++++++ usr.bin/tunerctl/tunerctl.c | 469 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 604 insertions(+) create mode 100644 usr.bin/tunerctl/Makefile create mode 100644 usr.bin/tunerctl/tunerctl.1 create mode 100644 usr.bin/tunerctl/tunerctl.c diff --git a/usr.bin/tunerctl/Makefile b/usr.bin/tunerctl/Makefile new file mode 100644 index 00000000000..41eb7a8b367 --- /dev/null +++ b/usr.bin/tunerctl/Makefile @@ -0,0 +1,6 @@ +# $OpenBSD: Makefile,v 1.1 2005/07/04 21:10:26 jakemsr Exp $ + +PROG= tunerctl +CFLAGS+=-Wall + +.include diff --git a/usr.bin/tunerctl/tunerctl.1 b/usr.bin/tunerctl/tunerctl.1 new file mode 100644 index 00000000000..f6eeb022c49 --- /dev/null +++ b/usr.bin/tunerctl/tunerctl.1 @@ -0,0 +1,129 @@ +.\" +.\" Copyright (c) 2005 Jacob Meuser +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" $OpenBSD: tunerctl.1,v 1.1 2005/07/04 21:10:26 jakemsr Exp $ +.\" +.Dd Mar 27, 2005 +.Dt TUNERCTL 1 +.Os +.Sh NAME +.Nm tunerctl +.Nd manipulate +.Xr bktr 4 +tuner devices. +.Sh SYNOPSIS +.Nm +.Op Fl nv +.Op Fl f Ar file +.Fl a +.Nm +.Op Fl nv +.Op Fl f Ar file +.Ar name +.Op Ar ... +.Nm +.Op Fl q +.Pf \ \& Op Fl f Ar file +.Xo +.Ar name Ns = Ns Ar value +.Op Ar ... +.Xc +.Sh DESCRIPTION +The +.Nm +command displays or sets various variables that affect the behaviour of +.Xr bktr 4 +device tuners. +If a list of variables is present on the command line, +.Nm +prints the current value of those variables for the specified device. +By default, +.Nm +operates on the +.Pa /dev/tuner0 +device. +.Pp +The options are as follows: +.Bl -tag -width "name=value" +.It Fl a +Print all device variables and their current values. +.It Fl f Ar file +Specify an alternative tuner device. +.It Fl n +Suppress printing of the variable names. +.It Fl q +Suppress all printing when setting a variable. +.It Fl v +Show the possible values of enumeration and range valued queries. +Enumeration values are show in +.Dq [] +and ranges are show in +.Dq () . +.It Ar name Ns = Ns Ar value +Attempt to set the specified variable +.Ar name +to +.Ar value . +.El +.Pp +Depending on the features of a specific tuner, the setting of some +variables may not have any effect. +.Pp +Variable names explained: +.Bl -tag -width contrast +.It Ic chanset +TV tuner channel set. +.It Ic channel +TV tuner channel. +.It Ic freq +Frequency in MHz. +.It Ic afc +Automatic Frequency Control. +.It Ic audio +Audio source. +.It Ic mute +Audio mute. +.It Ic bright +Video brightness. +.It Ic contrast +Video contrast. +.It Ic hue +Video hue. +.It Ic usat +Video +.Ql U +(blue) saturation. +.It Ic vsat +Video +.Ql V +(red) saturation. +.El +.Sh FILES +.Bl -tag -width /dev/tuner0 +.It Pa /dev/tuner0 +default tuner device +.El +.Sh EXAMPLES +The command +.Pp +.Dl "$ tunerctl chanset=nabcst channel=13" +.Pp +sets the tuner to North American broadcast TV channel 13. +.Sh SEE ALSO +.Xr bktr 4 +.Sh AUTHORS +.Nm +and this manual page were written by +.An Jacob Meuser Aq jakemsr@jakemsr.com . diff --git a/usr.bin/tunerctl/tunerctl.c b/usr.bin/tunerctl/tunerctl.c new file mode 100644 index 00000000000..ea8cc78f1fc --- /dev/null +++ b/usr.bin/tunerctl/tunerctl.c @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2005 Jacob Meuser + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * $OpenBSD: tunerctl.c,v 1.1 2005/07/04 21:10:26 jakemsr Exp $ + */ + + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define DEFAULT_TUNER_DEVICE "/dev/tuner0" + +struct fields { + char *name; + int type; +#define INT 1 +#define ASRC 2 +#define CSET 3 +#define MUTE 4 +#define OFFON 5 +#define FREQ 6 +#define VSAT 7 +#define USAT 8 +#define HUE 9 +#define BRIGHT 10 +#define CONTR 11 + int val; + long io_set; + long io_get; + int valmin; + int valmax; +} fields[] = { +{ "chanset", CSET, 0, TVTUNER_SETTYPE, TVTUNER_GETTYPE, 0, 0 }, +{ "channel", INT, 0, TVTUNER_SETCHNL, TVTUNER_GETCHNL, 0, 150 }, +{ "freq", FREQ, 0, TVTUNER_SETFREQ, TVTUNER_GETFREQ, 608, 14240 }, +{ "afc", OFFON, 0, TVTUNER_SETAFC, TVTUNER_GETAFC, 0, 1 }, +{ "audio", ASRC, 0, BT848_SAUDIO, BT848_GAUDIO, 0, 0 }, +{ "mute", MUTE, 0, BT848_SAUDIO, BT848_GAUDIO, 0, 1 }, +{ "bright", BRIGHT, 0, BT848_SBRIG, BT848_GBRIG, + BT848_BRIGHTMIN, BT848_BRIGHTMAX }, +{ "contrast", CONTR, 0, BT848_SCONT, BT848_GCONT, + BT848_CONTRASTMIN, BT848_CONTRASTMAX }, +{ "hue", HUE, 0, BT848_SHUE, BT848_GHUE, BT848_HUEMIN, + BT848_HUEMAX }, +{ "usat", USAT, 0, BT848_SUSAT, BT848_GUSAT, BT848_SATUMIN, + BT848_SATUMAX }, +{ "vsat", VSAT, 0, BT848_SVSAT, BT848_GVSAT, BT848_SATVMIN, + BT848_SATVMAX }, +{ 0, 0, 0, 0, 0, 0, 0} +}; + +struct chansets { + int value; + char *name; +} chansets[] = { +{ CHNLSET_NABCST, "nabcst", }, +{ CHNLSET_CABLEIRC, "cableirc", }, +{ CHNLSET_CABLEHRC, "cablehrc", }, +{ CHNLSET_WEUROPE, "weurope", }, +{ CHNLSET_JPNBCST, "jpnbcst", }, +{ CHNLSET_JPNCABLE, "jpncable", }, +{ CHNLSET_XUSSR, "xussr", }, +{ CHNLSET_AUSTRALIA, "australia", }, +{ CHNLSET_FRANCE, "france", }, +{ 0, 0 } +}; + +struct audiosources { + int value; + char *name; +} audiosources[] = { +{ AUDIO_TUNER, "tuner", }, +{ AUDIO_EXTERN, "extern", }, +{ AUDIO_INTERN, "intern", }, +{ 0, 0 } +}; + +int tuner_fd; +int print_choices; +int print_name; +int print_value; + +__dead void usage(void); +int run(int, char *); +int findfield(char *); +int prfield(int); +int do_ioctls(int, char *); +#define OFF 0 +#define ON 1 +int isoffon(const char *); + + +/* getopt externs */ +extern char *optarg; +extern int opterr; +extern int optind; +extern int optopt; +extern int optreset; + + +__dead void +usage(void) +{ + extern char *__progname; + + fprintf(stderr, + "usage: %s [-nv] [-f file] -a\n" + " %s [-nv] [-f file] name [...]\n" + " %s [-q] [-f file] name=value [...]\n", + __progname, __progname, __progname); + + exit (1); +} + +int +isoffon(const char *offon) +{ + if (strncmp(offon, "off", 3) == 0) + return (OFF); + else if (strncmp(offon, "on", 2) == 0) + return (ON); + + return (-1); +} + +int +findfield(char *name) +{ + int i, found = 0; + + for (i = 0; fields[i].name; i++) { + if (strncmp(fields[i].name, name, strlen(fields[i].name)) ==0) { + found = 1; + break; + } + } + if (found == 1) + return (i); + else + return (-1); +} + +int +prfield(int index) +{ + int switchval; + int i; + + if (print_name == 1) + printf("%s=", fields[index].name); + + if (ioctl(tuner_fd, fields[index].io_get, &fields[index].val) < 0) { + warn("%s", fields[index].name); + return (1); + } + + switchval = fields[index].type; + switch (switchval) { + case ASRC: + for (i = 0; audiosources[i].name; i++) + if (audiosources[i].value == + (fields[index].val & ~AUDIO_MUTE)) + break; + printf("%s", audiosources[i].name); + if (print_choices == 1) { + printf(" [ "); + for (i = 0; audiosources[i].name; i++) + printf("%s ", audiosources[i].name); + printf("]"); + } + break; + case CSET: + for (i = 0; chansets[i].name; i++) + if (chansets[i].value == fields[index].val) + break; + printf("%s", chansets[i].name); + if (print_choices == 1) { + printf(" [ "); + for (i = 0; chansets[i].name; i++) + printf("%s ", chansets[i].name); + printf("]"); + } + break; + case FREQ: + printf("%0.2f", (double)fields[index].val / 16); + if (print_choices == 1) + printf(" ( %0.2f - %0.2f )", + (double)fields[index].valmin / 16, + (double)fields[index].valmax / 16); + break; + case INT: + case BRIGHT: + case CONTR: + case HUE: + case VSAT: + case USAT: + i = fields[index].val; + if (switchval == BRIGHT) { + i = (i - BT848_BRIGHTREGMIN) * + BT848_BRIGHTRANGE / BT848_BRIGHTSTEPS + + BT848_BRIGHTMIN + (i < 0 ? -0.5 : 0.5); + } else if (switchval == CONTR) { + i = (i - BT848_CONTRASTREGMIN) * + BT848_CONTRASTRANGE / BT848_CONTRASTSTEPS + + BT848_CONTRASTMIN + (i < 0 ? -0.5 : 0.5); + } else if (switchval == HUE) { + i = (i - BT848_HUEREGMIN) * + BT848_HUERANGE / BT848_HUESTEPS + + BT848_HUEMIN + (i < 0 ? -0.5 : 0.5); + } else if (switchval == USAT) { + i = (i - BT848_SATUREGMIN) * + BT848_SATURANGE / BT848_SATUSTEPS + + BT848_SATUMIN + (i < 0 ? -0.5 : 0.5); + } else if (switchval == VSAT) { + i = (i - BT848_SATVREGMIN) * + BT848_SATVRANGE / BT848_SATVSTEPS + + BT848_SATVMIN + (i < 0 ? -0.5 : 0.5); + } + printf("%d", i); + if (print_choices == 1) + printf(" ( %d - %d )", fields[index].valmin, + fields[index].valmax); + break; + case MUTE: + case OFFON: + if (((switchval == MUTE) && (fields[index].val & AUDIO_MUTE)) || + ((switchval != MUTE) && (fields[index].val == 1))) + printf("on"); + else + printf("off"); + if (print_choices == 1) + printf(" [ off on ]"); + break; + default: + warnx("internal error: prfield"); + break; + } + printf("\n"); + + return (0); +} + +int +do_ioctls(int index, char *arg) +{ + const char *errstr; + int i; + int switchval; + + switchval = fields[index].type; + + if (arg != NULL) { + switch(switchval) { + case ASRC: + for (i = 0; audiosources[i].name; i++) + if (strncmp(audiosources[i].name, arg, + strlen(audiosources[i].name)) == 0) + break; + if (audiosources[i].name[0] != '\0') + fields[index].val = audiosources[i].value; + else { + warnx("%s is invalid: %s", fields[index].name, + arg); + return (1); + } + break; + case CSET: + for (i = 0; chansets[i].name; i++) + if (strncmp(chansets[i].name, arg, + strlen(chansets[i].name)) == 0) + break; + if (chansets[i].name[0] != '\0') + fields[index].val = chansets[i].value; + else { + warnx("%s is invalid: %s", fields[index].name, + arg); + return (1); + } + break; + case FREQ: + fields[index].val = strtod(arg, (char **)NULL) * 16; + if ((fields[index].val < fields[index].valmin) || + (fields[index].val > fields[index].valmax)) { + warnx("%s is invalid: %s", fields[index].name, + arg); + return (1); + } + break; + case INT: + case BRIGHT: + case CONTR: + case HUE: + case USAT: + case VSAT: + i = strtonum(arg, fields[index].valmin, + fields[index].valmax, &errstr); + if (errstr != NULL) { + warnx("%s is %s: %s", fields[index].name, + errstr, arg); + return (1); + } + if (switchval == BRIGHT) { + i = (i - BT848_BRIGHTMIN) * + BT848_BRIGHTSTEPS / BT848_BRIGHTRANGE + + BT848_BRIGHTREGMIN + (i < 0 ? -0.5 : 0.5); + if (i > BT848_BRIGHTREGMAX) + i = BT848_BRIGHTREGMAX; + } else if (switchval == CONTR) { + i = (i - BT848_CONTRASTMIN) * + BT848_CONTRASTSTEPS / BT848_CONTRASTRANGE + + BT848_CONTRASTREGMIN + (i < 0 ? -0.5 : 0.5); + if (i > BT848_CONTRASTREGMAX) + i = BT848_CONTRASTREGMAX; + } else if (switchval == HUE) { + i = (i - BT848_HUEMIN) * + BT848_HUESTEPS / BT848_HUERANGE + + BT848_HUEREGMIN + (i < 0 ? -0.5 : 0.5); + if (i > BT848_HUEREGMAX) + i = BT848_HUEREGMAX; + } else if (switchval == USAT) { + i = (i - BT848_SATUMIN) * + BT848_SATUSTEPS / BT848_SATURANGE + + BT848_SATUREGMIN + (i < 0 ? -0.5 : 0.5); + if (i > BT848_SATUREGMAX) + i = BT848_SATUREGMAX; + } else if (switchval == VSAT) { + i = (i - BT848_SATVMIN) * + BT848_SATVSTEPS / BT848_SATVRANGE + + BT848_SATVREGMIN + (i < 0 ? -0.5 : 0.5); + if (i > BT848_SATVREGMAX) + i = BT848_SATVREGMAX; + } + fields[index].val = i; + break; + case MUTE: + case OFFON: + fields[index].val = isoffon(arg); + if (fields[index].val < 0) { + warnx("%s is invalid: %s", fields[index].name, + optarg); + return (1); + } + if (switchval == MUTE) { + if (fields[index].val == 1) + fields[index].val = AUDIO_MUTE; + else + fields[index].val = AUDIO_UNMUTE; + } + break; + default: + warnx("internal error: do_ioctls: set"); + break; + } + if (ioctl(tuner_fd, fields[index].io_set,&fields[index].val)<0){ + warn("%s", fields[index].name); + return (1); + } + } else { + /* nothing is being set, so the -q option is meaningless */ + print_value = 1; + } + + if (print_value == 1) + if (prfield(index) > 0) + return (1); + + return (0); +} + + +int +main(int argc, char *argv[]) +{ + char *device = DEFAULT_TUNER_DEVICE; + int aflag = 0; + int err = 0; + int ch, i; + + print_choices = 0; + print_name = 1; + print_value = 1; + + while ((ch = getopt(argc, argv, "af:nqv")) != -1) { + switch (ch) { + case 'a': + aflag++; + break; + case 'f': + device = optarg; + break; + case 'n': + print_name = 0; + break; + case 'q': + print_value = 0; + break; + case 'v': + print_choices = 1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if ((argc == 0) && (aflag == 0)) + usage(); + + if ((tuner_fd = open(device, O_RDONLY)) < 0) { + warn("%s", device); + close(tuner_fd); + exit (1); + } + + if (aflag > 0) { + for (i = 0; fields[i].name; i++) { + if (do_ioctls(i, NULL) > 0) { + err++; + break; + } + } + } else { + for (; argc--; argv++) { + char *q; + + q = strchr(*argv, '='); + i = findfield(*argv); + if (i < 0) { + warnx("field '%s' does not exist", *argv); + err++; + break; + } else { + if (q != NULL) + *q++ = 0; + if (do_ioctls(i, q) > 0) { + err++; + break; + } + } + } + } + close(tuner_fd); + exit (err); +} -- cgit v1.2.3