xref: /dflybsd-src/tools/multimedia/cxm/setchannel/cxm_setchannel.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*-
286d7f5d3SJohn Marino  * Copyright (c) 2003, 2004, 2005
386d7f5d3SJohn Marino  *	John Wehle <john@feith.com>.  All rights reserved.
486d7f5d3SJohn Marino  *
586d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
686d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
786d7f5d3SJohn Marino  * are met:
886d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
986d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
1086d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
1186d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
1286d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
1386d7f5d3SJohn Marino  * 3. All advertising materials mentioning features or use of this software
1486d7f5d3SJohn Marino  *    must display the following acknowledgement:
1586d7f5d3SJohn Marino  *	This product includes software developed by John Wehle.
1686d7f5d3SJohn Marino  * 4. The name of the author may not be used to endorse or promote products
1786d7f5d3SJohn Marino  *    derived from this software without specific prior written permission.
1886d7f5d3SJohn Marino  *
1986d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2086d7f5d3SJohn Marino  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2186d7f5d3SJohn Marino  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2286d7f5d3SJohn Marino  * DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2386d7f5d3SJohn Marino  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2486d7f5d3SJohn Marino  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2586d7f5d3SJohn Marino  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2686d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2786d7f5d3SJohn Marino  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2886d7f5d3SJohn Marino  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2986d7f5d3SJohn Marino  * POSSIBILITY OF SUCH DAMAGE.
3086d7f5d3SJohn Marino  *
3186d7f5d3SJohn Marino  * Set the channel of the tuner card.
3286d7f5d3SJohn Marino  */
3386d7f5d3SJohn Marino 
3486d7f5d3SJohn Marino #include <sys/types.h>
3586d7f5d3SJohn Marino #include <sys/param.h>
3686d7f5d3SJohn Marino #include <sys/ioctl.h>
3786d7f5d3SJohn Marino 
3886d7f5d3SJohn Marino #include <ctype.h>
3986d7f5d3SJohn Marino #include <err.h>
4086d7f5d3SJohn Marino #include <fcntl.h>
4186d7f5d3SJohn Marino #include <stdio.h>
4286d7f5d3SJohn Marino #include <stdlib.h>
4386d7f5d3SJohn Marino #include <string.h>
4486d7f5d3SJohn Marino #include <unistd.h>
4586d7f5d3SJohn Marino 
4686d7f5d3SJohn Marino #include <dev/video/meteor/ioctl_meteor.h>
4786d7f5d3SJohn Marino #include <dev/video/bktr/ioctl_bt848.h>
4886d7f5d3SJohn Marino 
4986d7f5d3SJohn Marino static void
usage(void)5086d7f5d3SJohn Marino usage(void)
5186d7f5d3SJohn Marino {
5286d7f5d3SJohn Marino 	fprintf(stderr,
5386d7f5d3SJohn Marino 	    "usage: cxm_setchannel [-a {on|off}] [-c | -r | -s | -t] [-d unit] [-g geom]\n"
5486d7f5d3SJohn Marino 	    "                      [-m chnl_set] [chnl | freq]\n");
5586d7f5d3SJohn Marino }
5686d7f5d3SJohn Marino 
5786d7f5d3SJohn Marino int
main(int argc,char * argv[])5886d7f5d3SJohn Marino main(int argc, char *argv[])
5986d7f5d3SJohn Marino {
6086d7f5d3SJohn Marino 	char *ptr;
6186d7f5d3SJohn Marino 	char *endptr;
6286d7f5d3SJohn Marino 	char buf[255];
6386d7f5d3SJohn Marino 	int afc;
6486d7f5d3SJohn Marino 	int audio;
6586d7f5d3SJohn Marino 	int c;
6686d7f5d3SJohn Marino 	int channel_set;
6786d7f5d3SJohn Marino 	int i;
6886d7f5d3SJohn Marino 	int status;
6986d7f5d3SJohn Marino 	int tfd;
7086d7f5d3SJohn Marino 	int unit;
7186d7f5d3SJohn Marino 	unsigned int channel;
7286d7f5d3SJohn Marino 	unsigned int fraction;
7386d7f5d3SJohn Marino 	unsigned int freq;
7486d7f5d3SJohn Marino 	unsigned int x_size;
7586d7f5d3SJohn Marino 	unsigned int y_size;
7686d7f5d3SJohn Marino 	unsigned long device;
7786d7f5d3SJohn Marino 	struct bktr_capture_area cap;
7886d7f5d3SJohn Marino 
7986d7f5d3SJohn Marino 	afc = -1;
8086d7f5d3SJohn Marino 	audio = -1;
8186d7f5d3SJohn Marino 	channel = 0;
8286d7f5d3SJohn Marino 	channel_set = -1;
8386d7f5d3SJohn Marino 	device = 0;
8486d7f5d3SJohn Marino 	unit = 0;
8586d7f5d3SJohn Marino 	freq = 0;
8686d7f5d3SJohn Marino 	status = 0;
8786d7f5d3SJohn Marino 	x_size = 0;
8886d7f5d3SJohn Marino 	y_size = 0;
8986d7f5d3SJohn Marino 
9086d7f5d3SJohn Marino 	while ((c = getopt(argc, argv, "a:crstg:m:d:")) != -1)
9186d7f5d3SJohn Marino 		switch (c) {
9286d7f5d3SJohn Marino 		case 'a':
9386d7f5d3SJohn Marino 			if (strcasecmp(optarg, "on") == 0)
9486d7f5d3SJohn Marino 				afc = 1;
9586d7f5d3SJohn Marino 			else if (strcasecmp(optarg, "off") == 0)
9686d7f5d3SJohn Marino 				afc = 0;
9786d7f5d3SJohn Marino 			else {
9886d7f5d3SJohn Marino 				usage();
9986d7f5d3SJohn Marino 				exit(1);
10086d7f5d3SJohn Marino 			}
10186d7f5d3SJohn Marino 			break;
10286d7f5d3SJohn Marino 
10386d7f5d3SJohn Marino 		case 'c':
10486d7f5d3SJohn Marino 			device = METEOR_INPUT_DEV2;
10586d7f5d3SJohn Marino 			audio = -1;
10686d7f5d3SJohn Marino 			break;
10786d7f5d3SJohn Marino 
10886d7f5d3SJohn Marino 		case 'd':
10986d7f5d3SJohn Marino 			unit = atoi(optarg);
11086d7f5d3SJohn Marino 			break;
11186d7f5d3SJohn Marino 
11286d7f5d3SJohn Marino 		case 'r':
11386d7f5d3SJohn Marino 			device = 0;
11486d7f5d3SJohn Marino 			audio = AUDIO_INTERN;
11586d7f5d3SJohn Marino 			break;
11686d7f5d3SJohn Marino 
11786d7f5d3SJohn Marino 		case 's':
11886d7f5d3SJohn Marino 			device = METEOR_INPUT_DEV_SVIDEO;
11986d7f5d3SJohn Marino 			audio = -1;
12086d7f5d3SJohn Marino 			break;
12186d7f5d3SJohn Marino 
12286d7f5d3SJohn Marino 		case 't':
12386d7f5d3SJohn Marino 			device = METEOR_INPUT_DEV1;
12486d7f5d3SJohn Marino 			audio = -1;
12586d7f5d3SJohn Marino 			break;
12686d7f5d3SJohn Marino 
12786d7f5d3SJohn Marino 		case 'g':
12886d7f5d3SJohn Marino 			if (sscanf(optarg, "%ux%u", &x_size, &y_size) != 2 ||
12986d7f5d3SJohn Marino 			    x_size == 0 || y_size == 0) {
13086d7f5d3SJohn Marino 				usage();
13186d7f5d3SJohn Marino 				exit(1);
13286d7f5d3SJohn Marino 			}
13386d7f5d3SJohn Marino 			break;
13486d7f5d3SJohn Marino 
13586d7f5d3SJohn Marino 		case 'm':
13686d7f5d3SJohn Marino 			channel_set = atoi(optarg);
13786d7f5d3SJohn Marino 			if (channel_set < 0 || channel_set > CHNLSET_MAX) {
13886d7f5d3SJohn Marino 				usage();
13986d7f5d3SJohn Marino 				exit(1);
14086d7f5d3SJohn Marino 			}
14186d7f5d3SJohn Marino 			break;
14286d7f5d3SJohn Marino 
14386d7f5d3SJohn Marino 		default:
14486d7f5d3SJohn Marino 			usage();
14586d7f5d3SJohn Marino 			exit(1);
14686d7f5d3SJohn Marino 		}
14786d7f5d3SJohn Marino 
14886d7f5d3SJohn Marino 	if (optind < argc) {
14986d7f5d3SJohn Marino 
15086d7f5d3SJohn Marino 		/*
15186d7f5d3SJohn Marino 		 * A number containing a decimal point is the frequency in
15286d7f5d3SJohn Marino 		 * MHz.
15386d7f5d3SJohn Marino 		 */
15486d7f5d3SJohn Marino 
15586d7f5d3SJohn Marino 		if ((ptr = strchr(argv[optind], '.')) != NULL) {
15686d7f5d3SJohn Marino 			freq = strtol(argv[optind], &endptr, 10) * 1000;
15786d7f5d3SJohn Marino 			if (ptr != endptr) {
15886d7f5d3SJohn Marino 				usage();
15986d7f5d3SJohn Marino 				exit(1);
16086d7f5d3SJohn Marino 			}
16186d7f5d3SJohn Marino 			ptr++;
16286d7f5d3SJohn Marino 
16386d7f5d3SJohn Marino 			fraction = strtol(ptr, &endptr, 10);
16486d7f5d3SJohn Marino 			if (!isdigit(*ptr) || *endptr != '\0') {
16586d7f5d3SJohn Marino 				usage();
16686d7f5d3SJohn Marino 				exit(1);
16786d7f5d3SJohn Marino 			}
16886d7f5d3SJohn Marino 			for (i = endptr - ptr; i > 3; i--)
16986d7f5d3SJohn Marino 				fraction /= 10;
17086d7f5d3SJohn Marino 			for (; i < 3; i++)
17186d7f5d3SJohn Marino 				fraction *= 10;
17286d7f5d3SJohn Marino 
17386d7f5d3SJohn Marino 			freq += fraction;
17486d7f5d3SJohn Marino 		}
17586d7f5d3SJohn Marino 		/*
17686d7f5d3SJohn Marino 		 * An integer is the channel.
17786d7f5d3SJohn Marino 		 */
17886d7f5d3SJohn Marino 
17986d7f5d3SJohn Marino 		else
18086d7f5d3SJohn Marino 			channel = atoi(argv[optind]);
18186d7f5d3SJohn Marino 	}
18286d7f5d3SJohn Marino 	if (afc == -1 && audio == -1 && !device && x_size == 0 &&
18386d7f5d3SJohn Marino 	    y_size == 0 && channel_set == -1 && !channel && !freq) {
18486d7f5d3SJohn Marino 		usage();
18586d7f5d3SJohn Marino 		exit(1);
18686d7f5d3SJohn Marino 	}
18786d7f5d3SJohn Marino 
18886d7f5d3SJohn Marino 	sprintf(buf, "/dev/cxm%d", unit);
18986d7f5d3SJohn Marino 
19086d7f5d3SJohn Marino 	tfd = open(buf, O_RDONLY);
19186d7f5d3SJohn Marino 	if (tfd < 0) {
19286d7f5d3SJohn Marino 		warn("open() of /dev/cxm%d failed.", unit);
19386d7f5d3SJohn Marino 		exit(1);
19486d7f5d3SJohn Marino 	}
19586d7f5d3SJohn Marino 
19686d7f5d3SJohn Marino 	if (afc != -1) {
19786d7f5d3SJohn Marino 		if (ioctl(tfd, TVTUNER_SETAFC, &afc) < 0) {
19886d7f5d3SJohn Marino 			warn("ioctl( tfd, TVTUNER_SETAFC ) failed.");
19986d7f5d3SJohn Marino 			status = 1;
20086d7f5d3SJohn Marino 		}
20186d7f5d3SJohn Marino 	}
20286d7f5d3SJohn Marino 	if (device) {
20386d7f5d3SJohn Marino 		if (ioctl(tfd, METEORSINPUT, &device) < 0) {
20486d7f5d3SJohn Marino 			warn("ioctl( tfd, METEORSINPUT ) failed.");
20586d7f5d3SJohn Marino 			status = 1;
20686d7f5d3SJohn Marino 		}
20786d7f5d3SJohn Marino 	}
20886d7f5d3SJohn Marino 	if (audio != -1) {
20986d7f5d3SJohn Marino 		if (ioctl(tfd, BT848_SAUDIO, &audio) < 0) {
21086d7f5d3SJohn Marino 			warn("ioctl( tfd, BT848_SAUDIO ) failed.");
21186d7f5d3SJohn Marino 			status = 1;
21286d7f5d3SJohn Marino 		}
21386d7f5d3SJohn Marino 	}
21486d7f5d3SJohn Marino 	if (ioctl(tfd, BT848_GAUDIO, &audio) < 0) {
21586d7f5d3SJohn Marino 		warn("ioctl( tfd, BT848_GAUDIO ) failed.");
21686d7f5d3SJohn Marino 		status = 1;
21786d7f5d3SJohn Marino 	}
21886d7f5d3SJohn Marino 	if (x_size && y_size) {
21986d7f5d3SJohn Marino 		memset(&cap, 0, sizeof(cap));
22086d7f5d3SJohn Marino 		cap.x_size = x_size;
22186d7f5d3SJohn Marino 		cap.y_size = y_size;
22286d7f5d3SJohn Marino 		if (ioctl(tfd, BT848_SCAPAREA, &cap) < 0) {
22386d7f5d3SJohn Marino 			warn("ioctl( tfd, BT848_SCAPAREA ) failed.");
22486d7f5d3SJohn Marino 			status = 1;
22586d7f5d3SJohn Marino 		}
22686d7f5d3SJohn Marino 	}
22786d7f5d3SJohn Marino 	if (channel_set != -1) {
22886d7f5d3SJohn Marino 		if (ioctl(tfd, TVTUNER_SETTYPE, &channel_set) < 0) {
22986d7f5d3SJohn Marino 			warn("ioctl( tfd, TVTUNER_SETTYPE ) failed.");
23086d7f5d3SJohn Marino 			status = 1;
23186d7f5d3SJohn Marino 		}
23286d7f5d3SJohn Marino 	}
23386d7f5d3SJohn Marino 	if (channel) {
23486d7f5d3SJohn Marino 		if (ioctl(tfd, TVTUNER_SETCHNL, &channel) < 0) {
23586d7f5d3SJohn Marino 			warn("ioctl( tfd, TVTUNER_SETCHNL ) failed.");
23686d7f5d3SJohn Marino 			status = 1;
23786d7f5d3SJohn Marino 		}
23886d7f5d3SJohn Marino 	} else if (freq) {
23986d7f5d3SJohn Marino 		if (audio == AUDIO_INTERN) {
24086d7f5d3SJohn Marino 			/* Convert from kHz to MHz * 100 */
24186d7f5d3SJohn Marino 			freq = freq / 10;
24286d7f5d3SJohn Marino 
24386d7f5d3SJohn Marino 			if (ioctl(tfd, RADIO_SETFREQ, &freq) < 0) {
24486d7f5d3SJohn Marino 				warn("ioctl( tfd, RADIO_SETFREQ ) failed.");
24586d7f5d3SJohn Marino 				status = 1;
24686d7f5d3SJohn Marino 			}
24786d7f5d3SJohn Marino 		} else {
24886d7f5d3SJohn Marino 			/* Convert from kHz to MHz * 16 */
24986d7f5d3SJohn Marino 			freq = (freq * 16) / 1000;
25086d7f5d3SJohn Marino 
25186d7f5d3SJohn Marino 			if (ioctl(tfd, TVTUNER_SETFREQ, &freq) < 0) {
25286d7f5d3SJohn Marino 				warn("ioctl( tfd, TVTUNER_SETFREQ ) failed.");
25386d7f5d3SJohn Marino 				status = 1;
25486d7f5d3SJohn Marino 			}
25586d7f5d3SJohn Marino 		}
25686d7f5d3SJohn Marino 	}
25786d7f5d3SJohn Marino 	close(tfd);
25886d7f5d3SJohn Marino 	exit(status);
25986d7f5d3SJohn Marino }
260