|
@@ -43,6 +43,7 @@
|
|
|
* Douglas Schilling Landgraf <dougsland@gmail.com> and
|
|
|
* David Ellingsworth <david@identd.dyndns.org>
|
|
|
* for discussion, help and support.
|
|
|
+ * Version 0.11: Converted to v4l2_device.
|
|
|
*
|
|
|
* Many things to do:
|
|
|
* - Correct power managment of device (suspend & resume)
|
|
@@ -59,7 +60,7 @@
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/input.h>
|
|
|
#include <linux/videodev2.h>
|
|
|
-#include <media/v4l2-common.h>
|
|
|
+#include <media/v4l2-device.h>
|
|
|
#include <media/v4l2-ioctl.h>
|
|
|
#include <linux/usb.h>
|
|
|
#include <linux/version.h> /* for KERNEL_VERSION MACRO */
|
|
@@ -67,8 +68,8 @@
|
|
|
/* driver and module definitions */
|
|
|
#define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
|
|
|
#define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
|
|
|
-#define DRIVER_VERSION "0.10"
|
|
|
-#define RADIO_VERSION KERNEL_VERSION(0, 1, 0)
|
|
|
+#define DRIVER_VERSION "0.11"
|
|
|
+#define RADIO_VERSION KERNEL_VERSION(0, 1, 1)
|
|
|
|
|
|
MODULE_AUTHOR(DRIVER_AUTHOR);
|
|
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
|
@@ -113,38 +114,6 @@ static int radio_nr = -1;
|
|
|
module_param(radio_nr, int, 0);
|
|
|
MODULE_PARM_DESC(radio_nr, "Radio Nr");
|
|
|
|
|
|
-static struct v4l2_queryctrl radio_qctrl[] = {
|
|
|
- {
|
|
|
- .id = V4L2_CID_AUDIO_MUTE,
|
|
|
- .name = "Mute",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 1,
|
|
|
- .step = 1,
|
|
|
- .default_value = 1,
|
|
|
- .type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
|
- },
|
|
|
-/* HINT: the disabled controls are only here to satify kradio and such apps */
|
|
|
- { .id = V4L2_CID_AUDIO_VOLUME,
|
|
|
- .flags = V4L2_CTRL_FLAG_DISABLED,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = V4L2_CID_AUDIO_BALANCE,
|
|
|
- .flags = V4L2_CTRL_FLAG_DISABLED,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = V4L2_CID_AUDIO_BASS,
|
|
|
- .flags = V4L2_CTRL_FLAG_DISABLED,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = V4L2_CID_AUDIO_TREBLE,
|
|
|
- .flags = V4L2_CTRL_FLAG_DISABLED,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = V4L2_CID_AUDIO_LOUDNESS,
|
|
|
- .flags = V4L2_CTRL_FLAG_DISABLED,
|
|
|
- },
|
|
|
-};
|
|
|
-
|
|
|
static int usb_amradio_probe(struct usb_interface *intf,
|
|
|
const struct usb_device_id *id);
|
|
|
static void usb_amradio_disconnect(struct usb_interface *intf);
|
|
@@ -159,6 +128,7 @@ struct amradio_device {
|
|
|
/* reference to USB and video device */
|
|
|
struct usb_device *usbdev;
|
|
|
struct video_device *videodev;
|
|
|
+ struct v4l2_device v4l2_dev;
|
|
|
|
|
|
unsigned char *buffer;
|
|
|
struct mutex lock; /* buffer locking */
|
|
@@ -329,6 +299,7 @@ static void usb_amradio_disconnect(struct usb_interface *intf)
|
|
|
|
|
|
usb_set_intfdata(intf, NULL);
|
|
|
video_unregister_device(radio->videodev);
|
|
|
+ v4l2_device_disconnect(&radio->v4l2_dev);
|
|
|
}
|
|
|
|
|
|
/* vidioc_querycap - query device capabilities */
|
|
@@ -463,14 +434,11 @@ static int vidioc_g_frequency(struct file *file, void *priv,
|
|
|
static int vidioc_queryctrl(struct file *file, void *priv,
|
|
|
struct v4l2_queryctrl *qc)
|
|
|
{
|
|
|
- int i;
|
|
|
-
|
|
|
- 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));
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ switch (qc->id) {
|
|
|
+ case V4L2_CID_AUDIO_MUTE:
|
|
|
+ return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
|
|
|
}
|
|
|
+
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
@@ -671,34 +639,29 @@ 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)
|
|
|
+static void usb_amradio_video_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);
|
|
|
|
|
|
+ v4l2_device_unregister(&radio->v4l2_dev);
|
|
|
+
|
|
|
/* 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 = usb_amradio_device_release,
|
|
|
-};
|
|
|
-
|
|
|
/* check if the device is present and register with v4l and usb if it is */
|
|
|
static int usb_amradio_probe(struct usb_interface *intf,
|
|
|
const struct usb_device_id *id)
|
|
|
{
|
|
|
struct amradio_device *radio;
|
|
|
+ struct v4l2_device *v4l2_dev;
|
|
|
int retval;
|
|
|
|
|
|
- radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL);
|
|
|
+ radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL);
|
|
|
|
|
|
if (!radio) {
|
|
|
dev_err(&intf->dev, "kmalloc for amradio_device failed\n");
|
|
@@ -713,6 +676,15 @@ static int usb_amradio_probe(struct usb_interface *intf,
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
+ v4l2_dev = &radio->v4l2_dev;
|
|
|
+ retval = v4l2_device_register(&intf->dev, v4l2_dev);
|
|
|
+ if (retval < 0) {
|
|
|
+ dev_err(&intf->dev, "couldn't register v4l2_device\n");
|
|
|
+ kfree(radio->buffer);
|
|
|
+ kfree(radio);
|
|
|
+ return retval;
|
|
|
+ }
|
|
|
+
|
|
|
radio->videodev = video_device_alloc();
|
|
|
|
|
|
if (!radio->videodev) {
|
|
@@ -722,8 +694,11 @@ static int usb_amradio_probe(struct usb_interface *intf,
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- memcpy(radio->videodev, &amradio_videodev_template,
|
|
|
- sizeof(amradio_videodev_template));
|
|
|
+ strlcpy(radio->videodev->name, v4l2_dev->name, sizeof(radio->videodev->name));
|
|
|
+ radio->videodev->v4l2_dev = v4l2_dev;
|
|
|
+ radio->videodev->fops = &usb_amradio_fops;
|
|
|
+ radio->videodev->ioctl_ops = &usb_amradio_ioctl_ops;
|
|
|
+ radio->videodev->release = usb_amradio_video_device_release;
|
|
|
|
|
|
radio->removed = 0;
|
|
|
radio->users = 0;
|
|
@@ -734,10 +709,12 @@ static int usb_amradio_probe(struct usb_interface *intf,
|
|
|
mutex_init(&radio->lock);
|
|
|
|
|
|
video_set_drvdata(radio->videodev, radio);
|
|
|
+
|
|
|
retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
|
|
|
if (retval < 0) {
|
|
|
dev_err(&intf->dev, "could not register video device\n");
|
|
|
video_device_release(radio->videodev);
|
|
|
+ v4l2_device_unregister(v4l2_dev);
|
|
|
kfree(radio->buffer);
|
|
|
kfree(radio);
|
|
|
return -EIO;
|