diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-31 04:41:32 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-31 04:41:32 +0300 |
commit | f54a6ec0fd85002d94d05b4bb679508eeb066683 (patch) | |
tree | 0f24dd66cce563d2c5e7656c2489e5b96eef31f9 /drivers/media/radio/radio-mr800.c | |
parent | 5ed1836814d908f45cafde0e79cb85314ab9d41d (diff) | |
parent | 134179823b3ca9c8b98e0631906459dbb022ff9b (diff) | |
download | linux-f54a6ec0fd85002d94d05b4bb679508eeb066683.tar.xz |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (583 commits)
V4L/DVB (10130): use USB API functions rather than constants
V4L/DVB (10129): dvb: remove deprecated use of RW_LOCK_UNLOCKED in frontends
V4L/DVB (10128): modify V4L documentation to be a valid XHTML
V4L/DVB (10127): stv06xx: Avoid having y unitialized
V4L/DVB (10125): em28xx: Don't do AC97 vendor detection for i2s audio devices
V4L/DVB (10124): em28xx: expand output formats available
V4L/DVB (10123): em28xx: fix reversed definitions of I2S audio modes
V4L/DVB (10122): em28xx: don't load em28xx-alsa for em2870 based devices
V4L/DVB (10121): em28xx: remove worthless Pinnacle PCTV HD Mini 80e device profile
V4L/DVB (10120): em28xx: remove redundant Pinnacle Dazzle DVC 100 profile
V4L/DVB (10119): em28xx: fix corrupted XCLK value
V4L/DVB (10118): zoran: fix warning for a variable not used
V4L/DVB (10116): af9013: Fix gcc false warnings
V4L/DVB (10111a): usbvideo.h: remove an useless blank line
V4L/DVB (10111): quickcam_messenger.c: fix a warning
V4L/DVB (10110): v4l2-ioctl: Fix warnings when using .unlocked_ioctl = __video_ioctl2
V4L/DVB (10109): anysee: Fix usage of an unitialized function
V4L/DVB (10104): uvcvideo: Add support for video output devices
V4L/DVB (10102): uvcvideo: Ignore interrupt endpoint for built-in iSight webcams.
V4L/DVB (10101): uvcvideo: Fix bulk URB processing when the header is erroneous
...
Diffstat (limited to 'drivers/media/radio/radio-mr800.c')
-rw-r--r-- | drivers/media/radio/radio-mr800.c | 123 |
1 files changed, 91 insertions, 32 deletions
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 256cbeffdcb6..e730eddb2bb5 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -72,6 +72,11 @@ MODULE_LICENSE("GPL"); #define USB_AMRADIO_VENDOR 0x07ca #define USB_AMRADIO_PRODUCT 0xb800 +/* dev_warn macro with driver name */ +#define MR800_DRIVER_NAME "radio-mr800" +#define amradio_dev_warn(dev, fmt, arg...) \ + dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg) + /* Probably USB_TIMEOUT should be modified in module parameter */ #define BUFFER_LENGTH 8 #define USB_TIMEOUT 500 @@ -154,14 +159,14 @@ MODULE_DEVICE_TABLE(usb, usb_amradio_device_table); /* USB subsystem interface */ static struct usb_driver usb_amradio_driver = { - .name = "radio-mr800", + .name = MR800_DRIVER_NAME, .probe = usb_amradio_probe, .disconnect = usb_amradio_disconnect, .suspend = usb_amradio_suspend, .resume = usb_amradio_resume, .reset_resume = usb_amradio_resume, .id_table = usb_amradio_device_table, - .supports_autosuspend = 1, + .supports_autosuspend = 0, }; /* switch on radio. Send 8 bytes to device. */ @@ -202,6 +207,10 @@ static int amradio_stop(struct amradio_device *radio) int retval; int size; + /* safety check */ + if (radio->removed) + return -EIO; + mutex_lock(&radio->lock); radio->buffer[0] = 0x00; @@ -235,6 +244,10 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) int size; unsigned short freq_send = 0x13 + (freq >> 3) / 25; + /* safety check */ + if (radio->removed) + return -EIO; + mutex_lock(&radio->lock); radio->buffer[0] = 0x00; @@ -288,18 +301,12 @@ static void usb_amradio_disconnect(struct usb_interface *intf) { struct amradio_device *radio = usb_get_intfdata(intf); - usb_set_intfdata(intf, NULL); + mutex_lock(&radio->lock); + radio->removed = 1; + mutex_unlock(&radio->lock); - if (radio) { - video_unregister_device(radio->videodev); - radio->videodev = NULL; - if (radio->users) { - kfree(radio->buffer); - kfree(radio); - } else { - radio->removed = 1; - } - } + usb_set_intfdata(intf, NULL); + video_unregister_device(radio->videodev); } /* vidioc_querycap - query device capabilities */ @@ -320,6 +327,10 @@ static int vidioc_g_tuner(struct file *file, void *priv, { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + /* safety check */ + if (radio->removed) + return -EIO; + if (v->index > 0) return -EINVAL; @@ -346,6 +357,12 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { + struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + + /* safety check */ + if (radio->removed) + return -EIO; + if (v->index > 0) return -EINVAL; return 0; @@ -357,9 +374,14 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + /* safety check */ + if (radio->removed) + return -EIO; + radio->curfreq = f->frequency; if (amradio_setfreq(radio, radio->curfreq) < 0) - warn("Set frequency failed"); + amradio_dev_warn(&radio->videodev->dev, + "set frequency failed\n"); return 0; } @@ -369,6 +391,10 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + /* safety check */ + if (radio->removed) + return -EIO; + f->type = V4L2_TUNER_RADIO; f->frequency = radio->curfreq; return 0; @@ -382,8 +408,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); + memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); return 0; } } @@ -396,6 +421,10 @@ static int vidioc_g_ctrl(struct file *file, void *priv, { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + /* safety check */ + if (radio->removed) + return -EIO; + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value = radio->muted; @@ -410,16 +439,22 @@ static int vidioc_s_ctrl(struct file *file, void *priv, { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + /* safety check */ + if (radio->removed) + return -EIO; + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) { if (amradio_stop(radio) < 0) { - warn("amradio_stop() failed"); + amradio_dev_warn(&radio->videodev->dev, + "amradio_stop failed\n"); return -1; } } else { if (amradio_start(radio) < 0) { - warn("amradio_start() failed"); + amradio_dev_warn(&radio->videodev->dev, + "amradio_start failed\n"); return -1; } } @@ -475,30 +510,38 @@ static int usb_amradio_open(struct inode *inode, struct file *file) radio->muted = 1; if (amradio_start(radio) < 0) { - warn("Radio did not start up properly"); + amradio_dev_warn(&radio->videodev->dev, + "radio did not start up properly\n"); radio->users = 0; unlock_kernel(); return -EIO; } if (amradio_setfreq(radio, radio->curfreq) < 0) - warn("Set frequency failed"); + amradio_dev_warn(&radio->videodev->dev, + "set frequency failed\n"); unlock_kernel(); return 0; } -/*close device - free driver structures */ +/*close device */ static int usb_amradio_close(struct inode *inode, struct file *file) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + int retval; if (!radio) return -ENODEV; + radio->users = 0; - if (radio->removed) { - kfree(radio->buffer); - kfree(radio); + + if (!radio->removed) { + retval = amradio_stop(radio); + if (retval < 0) + amradio_dev_warn(&radio->videodev->dev, + "amradio_stop failed\n"); } + return 0; } @@ -508,9 +551,9 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) struct amradio_device *radio = usb_get_intfdata(intf); if (amradio_stop(radio) < 0) - warn("amradio_stop() failed"); + dev_warn(&intf->dev, "amradio_stop failed\n"); - info("radio-mr800: Going into suspend.."); + dev_info(&intf->dev, "going into suspend..\n"); return 0; } @@ -521,9 +564,9 @@ static int usb_amradio_resume(struct usb_interface *intf) struct amradio_device *radio = usb_get_intfdata(intf); if (amradio_start(radio) < 0) - warn("amradio_start() failed"); + dev_warn(&intf->dev, "amradio_start failed\n"); - info("radio-mr800: Coming out of suspend.."); + dev_info(&intf->dev, "coming out of suspend..\n"); return 0; } @@ -555,12 +598,24 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; +static void usb_amradio_device_release(struct video_device *videodev) +{ + struct amradio_device *radio = video_get_drvdata(videodev); + + /* we call v4l to free radio->videodev */ + video_device_release(videodev); + + /* free rest memory */ + kfree(radio->buffer); + kfree(radio); +} + /* V4L2 interface */ static struct video_device amradio_videodev_template = { .name = "AverMedia MR 800 USB FM Radio", .fops = &usb_amradio_fops, .ioctl_ops = &usb_amradio_ioctl_ops, - .release = video_device_release, + .release = usb_amradio_device_release, }; /* check if the device is present and register with v4l and @@ -602,7 +657,7 @@ static int usb_amradio_probe(struct usb_interface *intf, video_set_drvdata(radio->videodev, radio); if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) { - warn("Could not register video device"); + dev_warn(&intf->dev, "could not register video device\n"); video_device_release(radio->videodev); kfree(radio->buffer); kfree(radio); @@ -617,9 +672,13 @@ static int __init amradio_init(void) { int retval = usb_register(&usb_amradio_driver); - info(DRIVER_VERSION " " DRIVER_DESC); + pr_info(KBUILD_MODNAME + ": version " DRIVER_VERSION " " DRIVER_DESC "\n"); + if (retval) - err("usb_register failed. Error number %d", retval); + pr_err(KBUILD_MODNAME + ": usb_register failed. Error number %d\n", retval); + return retval; } |