Add cxm(4), a driver for Hauppauge PVR-250/350 video capture cards.
[dragonfly.git] / tools / multimedia / cxm / setchannel / cxm_setchannel.c
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 }