Annotation of src/usr.bin/tunerctl/tunerctl.c, Revision 1.1
1.1 ! jakemsr 1: /*
! 2: * Copyright (c) 2005 Jacob Meuser <jakemsr@jakemsr.com>
! 3: *
! 4: * Permission to use, copy, modify, and distribute this software for any
! 5: * purpose with or without fee is hereby granted, provided that the above
! 6: * copyright notice and this permission notice appear in all copies.
! 7: *
! 8: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 9: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 10: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 11: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 12: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 13: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 14: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 15: */
! 16:
! 17: /*
! 18: * $OpenBSD$
! 19: */
! 20:
! 21:
! 22: #include <sys/param.h>
! 23: #include <sys/ioctl.h>
! 24: #include <sys/stat.h>
! 25:
! 26: #include <dev/ic/bt8xx.h>
! 27:
! 28: #include <err.h>
! 29: #include <fcntl.h>
! 30: #include <stdio.h>
! 31: #include <stdlib.h>
! 32: #include <string.h>
! 33: #include <unistd.h>
! 34:
! 35: #define DEFAULT_TUNER_DEVICE "/dev/tuner0"
! 36:
! 37: struct fields {
! 38: char *name;
! 39: int type;
! 40: #define INT 1
! 41: #define ASRC 2
! 42: #define CSET 3
! 43: #define MUTE 4
! 44: #define OFFON 5
! 45: #define FREQ 6
! 46: #define VSAT 7
! 47: #define USAT 8
! 48: #define HUE 9
! 49: #define BRIGHT 10
! 50: #define CONTR 11
! 51: int val;
! 52: long io_set;
! 53: long io_get;
! 54: int valmin;
! 55: int valmax;
! 56: } fields[] = {
! 57: { "chanset", CSET, 0, TVTUNER_SETTYPE, TVTUNER_GETTYPE, 0, 0 },
! 58: { "channel", INT, 0, TVTUNER_SETCHNL, TVTUNER_GETCHNL, 0, 150 },
! 59: { "freq", FREQ, 0, TVTUNER_SETFREQ, TVTUNER_GETFREQ, 608, 14240 },
! 60: { "afc", OFFON, 0, TVTUNER_SETAFC, TVTUNER_GETAFC, 0, 1 },
! 61: { "audio", ASRC, 0, BT848_SAUDIO, BT848_GAUDIO, 0, 0 },
! 62: { "mute", MUTE, 0, BT848_SAUDIO, BT848_GAUDIO, 0, 1 },
! 63: { "bright", BRIGHT, 0, BT848_SBRIG, BT848_GBRIG,
! 64: BT848_BRIGHTMIN, BT848_BRIGHTMAX },
! 65: { "contrast", CONTR, 0, BT848_SCONT, BT848_GCONT,
! 66: BT848_CONTRASTMIN, BT848_CONTRASTMAX },
! 67: { "hue", HUE, 0, BT848_SHUE, BT848_GHUE, BT848_HUEMIN,
! 68: BT848_HUEMAX },
! 69: { "usat", USAT, 0, BT848_SUSAT, BT848_GUSAT, BT848_SATUMIN,
! 70: BT848_SATUMAX },
! 71: { "vsat", VSAT, 0, BT848_SVSAT, BT848_GVSAT, BT848_SATVMIN,
! 72: BT848_SATVMAX },
! 73: { 0, 0, 0, 0, 0, 0, 0}
! 74: };
! 75:
! 76: struct chansets {
! 77: int value;
! 78: char *name;
! 79: } chansets[] = {
! 80: { CHNLSET_NABCST, "nabcst", },
! 81: { CHNLSET_CABLEIRC, "cableirc", },
! 82: { CHNLSET_CABLEHRC, "cablehrc", },
! 83: { CHNLSET_WEUROPE, "weurope", },
! 84: { CHNLSET_JPNBCST, "jpnbcst", },
! 85: { CHNLSET_JPNCABLE, "jpncable", },
! 86: { CHNLSET_XUSSR, "xussr", },
! 87: { CHNLSET_AUSTRALIA, "australia", },
! 88: { CHNLSET_FRANCE, "france", },
! 89: { 0, 0 }
! 90: };
! 91:
! 92: struct audiosources {
! 93: int value;
! 94: char *name;
! 95: } audiosources[] = {
! 96: { AUDIO_TUNER, "tuner", },
! 97: { AUDIO_EXTERN, "extern", },
! 98: { AUDIO_INTERN, "intern", },
! 99: { 0, 0 }
! 100: };
! 101:
! 102: int tuner_fd;
! 103: int print_choices;
! 104: int print_name;
! 105: int print_value;
! 106:
! 107: __dead void usage(void);
! 108: int run(int, char *);
! 109: int findfield(char *);
! 110: int prfield(int);
! 111: int do_ioctls(int, char *);
! 112: #define OFF 0
! 113: #define ON 1
! 114: int isoffon(const char *);
! 115:
! 116:
! 117: /* getopt externs */
! 118: extern char *optarg;
! 119: extern int opterr;
! 120: extern int optind;
! 121: extern int optopt;
! 122: extern int optreset;
! 123:
! 124:
! 125: __dead void
! 126: usage(void)
! 127: {
! 128: extern char *__progname;
! 129:
! 130: fprintf(stderr,
! 131: "usage: %s [-nv] [-f file] -a\n"
! 132: " %s [-nv] [-f file] name [...]\n"
! 133: " %s [-q] [-f file] name=value [...]\n",
! 134: __progname, __progname, __progname);
! 135:
! 136: exit (1);
! 137: }
! 138:
! 139: int
! 140: isoffon(const char *offon)
! 141: {
! 142: if (strncmp(offon, "off", 3) == 0)
! 143: return (OFF);
! 144: else if (strncmp(offon, "on", 2) == 0)
! 145: return (ON);
! 146:
! 147: return (-1);
! 148: }
! 149:
! 150: int
! 151: findfield(char *name)
! 152: {
! 153: int i, found = 0;
! 154:
! 155: for (i = 0; fields[i].name; i++) {
! 156: if (strncmp(fields[i].name, name, strlen(fields[i].name)) ==0) {
! 157: found = 1;
! 158: break;
! 159: }
! 160: }
! 161: if (found == 1)
! 162: return (i);
! 163: else
! 164: return (-1);
! 165: }
! 166:
! 167: int
! 168: prfield(int index)
! 169: {
! 170: int switchval;
! 171: int i;
! 172:
! 173: if (print_name == 1)
! 174: printf("%s=", fields[index].name);
! 175:
! 176: if (ioctl(tuner_fd, fields[index].io_get, &fields[index].val) < 0) {
! 177: warn("%s", fields[index].name);
! 178: return (1);
! 179: }
! 180:
! 181: switchval = fields[index].type;
! 182: switch (switchval) {
! 183: case ASRC:
! 184: for (i = 0; audiosources[i].name; i++)
! 185: if (audiosources[i].value ==
! 186: (fields[index].val & ~AUDIO_MUTE))
! 187: break;
! 188: printf("%s", audiosources[i].name);
! 189: if (print_choices == 1) {
! 190: printf(" [ ");
! 191: for (i = 0; audiosources[i].name; i++)
! 192: printf("%s ", audiosources[i].name);
! 193: printf("]");
! 194: }
! 195: break;
! 196: case CSET:
! 197: for (i = 0; chansets[i].name; i++)
! 198: if (chansets[i].value == fields[index].val)
! 199: break;
! 200: printf("%s", chansets[i].name);
! 201: if (print_choices == 1) {
! 202: printf(" [ ");
! 203: for (i = 0; chansets[i].name; i++)
! 204: printf("%s ", chansets[i].name);
! 205: printf("]");
! 206: }
! 207: break;
! 208: case FREQ:
! 209: printf("%0.2f", (double)fields[index].val / 16);
! 210: if (print_choices == 1)
! 211: printf(" ( %0.2f - %0.2f )",
! 212: (double)fields[index].valmin / 16,
! 213: (double)fields[index].valmax / 16);
! 214: break;
! 215: case INT:
! 216: case BRIGHT:
! 217: case CONTR:
! 218: case HUE:
! 219: case VSAT:
! 220: case USAT:
! 221: i = fields[index].val;
! 222: if (switchval == BRIGHT) {
! 223: i = (i - BT848_BRIGHTREGMIN) *
! 224: BT848_BRIGHTRANGE / BT848_BRIGHTSTEPS +
! 225: BT848_BRIGHTMIN + (i < 0 ? -0.5 : 0.5);
! 226: } else if (switchval == CONTR) {
! 227: i = (i - BT848_CONTRASTREGMIN) *
! 228: BT848_CONTRASTRANGE / BT848_CONTRASTSTEPS +
! 229: BT848_CONTRASTMIN + (i < 0 ? -0.5 : 0.5);
! 230: } else if (switchval == HUE) {
! 231: i = (i - BT848_HUEREGMIN) *
! 232: BT848_HUERANGE / BT848_HUESTEPS +
! 233: BT848_HUEMIN + (i < 0 ? -0.5 : 0.5);
! 234: } else if (switchval == USAT) {
! 235: i = (i - BT848_SATUREGMIN) *
! 236: BT848_SATURANGE / BT848_SATUSTEPS +
! 237: BT848_SATUMIN + (i < 0 ? -0.5 : 0.5);
! 238: } else if (switchval == VSAT) {
! 239: i = (i - BT848_SATVREGMIN) *
! 240: BT848_SATVRANGE / BT848_SATVSTEPS +
! 241: BT848_SATVMIN + (i < 0 ? -0.5 : 0.5);
! 242: }
! 243: printf("%d", i);
! 244: if (print_choices == 1)
! 245: printf(" ( %d - %d )", fields[index].valmin,
! 246: fields[index].valmax);
! 247: break;
! 248: case MUTE:
! 249: case OFFON:
! 250: if (((switchval == MUTE) && (fields[index].val & AUDIO_MUTE)) ||
! 251: ((switchval != MUTE) && (fields[index].val == 1)))
! 252: printf("on");
! 253: else
! 254: printf("off");
! 255: if (print_choices == 1)
! 256: printf(" [ off on ]");
! 257: break;
! 258: default:
! 259: warnx("internal error: prfield");
! 260: break;
! 261: }
! 262: printf("\n");
! 263:
! 264: return (0);
! 265: }
! 266:
! 267: int
! 268: do_ioctls(int index, char *arg)
! 269: {
! 270: const char *errstr;
! 271: int i;
! 272: int switchval;
! 273:
! 274: switchval = fields[index].type;
! 275:
! 276: if (arg != NULL) {
! 277: switch(switchval) {
! 278: case ASRC:
! 279: for (i = 0; audiosources[i].name; i++)
! 280: if (strncmp(audiosources[i].name, arg,
! 281: strlen(audiosources[i].name)) == 0)
! 282: break;
! 283: if (audiosources[i].name[0] != '\0')
! 284: fields[index].val = audiosources[i].value;
! 285: else {
! 286: warnx("%s is invalid: %s", fields[index].name,
! 287: arg);
! 288: return (1);
! 289: }
! 290: break;
! 291: case CSET:
! 292: for (i = 0; chansets[i].name; i++)
! 293: if (strncmp(chansets[i].name, arg,
! 294: strlen(chansets[i].name)) == 0)
! 295: break;
! 296: if (chansets[i].name[0] != '\0')
! 297: fields[index].val = chansets[i].value;
! 298: else {
! 299: warnx("%s is invalid: %s", fields[index].name,
! 300: arg);
! 301: return (1);
! 302: }
! 303: break;
! 304: case FREQ:
! 305: fields[index].val = strtod(arg, (char **)NULL) * 16;
! 306: if ((fields[index].val < fields[index].valmin) ||
! 307: (fields[index].val > fields[index].valmax)) {
! 308: warnx("%s is invalid: %s", fields[index].name,
! 309: arg);
! 310: return (1);
! 311: }
! 312: break;
! 313: case INT:
! 314: case BRIGHT:
! 315: case CONTR:
! 316: case HUE:
! 317: case USAT:
! 318: case VSAT:
! 319: i = strtonum(arg, fields[index].valmin,
! 320: fields[index].valmax, &errstr);
! 321: if (errstr != NULL) {
! 322: warnx("%s is %s: %s", fields[index].name,
! 323: errstr, arg);
! 324: return (1);
! 325: }
! 326: if (switchval == BRIGHT) {
! 327: i = (i - BT848_BRIGHTMIN) *
! 328: BT848_BRIGHTSTEPS / BT848_BRIGHTRANGE +
! 329: BT848_BRIGHTREGMIN + (i < 0 ? -0.5 : 0.5);
! 330: if (i > BT848_BRIGHTREGMAX)
! 331: i = BT848_BRIGHTREGMAX;
! 332: } else if (switchval == CONTR) {
! 333: i = (i - BT848_CONTRASTMIN) *
! 334: BT848_CONTRASTSTEPS / BT848_CONTRASTRANGE +
! 335: BT848_CONTRASTREGMIN + (i < 0 ? -0.5 : 0.5);
! 336: if (i > BT848_CONTRASTREGMAX)
! 337: i = BT848_CONTRASTREGMAX;
! 338: } else if (switchval == HUE) {
! 339: i = (i - BT848_HUEMIN) *
! 340: BT848_HUESTEPS / BT848_HUERANGE +
! 341: BT848_HUEREGMIN + (i < 0 ? -0.5 : 0.5);
! 342: if (i > BT848_HUEREGMAX)
! 343: i = BT848_HUEREGMAX;
! 344: } else if (switchval == USAT) {
! 345: i = (i - BT848_SATUMIN) *
! 346: BT848_SATUSTEPS / BT848_SATURANGE +
! 347: BT848_SATUREGMIN + (i < 0 ? -0.5 : 0.5);
! 348: if (i > BT848_SATUREGMAX)
! 349: i = BT848_SATUREGMAX;
! 350: } else if (switchval == VSAT) {
! 351: i = (i - BT848_SATVMIN) *
! 352: BT848_SATVSTEPS / BT848_SATVRANGE +
! 353: BT848_SATVREGMIN + (i < 0 ? -0.5 : 0.5);
! 354: if (i > BT848_SATVREGMAX)
! 355: i = BT848_SATVREGMAX;
! 356: }
! 357: fields[index].val = i;
! 358: break;
! 359: case MUTE:
! 360: case OFFON:
! 361: fields[index].val = isoffon(arg);
! 362: if (fields[index].val < 0) {
! 363: warnx("%s is invalid: %s", fields[index].name,
! 364: optarg);
! 365: return (1);
! 366: }
! 367: if (switchval == MUTE) {
! 368: if (fields[index].val == 1)
! 369: fields[index].val = AUDIO_MUTE;
! 370: else
! 371: fields[index].val = AUDIO_UNMUTE;
! 372: }
! 373: break;
! 374: default:
! 375: warnx("internal error: do_ioctls: set");
! 376: break;
! 377: }
! 378: if (ioctl(tuner_fd, fields[index].io_set,&fields[index].val)<0){
! 379: warn("%s", fields[index].name);
! 380: return (1);
! 381: }
! 382: } else {
! 383: /* nothing is being set, so the -q option is meaningless */
! 384: print_value = 1;
! 385: }
! 386:
! 387: if (print_value == 1)
! 388: if (prfield(index) > 0)
! 389: return (1);
! 390:
! 391: return (0);
! 392: }
! 393:
! 394:
! 395: int
! 396: main(int argc, char *argv[])
! 397: {
! 398: char *device = DEFAULT_TUNER_DEVICE;
! 399: int aflag = 0;
! 400: int err = 0;
! 401: int ch, i;
! 402:
! 403: print_choices = 0;
! 404: print_name = 1;
! 405: print_value = 1;
! 406:
! 407: while ((ch = getopt(argc, argv, "af:nqv")) != -1) {
! 408: switch (ch) {
! 409: case 'a':
! 410: aflag++;
! 411: break;
! 412: case 'f':
! 413: device = optarg;
! 414: break;
! 415: case 'n':
! 416: print_name = 0;
! 417: break;
! 418: case 'q':
! 419: print_value = 0;
! 420: break;
! 421: case 'v':
! 422: print_choices = 1;
! 423: break;
! 424: default:
! 425: usage();
! 426: }
! 427: }
! 428: argc -= optind;
! 429: argv += optind;
! 430:
! 431: if ((argc == 0) && (aflag == 0))
! 432: usage();
! 433:
! 434: if ((tuner_fd = open(device, O_RDONLY)) < 0) {
! 435: warn("%s", device);
! 436: close(tuner_fd);
! 437: exit (1);
! 438: }
! 439:
! 440: if (aflag > 0) {
! 441: for (i = 0; fields[i].name; i++) {
! 442: if (do_ioctls(i, NULL) > 0) {
! 443: err++;
! 444: break;
! 445: }
! 446: }
! 447: } else {
! 448: for (; argc--; argv++) {
! 449: char *q;
! 450:
! 451: q = strchr(*argv, '=');
! 452: i = findfield(*argv);
! 453: if (i < 0) {
! 454: warnx("field '%s' does not exist", *argv);
! 455: err++;
! 456: break;
! 457: } else {
! 458: if (q != NULL)
! 459: *q++ = 0;
! 460: if (do_ioctls(i, q) > 0) {
! 461: err++;
! 462: break;
! 463: }
! 464: }
! 465: }
! 466: }
! 467: close(tuner_fd);
! 468: exit (err);
! 469: }