diff options
author | Alexey Klimov <klimov.linux@gmail.com> | 2013-03-14 17:12:06 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-29 07:20:19 -0400 |
commit | 4b0cac5e759552a24dbdc940db268601422d5b0a (patch) | |
tree | 641b16f7c210cc6f050a613e06fca58775cdd25d /drivers/media/radio | |
parent | 471c4dd38642eb881c4da8372d69e8d11e450a79 (diff) |
[media] radio-mr800: move clamp_t check inside amradio_set_freq()
If i run verbose v4l2-compliance with my radio-mr800 device few times
then i get warning about frequency out of range:
root@machine:~# v4l2-compliance -r /dev/radio0 -v 2
is radio
Driver Info:
Driver name : radio-mr800
Card type : AverMedia MR 800 USB FM Radio
Bus info : usb-0000:00:1a.0-1.2
Driver version: 3.9.0
Capabilities : 0x80050400
Tuner
Radio
Device Capabilities
Device Caps : 0x00050400
Tuner
Radio
Compliance test for device /dev/radio0 (not using libv4l2):
Required ioctls:
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second radio open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
Debug ioctls:
test VIDIOC_DBG_G_CHIP_IDENT: OK (Not Supported)
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK
Input ioctls:
test VIDIOC_G/S_TUNER: OK
warn: v4l2-test-input-output.cpp(234): returned tuner 0 frequency out
of range (6550200 not in [1400000...1728000])
test VIDIOC_G/S_FREQUENCY: OK
test VIDIOC_S_HW_FREQ_SEEK: OK
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 1
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Control ioctls:
info: checking v4l2_queryctrl of control 'User Controls' (0x00980001)
info: checking v4l2_queryctrl of control 'Mute' (0x00980909)
info: checking v4l2_queryctrl of control 'Mute' (0x00980909)
test VIDIOC_QUERYCTRL/MENU: OK
info: checking control 'User Controls' (0x00980001)
info: checking control 'Mute' (0x00980909)
test VIDIOC_G/S_CTRL: OK
info: checking extended control 'User Controls' (0x00980001)
info: checking extended control 'Mute' (0x00980909)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
info: checking control event 'User Controls' (0x00980001)
info: checking control event 'Mute' (0x00980909)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 2 Private Controls: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_PRESETS: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK (Not Supported)
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK (Not Supported)
test VIDIOC_TRY_FMT: OK (Not Supported)
test VIDIOC_S_FMT: OK (Not Supported)
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK (Not Supported)
Total: 38, Succeeded: 38, Failed: 0, Warnings: 1
Some printk() debugging showed that vidioc_s_hw_freq_seek() setups
radio->curfreq to out of range value (lines 395-396) and calls
amradio_set_freq() to set this frequency on device without any
out-of-range checks.
Patch protects from setting up frequency on device to incorrect value
moving clamp_t check inside amradio_set_freq. With this patch we can
call amradio_set_freq() with out of range frequency from any place.
Also put comment that sometimes radio->curfreq is set to out of range
value in vidioc_s_hw_freq_seek().
Signed-off-by: Alexey Klimov <klimov.linux@gmail.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/radio')
-rw-r--r-- | drivers/media/radio/radio-mr800.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 2ce75d1564dc..a360227ca3ab 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c | |||
@@ -203,10 +203,14 @@ static int amradio_set_mute(struct amradio_device *radio, bool mute) | |||
203 | /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ | 203 | /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ |
204 | static int amradio_set_freq(struct amradio_device *radio, int freq) | 204 | static int amradio_set_freq(struct amradio_device *radio, int freq) |
205 | { | 205 | { |
206 | unsigned short freq_send = 0x10 + (freq >> 3) / 25; | 206 | unsigned short freq_send; |
207 | u8 buf[3]; | 207 | u8 buf[3]; |
208 | int retval; | 208 | int retval; |
209 | 209 | ||
210 | /* we need to be sure that frequency isn't out of range */ | ||
211 | freq = clamp_t(unsigned, freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL); | ||
212 | freq_send = 0x10 + (freq >> 3) / 25; | ||
213 | |||
210 | /* frequency is calculated from freq_send and placed in first 2 bytes */ | 214 | /* frequency is calculated from freq_send and placed in first 2 bytes */ |
211 | buf[0] = (freq_send >> 8) & 0xff; | 215 | buf[0] = (freq_send >> 8) & 0xff; |
212 | buf[1] = freq_send & 0xff; | 216 | buf[1] = freq_send & 0xff; |
@@ -329,8 +333,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
329 | 333 | ||
330 | if (f->tuner != 0) | 334 | if (f->tuner != 0) |
331 | return -EINVAL; | 335 | return -EINVAL; |
332 | return amradio_set_freq(radio, clamp_t(unsigned, f->frequency, | 336 | return amradio_set_freq(radio, f->frequency); |
333 | FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL)); | ||
334 | } | 337 | } |
335 | 338 | ||
336 | /* vidioc_g_frequency - get tuner radio frequency */ | 339 | /* vidioc_g_frequency - get tuner radio frequency */ |
@@ -389,6 +392,7 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *priv, | |||
389 | continue; | 392 | continue; |
390 | amradio_send_cmd(radio, AMRADIO_GET_FREQ, 0, NULL, 0, true); | 393 | amradio_send_cmd(radio, AMRADIO_GET_FREQ, 0, NULL, 0, true); |
391 | if (radio->buffer[1] || radio->buffer[2]) { | 394 | if (radio->buffer[1] || radio->buffer[2]) { |
395 | /* To check: sometimes radio->curfreq is set to out of range value */ | ||
392 | radio->curfreq = (radio->buffer[1] << 8) | radio->buffer[2]; | 396 | radio->curfreq = (radio->buffer[1] << 8) | radio->buffer[2]; |
393 | radio->curfreq = (radio->curfreq - 0x10) * 200; | 397 | radio->curfreq = (radio->curfreq - 0x10) * 200; |
394 | amradio_send_cmd(radio, AMRADIO_STOP_SEARCH, | 398 | amradio_send_cmd(radio, AMRADIO_STOP_SEARCH, |