~ubuntu-branches/ubuntu/trusty/v4l-utils/trusty

« back to all changes in this revision

Viewing changes to utils/v4l2-ctl/v4l2-ctl-tuner.cpp

  • Committer: Package Import Robot
  • Author(s): Gregor Jasny
  • Date: 2012-10-09 18:38:05 UTC
  • mfrom: (11.1.15 sid)
  • Revision ID: package-import@ubuntu.com-20121009183805-v1m5kb2a1i97rw9y
* Imported Upstream version 0.8.9
  - libv4lconvert: Various Pixart JPEG fixes
  - libv4lconvert: Add more notebooks to the upside down device table
  - keytable: Add support for Sanyo IR and RC-5-SZ protocol
  - keytable: Add missing buttons in shipped keytables (LP: #1054122)
  - v4l2-compliance, v4l-ctl, qv4l2: Sync with development branch
* Drop 32bit cross compiled libraries

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <unistd.h>
 
2
#include <stdlib.h>
 
3
#include <stdio.h>
 
4
#include <string.h>
 
5
#include <inttypes.h>
 
6
#include <getopt.h>
 
7
#include <sys/types.h>
 
8
#include <sys/stat.h>
 
9
#include <fcntl.h>
 
10
#include <ctype.h>
 
11
#include <errno.h>
 
12
#include <sys/ioctl.h>
 
13
#include <sys/time.h>
 
14
#include <dirent.h>
 
15
#include <math.h>
 
16
 
 
17
#include <linux/videodev2.h>
 
18
#include <libv4l2.h>
 
19
#include <string>
 
20
 
 
21
#include "v4l2-ctl.h"
 
22
 
 
23
static int tuner_index;
 
24
static struct v4l2_tuner tuner;         /* set_freq/get_freq */
 
25
static struct v4l2_modulator modulator; /* set_freq/get_freq */
 
26
static int txsubchans;                  /* set_modulator */
 
27
static double freq;                     /* get/set frequency */
 
28
static struct v4l2_frequency vf;        /* get_freq/set_freq */
 
29
static struct v4l2_hw_freq_seek freq_seek; /* freq-seek */
 
30
static double low, high;                /* freq-seek frequency range */
 
31
static int mode = V4L2_TUNER_MODE_STEREO;  /* set audio mode */
 
32
 
 
33
void tuner_usage(void)
 
34
{
 
35
        printf("\nTuner/Modulator options:\n"
 
36
               "  -F, --get-freq     query the frequency [VIDIOC_G_FREQUENCY]\n"
 
37
               "  -f, --set-freq=<freq>\n"
 
38
               "                     set the frequency to <freq> MHz [VIDIOC_S_FREQUENCY]\n"
 
39
               "  -T, --get-tuner    query the tuner settings [VIDIOC_G_TUNER]\n"
 
40
               "  -t, --set-tuner=<mode>\n"
 
41
               "                     set the audio mode of the tuner [VIDIOC_S_TUNER]\n"
 
42
               "                     Possible values: mono, stereo, lang2, lang1, bilingual\n"
 
43
               "  --tuner-index=<idx> Use idx as tuner idx for tuner/modulator commands\n"
 
44
               "  --list-freq-bands  display all frequency bands for the tuner/modulator\n"
 
45
               "                     [VIDIOC_ENUM_FREQ_BANDS]\n"
 
46
               "  --get-modulator    query the modulator settings [VIDIOC_G_MODULATOR]\n"
 
47
               "  --set-modulator=<txsubchans>\n"
 
48
               "                     set the sub-carrier modulation [VIDIOC_S_MODULATOR]\n"
 
49
               "                     <txsubchans> is one of:\n"
 
50
               "                     mono:       Modulate as mono\n"
 
51
               "                     mono-rds:   Modulate as mono with RDS (radio only)\n"
 
52
               "                     stereo:     Modulate as stereo\n"
 
53
               "                     stereo-rds: Modulate as stereo with RDS (radio only)\n"
 
54
               "                     bilingual:  Modulate as bilingual\n"
 
55
               "                     mono-sap:   Modulate as mono with Second Audio Program\n"
 
56
               "                     stereo-sap: Modulate as stereo with Second Audio Program\n"
 
57
               "  --freq-seek=dir=<0/1>,wrap=<0/1>,spacing=<hz>,low=<freq>,high=<freq>\n"
 
58
               "                     perform a hardware frequency seek [VIDIOC_S_HW_FREQ_SEEK]\n"
 
59
               "                     dir is 0 (seek downward) or 1 (seek upward)\n"
 
60
               "                     wrap is 0 (do not wrap around) or 1 (wrap around)\n"
 
61
               "                     spacing sets the seek resolution (use 0 for default)\n"
 
62
               "                     low and high set the low and high seek frequency range in MHz\n"
 
63
               );
 
64
}
 
65
 
 
66
static const char *audmode2s(int audmode)
 
67
{
 
68
        switch (audmode) {
 
69
                case V4L2_TUNER_MODE_STEREO: return "stereo";
 
70
                case V4L2_TUNER_MODE_LANG1: return "lang1";
 
71
                case V4L2_TUNER_MODE_LANG2: return "lang2";
 
72
                case V4L2_TUNER_MODE_LANG1_LANG2: return "bilingual";
 
73
                case V4L2_TUNER_MODE_MONO: return "mono";
 
74
                default: return "unknown";
 
75
        }
 
76
}
 
77
 
 
78
static std::string rxsubchans2s(int rxsubchans)
 
79
{
 
80
        std::string s;
 
81
 
 
82
        if (rxsubchans & V4L2_TUNER_SUB_MONO)
 
83
                s += "mono ";
 
84
        if (rxsubchans & V4L2_TUNER_SUB_STEREO)
 
85
                s += "stereo ";
 
86
        if (rxsubchans & V4L2_TUNER_SUB_LANG1)
 
87
                s += "lang1 ";
 
88
        if (rxsubchans & V4L2_TUNER_SUB_LANG2)
 
89
                s += "lang2 ";
 
90
        if (rxsubchans & V4L2_TUNER_SUB_RDS)
 
91
                s += "rds ";
 
92
        return s;
 
93
}
 
94
 
 
95
static std::string txsubchans2s(int txsubchans)
 
96
{
 
97
        std::string s;
 
98
 
 
99
        if (txsubchans & V4L2_TUNER_SUB_MONO)
 
100
                s += "mono ";
 
101
        if (txsubchans & V4L2_TUNER_SUB_STEREO)
 
102
                s += "stereo ";
 
103
        if (txsubchans & V4L2_TUNER_SUB_LANG1)
 
104
                s += "bilingual ";
 
105
        if (txsubchans & V4L2_TUNER_SUB_SAP)
 
106
                s += "sap ";
 
107
        if (txsubchans & V4L2_TUNER_SUB_RDS)
 
108
                s += "rds ";
 
109
        return s;
 
110
}
 
111
 
 
112
static std::string tcap2s(unsigned cap)
 
113
{
 
114
        std::string s;
 
115
 
 
116
        if (cap & V4L2_TUNER_CAP_LOW)
 
117
                s += "62.5 Hz ";
 
118
        else
 
119
                s += "62.5 kHz ";
 
120
        if (cap & V4L2_TUNER_CAP_NORM)
 
121
                s += "multi-standard ";
 
122
        if (cap & V4L2_TUNER_CAP_HWSEEK_BOUNDED)
 
123
                s += "hwseek-bounded ";
 
124
        if (cap & V4L2_TUNER_CAP_HWSEEK_WRAP)
 
125
                s += "hwseek-wrap ";
 
126
        if (cap & V4L2_TUNER_CAP_STEREO)
 
127
                s += "stereo ";
 
128
        if (cap & V4L2_TUNER_CAP_LANG1)
 
129
                s += "lang1 ";
 
130
        if (cap & V4L2_TUNER_CAP_LANG2)
 
131
                s += "lang2 ";
 
132
        if (cap & V4L2_TUNER_CAP_RDS)
 
133
                s += "rds ";
 
134
        if (cap & V4L2_TUNER_CAP_RDS_BLOCK_IO)
 
135
                s += "rds-block-I/O ";
 
136
        if (cap & V4L2_TUNER_CAP_RDS_CONTROLS)
 
137
                s += "rds-controls ";
 
138
        if (cap & V4L2_TUNER_CAP_FREQ_BANDS)
 
139
                s += "freq-bands ";
 
140
        if (cap & V4L2_TUNER_CAP_HWSEEK_PROG_LIM)
 
141
                s += "hwseek-prog-lim ";
 
142
        return s;
 
143
}
 
144
 
 
145
static std::string modulation2s(unsigned modulation)
 
146
{
 
147
        switch (modulation) {
 
148
        case V4L2_BAND_MODULATION_VSB:
 
149
                return "VSB";
 
150
        case V4L2_BAND_MODULATION_FM:
 
151
                return "FM";
 
152
        case V4L2_BAND_MODULATION_AM:
 
153
                return "AM";
 
154
        }
 
155
        return "Unknown";
 
156
}
 
157
 
 
158
static void parse_freq_seek(char *optarg, struct v4l2_hw_freq_seek &seek)
 
159
{
 
160
        char *value;
 
161
        char *subs = optarg;
 
162
 
 
163
        while (*subs != '\0') {
 
164
                static const char *const subopts[] = {
 
165
                        "dir",
 
166
                        "wrap",
 
167
                        "spacing",
 
168
                        "low",
 
169
                        "high",
 
170
                        NULL
 
171
                };
 
172
 
 
173
                switch (parse_subopt(&subs, subopts, &value)) {
 
174
                case 0:
 
175
                        seek.seek_upward = strtol(value, 0L, 0);
 
176
                        break;
 
177
                case 1:
 
178
                        seek.wrap_around = strtol(value, 0L, 0);
 
179
                        break;
 
180
                case 2:
 
181
                        seek.spacing = strtol(value, 0L, 0);
 
182
                        break;
 
183
                case 3:
 
184
                        low = strtod(value, NULL);
 
185
                        break;
 
186
                case 4:
 
187
                        high = strtod(value, NULL);
 
188
                        break;
 
189
                default:
 
190
                        tuner_usage();
 
191
                        exit(1);
 
192
                }
 
193
        }
 
194
}
 
195
 
 
196
void tuner_cmd(int ch, char *optarg)
 
197
{
 
198
        switch (ch) {
 
199
        case OptSetFreq:
 
200
                freq = strtod(optarg, NULL);
 
201
                break;
 
202
        case OptSetTuner:
 
203
                if (!strcmp(optarg, "stereo"))
 
204
                        mode = V4L2_TUNER_MODE_STEREO;
 
205
                else if (!strcmp(optarg, "lang1"))
 
206
                        mode = V4L2_TUNER_MODE_LANG1;
 
207
                else if (!strcmp(optarg, "lang2"))
 
208
                        mode = V4L2_TUNER_MODE_LANG2;
 
209
                else if (!strcmp(optarg, "bilingual"))
 
210
                        mode = V4L2_TUNER_MODE_LANG1_LANG2;
 
211
                else if (!strcmp(optarg, "mono"))
 
212
                        mode = V4L2_TUNER_MODE_MONO;
 
213
                else {
 
214
                        fprintf(stderr, "Unknown audio mode\n");
 
215
                        tuner_usage();
 
216
                        exit(1);
 
217
                }
 
218
                break;
 
219
        case OptSetModulator:
 
220
                txsubchans = strtol(optarg, 0L, 0);
 
221
                if (!strcmp(optarg, "stereo"))
 
222
                        txsubchans = V4L2_TUNER_SUB_STEREO;
 
223
                else if (!strcmp(optarg, "stereo-sap"))
 
224
                        txsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_SAP;
 
225
                else if (!strcmp(optarg, "bilingual"))
 
226
                        txsubchans = V4L2_TUNER_SUB_LANG1;
 
227
                else if (!strcmp(optarg, "mono"))
 
228
                        txsubchans = V4L2_TUNER_SUB_MONO;
 
229
                else if (!strcmp(optarg, "mono-sap"))
 
230
                        txsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_SAP;
 
231
                else if (!strcmp(optarg, "stereo-rds"))
 
232
                        txsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_RDS;
 
233
                else if (!strcmp(optarg, "mono-rds"))
 
234
                        txsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_RDS;
 
235
                else {
 
236
                        fprintf(stderr, "Unknown txsubchans value\n");
 
237
                        tuner_usage();
 
238
                        exit(1);
 
239
                }
 
240
                break;
 
241
        case OptFreqSeek:
 
242
                parse_freq_seek(optarg, freq_seek);
 
243
                break;
 
244
        case OptTunerIndex:
 
245
                tuner_index = strtoul(optarg, NULL, 0);
 
246
                break;
 
247
        }
 
248
}
 
249
 
 
250
void tuner_set(int fd)
 
251
{
 
252
        __u32 type = (capabilities & V4L2_CAP_RADIO) ?
 
253
                V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 
254
        double fac = 16;
 
255
 
 
256
        if (capabilities & V4L2_CAP_MODULATOR) {
 
257
                type = V4L2_TUNER_RADIO;
 
258
                modulator.index = tuner_index;
 
259
                if (doioctl(fd, VIDIOC_G_MODULATOR, &modulator) == 0)
 
260
                        fac = (modulator.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
 
261
        } else if (capabilities & V4L2_CAP_TUNER) {
 
262
                tuner.index = tuner_index;
 
263
                if (doioctl(fd, VIDIOC_G_TUNER, &tuner) == 0) {
 
264
                        fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
 
265
                        type = tuner.type;
 
266
                }
 
267
        }
 
268
        if (options[OptSetFreq]) {
 
269
                vf.type = type;
 
270
                vf.tuner = tuner_index;
 
271
                vf.frequency = __u32(freq * fac);
 
272
                if (doioctl(fd, VIDIOC_S_FREQUENCY, &vf) == 0)
 
273
                        printf("Frequency for tuner %d set to %d (%f MHz)\n",
 
274
                               vf.tuner, vf.frequency, vf.frequency / fac);
 
275
        }
 
276
 
 
277
        if (options[OptSetTuner]) {
 
278
                struct v4l2_tuner vt;
 
279
 
 
280
                memset(&vt, 0, sizeof(struct v4l2_tuner));
 
281
                vt.index = tuner_index;
 
282
                if (doioctl(fd, VIDIOC_G_TUNER, &vt) == 0) {
 
283
                        vt.audmode = mode;
 
284
                        doioctl(fd, VIDIOC_S_TUNER, &vt);
 
285
                }
 
286
        }
 
287
 
 
288
        if (options[OptListFreqBands]) {
 
289
                struct v4l2_frequency_band band;
 
290
 
 
291
                memset(&band, 0, sizeof(band));
 
292
                band.tuner = tuner_index;
 
293
                band.type = type;
 
294
                band.index = 0;
 
295
                printf("ioctl: VIDIOC_ENUM_FREQ_BANDS\n");
 
296
                while (test_ioctl(fd, VIDIOC_ENUM_FREQ_BANDS, &band) >= 0) {
 
297
                        if (band.index)
 
298
                                printf("\n");
 
299
                        printf("\tIndex          : %d\n", band.index);
 
300
                        printf("\tModulation     : %s\n", modulation2s(band.modulation).c_str());
 
301
                        printf("\tCapability     : %s\n", tcap2s(band.capability).c_str());
 
302
                        if (band.capability & V4L2_TUNER_CAP_LOW)
 
303
                                printf("\tFrequency Range: %.3f MHz - %.3f MHz\n",
 
304
                                     band.rangelow / 16000.0, band.rangehigh / 16000.0);
 
305
                        else
 
306
                                printf("\tFrequency Range: %.3f MHz - %.3f MHz\n",
 
307
                                     band.rangelow / 16.0, band.rangehigh / 16.0);
 
308
                        band.index++;
 
309
                }
 
310
        }
 
311
 
 
312
        if (options[OptSetModulator]) {
 
313
                struct v4l2_modulator mt;
 
314
 
 
315
                memset(&mt, 0, sizeof(struct v4l2_modulator));
 
316
                mt.index = tuner_index;
 
317
                if (doioctl(fd, VIDIOC_G_MODULATOR, &mt) == 0) {
 
318
                        mt.txsubchans = txsubchans;
 
319
                        doioctl(fd, VIDIOC_S_MODULATOR, &mt);
 
320
                }
 
321
        }
 
322
 
 
323
        if (options[OptFreqSeek]) {
 
324
                freq_seek.tuner = tuner_index;
 
325
                freq_seek.type = type;
 
326
                freq_seek.rangelow = __u32(low * fac);
 
327
                freq_seek.rangehigh = __u32(high * fac);
 
328
                doioctl(fd, VIDIOC_S_HW_FREQ_SEEK, &freq_seek);
 
329
        }
 
330
}
 
331
 
 
332
void tuner_get(int fd)
 
333
{
 
334
        if (options[OptGetFreq]) {
 
335
                double fac = 16;
 
336
 
 
337
                if (capabilities & V4L2_CAP_MODULATOR) {
 
338
                        vf.type = V4L2_TUNER_RADIO;
 
339
                        modulator.index = tuner_index;
 
340
                        if (doioctl(fd, VIDIOC_G_MODULATOR, &modulator) == 0)
 
341
                                fac = (modulator.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
 
342
                } else {
 
343
                        vf.type = V4L2_TUNER_ANALOG_TV;
 
344
                        tuner.index = tuner_index;
 
345
                        if (doioctl(fd, VIDIOC_G_TUNER, &tuner) == 0) {
 
346
                                fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
 
347
                                vf.type = tuner.type;
 
348
                        }
 
349
                }
 
350
                vf.tuner = tuner_index;
 
351
                if (doioctl(fd, VIDIOC_G_FREQUENCY, &vf) == 0)
 
352
                        printf("Frequency for tuner %d: %d (%f MHz)\n",
 
353
                               vf.tuner, vf.frequency, vf.frequency / fac);
 
354
        }
 
355
 
 
356
        if (options[OptGetTuner]) {
 
357
                struct v4l2_tuner vt;
 
358
 
 
359
                memset(&vt, 0, sizeof(struct v4l2_tuner));
 
360
                vt.index = tuner_index;
 
361
                if (doioctl(fd, VIDIOC_G_TUNER, &vt) == 0) {
 
362
                        printf("Tuner %d:\n", vt.index);
 
363
                        printf("\tName                 : %s\n", vt.name);
 
364
                        printf("\tCapabilities         : %s\n", tcap2s(vt.capability).c_str());
 
365
                        if (vt.capability & V4L2_TUNER_CAP_LOW)
 
366
                                printf("\tFrequency range      : %.3f MHz - %.3f MHz\n",
 
367
                                     vt.rangelow / 16000.0, vt.rangehigh / 16000.0);
 
368
                        else
 
369
                                printf("\tFrequency range      : %.3f MHz - %.3f MHz\n",
 
370
                                     vt.rangelow / 16.0, vt.rangehigh / 16.0);
 
371
                        printf("\tSignal strength/AFC  : %d%%/%d\n", (int)((vt.signal / 655.35)+0.5), vt.afc);
 
372
                        printf("\tCurrent audio mode   : %s\n", audmode2s(vt.audmode));
 
373
                        printf("\tAvailable subchannels: %s\n",
 
374
                                        rxsubchans2s(vt.rxsubchans).c_str());
 
375
                }
 
376
        }
 
377
 
 
378
        if (options[OptGetModulator]) {
 
379
                struct v4l2_modulator mt;
 
380
 
 
381
                memset(&mt, 0, sizeof(struct v4l2_modulator));
 
382
                modulator.index = tuner_index;
 
383
                if (doioctl(fd, VIDIOC_G_MODULATOR, &mt) == 0) {
 
384
                        printf("Modulator %d:\n", modulator.index);
 
385
                        printf("\tName                 : %s\n", mt.name);
 
386
                        printf("\tCapabilities         : %s\n", tcap2s(mt.capability).c_str());
 
387
                        if (mt.capability & V4L2_TUNER_CAP_LOW)
 
388
                                printf("\tFrequency range      : %.1f MHz - %.1f MHz\n",
 
389
                                     mt.rangelow / 16000.0, mt.rangehigh / 16000.0);
 
390
                        else
 
391
                                printf("\tFrequency range      : %.1f MHz - %.1f MHz\n",
 
392
                                     mt.rangelow / 16.0, mt.rangehigh / 16.0);
 
393
                        printf("\tSubchannel modulation: %s\n",
 
394
                                        txsubchans2s(mt.txsubchans).c_str());
 
395
                }
 
396
        }
 
397
}
 
398
 
 
399
void tuner_list(int fd)
 
400
{
 
401
}