@@ -60,6 +60,13 @@ extern FILE *v4l1_log_file;
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
+#define DIV_ROUND_CLOSEST(x, divisor)( \
+{ \
+ typeof(divisor) __divisor = divisor; \
+ (((x) + ((__divisor) / 2)) / (__divisor)); \
+} \
+)
+
struct v4l1_dev_info {
int fd;
int flags;
@@ -983,6 +983,178 @@ int v4l1_ioctl(int fd, unsigned long int request, ...)
break;
}
+
+ case VIDIOCSAUDIO: {
+ struct video_audio *aud = arg;
+ struct v4l2_audio aud2 = { 0, };
+ struct v4l2_tuner tun2 = { 0, };
+
+ aud2.index = aud->audio;
+ result = v4l2_ioctl(fd, VIDIOC_S_AUDIO, &aud2);
+ if (result < 0)
+ break;
+
+ v4l2_set_control(fd, V4L2_CID_AUDIO_VOLUME,
+ aud->volume);
+ v4l2_set_control(fd, V4L2_CID_AUDIO_BASS,
+ aud->bass);
+ v4l2_set_control(fd, V4L2_CID_AUDIO_TREBLE,
+ aud->treble);
+ v4l2_set_control(fd, V4L2_CID_AUDIO_BALANCE,
+ aud->balance);
+ v4l2_set_control(fd, V4L2_CID_AUDIO_MUTE,
+ !!(aud->flags & VIDEO_AUDIO_MUTE));
+
+ result = v4l2_ioctl(fd, VIDIOC_G_TUNER, &tun2);
+ if (result < 0)
+ break;
+ if (result == 0) {
+ switch (aud->mode) {
+ default:
+ case VIDEO_SOUND_MONO:
+ case VIDEO_SOUND_LANG1:
+ tun2.audmode = V4L2_TUNER_MODE_MONO;
+ break;
+ case VIDEO_SOUND_STEREO:
+ tun2.audmode = V4L2_TUNER_MODE_STEREO;
+ break;
+ case VIDEO_SOUND_LANG2:
+ tun2.audmode = V4L2_TUNER_MODE_LANG2;
+ break;
+ }
+ result = v4l2_ioctl(fd, VIDIOC_S_TUNER, &tun2);
+ }
+ break;
+ }
+
+ case VIDIOCGAUDIO: {
+ int i;
+ struct video_audio *aud = arg;
+ struct v4l2_queryctrl qctrl2;
+ struct v4l2_audio aud2 = { 0, };
+ struct v4l2_tuner tun2;
+
+ result = v4l2_ioctl(fd, VIDIOC_G_AUDIO, &aud2);
+ if (result < 0)
+ break;
+
+ memcpy(aud->name, aud2.name,
+ min(sizeof(aud->name), sizeof(aud2.name)));
+ aud->name[sizeof(aud->name) - 1] = 0;
+ aud->audio = aud2.index;
+ aud->flags = 0;
+ i = v4l2_get_control(fd, V4L2_CID_AUDIO_VOLUME);
+ if (i >= 0) {
+ aud->volume = i;
+ aud->flags |= VIDEO_AUDIO_VOLUME;
+ }
+ i = v4l2_get_control(fd, V4L2_CID_AUDIO_BASS);
+ if (i >= 0) {
+ aud->bass = i;
+ aud->flags |= VIDEO_AUDIO_BASS;
+ }
+ i = v4l2_get_control(fd, V4L2_CID_AUDIO_TREBLE);
+ if (i >= 0) {
+ aud->treble = i;
+ aud->flags |= VIDEO_AUDIO_TREBLE;
+ }
+ i = v4l2_get_control(fd, V4L2_CID_AUDIO_BALANCE);
+ if (i >= 0) {
+ aud->balance = i;
+ aud->flags |= VIDEO_AUDIO_BALANCE;
+ }
+ i = v4l2_get_control(fd, V4L2_CID_AUDIO_MUTE);
+ if (i >= 0) {
+ if (i)
+ aud->flags |= VIDEO_AUDIO_MUTE;
+
+ aud->flags |= VIDEO_AUDIO_MUTABLE;
+ }
+ aud->step = 1;
+ qctrl2.id = V4L2_CID_AUDIO_VOLUME;
+ if (v4l2_ioctl(fd, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
+ !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
+ aud->step = qctrl2.step;
+ aud->mode = 0;
+
+ result = v4l2_ioctl(fd, VIDIOC_G_TUNER, &tun2);
+ if (result < 0)
+ break;
+
+ if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
+ aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
+ aud->mode = VIDEO_SOUND_STEREO;
+ else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
+ aud->mode = VIDEO_SOUND_MONO;
+
+ }
+
+ case VIDIOCSVBIFMT: {
+ struct vbi_format *fmt = arg;
+ struct v4l2_format fmt2;
+
+ if (VIDEO_PALETTE_RAW != fmt->sample_format) {
+ result = -EINVAL;
+ break;
+ }
+
+ fmt2.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ fmt2.fmt.vbi.samples_per_line = fmt->samples_per_line;
+ fmt2.fmt.vbi.sampling_rate = fmt->sampling_rate;
+ fmt2.fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+ fmt2.fmt.vbi.start[0] = fmt->start[0];
+ fmt2.fmt.vbi.count[0] = fmt->count[0];
+ fmt2.fmt.vbi.start[1] = fmt->start[1];
+ fmt2.fmt.vbi.count[1] = fmt->count[1];
+ fmt2.fmt.vbi.flags = fmt->flags;
+
+ result = v4l2_ioctl(fd, VIDIOC_TRY_FMT, fmt2);
+ if (result < 0)
+ break;
+
+ if (fmt2.fmt.vbi.samples_per_line != fmt->samples_per_line ||
+ fmt2.fmt.vbi.sampling_rate != fmt->sampling_rate ||
+ fmt2.fmt.vbi.sample_format != V4L2_PIX_FMT_GREY ||
+ fmt2.fmt.vbi.start[0] != fmt->start[0] ||
+ fmt2.fmt.vbi.count[0] != fmt->count[0] ||
+ fmt2.fmt.vbi.start[1] != fmt->start[1] ||
+ fmt2.fmt.vbi.count[1] != fmt->count[1] ||
+ fmt2.fmt.vbi.flags != fmt->flags) {
+ result = -EINVAL;
+ break;
+ }
+ result = v4l2_ioctl(fd, VIDIOC_S_FMT, fmt2);
+
+ }
+
+ case VIDIOCGVBIFMT: {
+ struct vbi_format *fmt = arg;
+ struct v4l2_format fmt2 = { 0, };
+
+ fmt2.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ result = v4l2_ioctl(fd, VIDIOC_G_FMT, &fmt2);
+
+ if (result < 0)
+ break;
+
+ if (fmt2.fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
+ result = -EINVAL;
+ break;
+ }
+
+ fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line;
+ fmt->sampling_rate = fmt2.fmt.vbi.sampling_rate;
+ fmt->sample_format = VIDEO_PALETTE_RAW;
+ fmt->start[0] = fmt2.fmt.vbi.start[0];
+ fmt->count[0] = fmt2.fmt.vbi.count[0];
+ fmt->start[1] = fmt2.fmt.vbi.start[1];
+ fmt->count[1] = fmt2.fmt.vbi.count[1];
+ fmt->flags = fmt2.fmt.vbi.flags & 0x03;
+
+ break;
+ }
+
default:
/* Pass through libv4l2 for applications which are using v4l2 through
libv4l1 (this can happen with the v4l1compat.so wrapper preloaded */