1 /*- 2 * Copyright (c) 2003, 2004, 2005 3 * John Wehle <john@feith.com>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by John Wehle. 16 * 4. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Set the channel of the tuner card. 32 */ 33 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/ioctl.h> 37 38 #include <ctype.h> 39 #include <err.h> 40 #include <fcntl.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 46 #include <dev/video/meteor/ioctl_meteor.h> 47 #include <dev/video/bktr/ioctl_bt848.h> 48 49 static void 50 usage(void) 51 { 52 fprintf(stderr, 53 "usage: cxm_setchannel [-a {on|off}] [-c | -r | -s | -t] [-d unit] [-g geom]\n" 54 " [-m chnl_set] [chnl | freq]\n"); 55 } 56 57 int 58 main(int argc, char *argv[]) 59 { 60 char *ptr; 61 char *endptr; 62 char buf[255]; 63 int afc; 64 int audio; 65 int c; 66 int channel_set; 67 int i; 68 int status; 69 int tfd; 70 int unit; 71 unsigned int channel; 72 unsigned int fraction; 73 unsigned int freq; 74 unsigned int x_size; 75 unsigned int y_size; 76 unsigned long device; 77 struct bktr_capture_area cap; 78 79 afc = -1; 80 audio = -1; 81 channel = 0; 82 channel_set = -1; 83 device = 0; 84 unit = 0; 85 freq = 0; 86 status = 0; 87 x_size = 0; 88 y_size = 0; 89 90 while ((c = getopt(argc, argv, "a:crstg:m:d:")) != -1) 91 switch (c) { 92 case 'a': 93 if (strcasecmp(optarg, "on") == 0) 94 afc = 1; 95 else if (strcasecmp(optarg, "off") == 0) 96 afc = 0; 97 else { 98 usage(); 99 exit(1); 100 } 101 break; 102 103 case 'c': 104 device = METEOR_INPUT_DEV2; 105 audio = -1; 106 break; 107 108 case 'd': 109 unit = atoi(optarg); 110 break; 111 112 case 'r': 113 device = 0; 114 audio = AUDIO_INTERN; 115 break; 116 117 case 's': 118 device = METEOR_INPUT_DEV_SVIDEO; 119 audio = -1; 120 break; 121 122 case 't': 123 device = METEOR_INPUT_DEV1; 124 audio = -1; 125 break; 126 127 case 'g': 128 if (sscanf(optarg, "%ux%u", &x_size, &y_size) != 2 || 129 x_size == 0 || y_size == 0) { 130 usage(); 131 exit(1); 132 } 133 break; 134 135 case 'm': 136 channel_set = atoi(optarg); 137 if (channel_set < 0 || channel_set > CHNLSET_MAX) { 138 usage(); 139 exit(1); 140 } 141 break; 142 143 default: 144 usage(); 145 exit(1); 146 } 147 148 if (optind < argc) { 149 150 /* 151 * A number containing a decimal point is the frequency in 152 * MHz. 153 */ 154 155 if ((ptr = strchr(argv[optind], '.')) != NULL) { 156 freq = strtol(argv[optind], &endptr, 10) * 1000; 157 if (ptr != endptr) { 158 usage(); 159 exit(1); 160 } 161 ptr++; 162 163 fraction = strtol(ptr, &endptr, 10); 164 if (!isdigit(*ptr) || *endptr != '\0') { 165 usage(); 166 exit(1); 167 } 168 for (i = endptr - ptr; i > 3; i--) 169 fraction /= 10; 170 for (; i < 3; i++) 171 fraction *= 10; 172 173 freq += fraction; 174 } 175 /* 176 * An integer is the channel. 177 */ 178 179 else 180 channel = atoi(argv[optind]); 181 } 182 if (afc == -1 && audio == -1 && !device && x_size == 0 && 183 y_size == 0 && channel_set == -1 && !channel && !freq) { 184 usage(); 185 exit(1); 186 } 187 188 sprintf(buf, "/dev/cxm%d", unit); 189 190 tfd = open(buf, O_RDONLY); 191 if (tfd < 0) { 192 warn("open() of /dev/cxm%d failed.", unit); 193 exit(1); 194 } 195 196 if (afc != -1) { 197 if (ioctl(tfd, TVTUNER_SETAFC, &afc) < 0) { 198 warn("ioctl( tfd, TVTUNER_SETAFC ) failed."); 199 status = 1; 200 } 201 } 202 if (device) { 203 if (ioctl(tfd, METEORSINPUT, &device) < 0) { 204 warn("ioctl( tfd, METEORSINPUT ) failed."); 205 status = 1; 206 } 207 } 208 if (audio != -1) { 209 if (ioctl(tfd, BT848_SAUDIO, &audio) < 0) { 210 warn("ioctl( tfd, BT848_SAUDIO ) failed."); 211 status = 1; 212 } 213 } 214 if (ioctl(tfd, BT848_GAUDIO, &audio) < 0) { 215 warn("ioctl( tfd, BT848_GAUDIO ) failed."); 216 status = 1; 217 } 218 if (x_size && y_size) { 219 memset(&cap, 0, sizeof(cap)); 220 cap.x_size = x_size; 221 cap.y_size = y_size; 222 if (ioctl(tfd, BT848_SCAPAREA, &cap) < 0) { 223 warn("ioctl( tfd, BT848_SCAPAREA ) failed."); 224 status = 1; 225 } 226 } 227 if (channel_set != -1) { 228 if (ioctl(tfd, TVTUNER_SETTYPE, &channel_set) < 0) { 229 warn("ioctl( tfd, TVTUNER_SETTYPE ) failed."); 230 status = 1; 231 } 232 } 233 if (channel) { 234 if (ioctl(tfd, TVTUNER_SETCHNL, &channel) < 0) { 235 warn("ioctl( tfd, TVTUNER_SETCHNL ) failed."); 236 status = 1; 237 } 238 } else if (freq) { 239 if (audio == AUDIO_INTERN) { 240 /* Convert from kHz to MHz * 100 */ 241 freq = freq / 10; 242 243 if (ioctl(tfd, RADIO_SETFREQ, &freq) < 0) { 244 warn("ioctl( tfd, RADIO_SETFREQ ) failed."); 245 status = 1; 246 } 247 } else { 248 /* Convert from kHz to MHz * 16 */ 249 freq = (freq * 16) / 1000; 250 251 if (ioctl(tfd, TVTUNER_SETFREQ, &freq) < 0) { 252 warn("ioctl( tfd, TVTUNER_SETFREQ ) failed."); 253 status = 1; 254 } 255 } 256 } 257 close(tfd); 258 exit(status); 259 } 260