1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2003, 2004, 2005 5 * John Wehle <john@feith.com>. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD: stable/11/usr.bin/setchannel/setchannel.c 330449 2018-03-05 07:26:05Z eadler $ 29 */ 30 31/* Set the channel of the tuner card. */ 32 33#include <sys/ioctl.h> 34#include <sys/param.h> 35 36#include <ctype.h> 37#include <errno.h> 38#include <fcntl.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include <unistd.h> 43 44#include <dev/bktr/ioctl_meteor.h> 45#include <dev/bktr/ioctl_bt848.h> 46 47static void 48usage(void) 49{ 50 printf 51 ("Usage: setchannel [-a {on|off}] [-c | -r | -s | -t] " 52 "[-g geom] [-m chnl_set] [chnl | freq]\n" 53 " -a Enable / disable AFC.\n" 54 " -c Select composite input.\n" 55 " -d Select tuner unit number.\n" 56 " -r Select radio input.\n" 57 " -s Select svideo input.\n" 58 " -t Select tuner.\n" 59 " -g Select geometry.\n" 60 " 352x240 or 352x288 = VCD\n" 61 " 480x480 or 480x576 = SVCD\n" 62 " 352x480 or 352x576 = DVD (half D1)\n" 63 " 720x480 or 720x576 = DVD (full D1)\n" 64 " -m Select channel set / system.\n" 65 " 0 = Tuner Default\n" 66 " %u = US Broadcast / NTSC\n" 67 " %u = US Cable / NTSC\n" 68 " %u = Western Europe / PAL\n" 69 " %u = Japan Broadcast / NTSC\n" 70 " %u = Japan Cable / NTSC\n" 71 " %u = Australia / PAL\n" 72 " %u = France / SECAM\n" 73 " chnl Channel\n" 74 " freq Frequency in MHz (must include decimal point).\n", 75 CHNLSET_NABCST, CHNLSET_CABLEIRC, CHNLSET_WEUROPE, CHNLSET_JPNBCST, 76 CHNLSET_JPNCABLE, CHNLSET_AUSTRALIA, CHNLSET_FRANCE); 77} 78 79#define DEVNAME_BASE "/dev/cxm" 80char dev_name[16]; 81 82int 83main(int argc, char *argv[]) 84{ 85 char *ptr; 86 char *endptr; 87 int afc; 88 int audio; 89 int c; 90 int channel_set; 91 int i; 92 int status; 93 int unit; 94 int tfd; 95 unsigned int channel; 96 unsigned int fraction; 97 unsigned int freq; 98 unsigned int x_size; 99 unsigned int y_size; 100 unsigned long device; 101 struct bktr_capture_area cap; 102 103 afc = -1; 104 audio = -1; 105 channel = 0; 106 channel_set = -1; 107 device = 0; 108 freq = 0; 109 status = 0; 110 unit = 0; 111 x_size = 0; 112 y_size = 0; 113 114 while ((c = getopt(argc, argv, "a:cd:rg:m:st")) != -1) 115 switch (c) { 116 117 case 'a': 118 if (strcasecmp(optarg, "on") == 0) 119 afc = 1; 120 else if (strcasecmp(optarg, "off") == 0) 121 afc = 0; 122 else { 123 usage(); 124 exit(1); 125 } 126 break; 127 128 case 'c': 129 device = METEOR_INPUT_DEV2; 130 audio = -1; 131 break; 132 133 case 'd': 134 unit = atoi(optarg); 135 break; 136 137 case 'r': 138 device = 0; 139 audio = AUDIO_INTERN; 140 break; 141 142 case 's': 143 device = METEOR_INPUT_DEV_SVIDEO; 144 audio = -1; 145 break; 146 147 case 't': 148 device = METEOR_INPUT_DEV1; 149 audio = -1; 150 break; 151 152 case 'g': 153 if (sscanf(optarg, "%ux%u", &x_size, &y_size) != 2 154 || x_size == 0 || y_size == 0) { 155 usage(); 156 exit(1); 157 } 158 break; 159 160 case 'm': 161 channel_set = atoi(optarg); 162 if (channel_set < 0 || channel_set > CHNLSET_MAX) { 163 usage(); 164 exit(1); 165 } 166 break; 167 168 default: 169 usage(); 170 exit(1); 171 } 172 173 if (optind < argc) { 174 175 /* 176 * A number containing a decimal point is the frequency in MHz. 177 */ 178 179 if ((ptr = strchr(argv[optind], '.')) != NULL) { 180 freq = strtol(argv[optind], &endptr, 10) * 1000; 181 if (ptr != endptr) { 182 usage(); 183 exit(1); 184 } 185 186 ptr++; 187 188 fraction = strtol(ptr, &endptr, 10); 189 if (!isdigit(*ptr) || *endptr != '\0') { 190 usage(); 191 exit(1); 192 } 193 194 for (i = endptr - ptr; i > 3; i--) 195 fraction /= 10; 196 for (; i < 3; i++) 197 fraction *= 10; 198 199 freq += fraction; 200 } 201 202 /* An integer is the channel. */ 203 else 204 channel = atoi(argv[optind]); 205 } 206 207 if (afc == -1 && audio == -1 && !device && x_size == 0 && y_size == 0 208 && channel_set == -1 && !channel && !freq) { 209 usage(); 210 exit(1); 211 } 212 213 sprintf(dev_name, DEVNAME_BASE "%d", unit); 214 tfd = open(dev_name, O_RDONLY); 215 if (tfd < 0) { 216 fprintf(stderr, "Can't open %s: %s (%d)\n", dev_name, 217 strerror(errno), errno); 218 exit(1); 219 } 220 221 if (afc != -1) 222 if (ioctl(tfd, TVTUNER_SETAFC, &afc) < 0) { 223 perror("ioctl(tfd, TVTUNER_SETAFC) failed."); 224 status = 1; 225 } 226 227 if (device) 228 if (ioctl(tfd, METEORSINPUT, &device) < 0) { 229 perror("ioctl(tfd, METEORSINPUT) failed."); 230 status = 1; 231 } 232 233 if (audio != -1) 234 if (ioctl(tfd, BT848_SAUDIO, &audio) < 0) { 235 perror("ioctl(tfd, BT848_SAUDIO) failed."); 236 status = 1; 237 } 238 239 if (ioctl(tfd, BT848_GAUDIO, &audio) < 0) { 240 perror("ioctl(tfd, BT848_GAUDIO) failed."); 241 status = 1; 242 } 243 244 if (x_size && y_size) { 245 memset(&cap, 0, sizeof(cap)); 246 cap.x_size = x_size; 247 cap.y_size = y_size; 248 if (ioctl(tfd, BT848_SCAPAREA, &cap) < 0) { 249 perror("ioctl(tfd, BT848_SCAPAREA) failed."); 250 status = 1; 251 } 252 } 253 254 if (channel_set != -1) 255 if (ioctl(tfd, TVTUNER_SETTYPE, &channel_set) < 0) { 256 perror("ioctl(tfd, TVTUNER_SETTYPE) failed."); 257 status = 1; 258 } 259 260 if (channel) { 261 if (ioctl(tfd, TVTUNER_SETCHNL, &channel) < 0) { 262 perror("ioctl(tfd, TVTUNER_SETCHNL) failed."); 263 status = 1; 264 } 265 } else if (freq) { 266 if (audio == AUDIO_INTERN) { 267 /* Convert from kHz to MHz * 100 */ 268 freq = freq / 10; 269 270 if (ioctl(tfd, RADIO_SETFREQ, &freq) < 0) { 271 perror("ioctl(tfd, RADIO_SETFREQ) failed."); 272 status = 1; 273 } 274 } else { 275 /* Convert from kHz to MHz * 16 */ 276 freq = (freq * 16) / 1000; 277 278 if (ioctl(tfd, TVTUNER_SETFREQ, &freq) < 0) { 279 perror("ioctl(tfd, TVTUNER_SETFREQ) failed."); 280 status = 1; 281 } 282 } 283 } 284 285 close(tfd); 286 exit(status); 287} 288