Commit 62bba5dd authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] gspca: Allow subdrivers to use the control framework

Make the necessary changes to allow subdrivers to use the control framework.
This does not add control event support, that comes later.

It add a init_control cam_op that is called after init in probe that allows
the subdriver to set up the controls.

HdG: Call v4l2_ctrl_handler_setup from resume instead of
gspca_set_default_mode, as we just want to resend the current ctrl values to
the device.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ceede9fa
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/ktime.h> #include <linux/ktime.h>
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include "gspca.h" #include "gspca.h"
...@@ -1006,6 +1007,8 @@ static void gspca_set_default_mode(struct gspca_dev *gspca_dev) ...@@ -1006,6 +1007,8 @@ static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
/* set the current control values to their default values /* set the current control values to their default values
* which may have changed in sd_init() */ * which may have changed in sd_init() */
/* does nothing if ctrl_handler == NULL */
v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
ctrl = gspca_dev->cam.ctrls; ctrl = gspca_dev->cam.ctrls;
if (ctrl != NULL) { if (ctrl != NULL) {
for (i = 0; for (i = 0;
...@@ -1323,6 +1326,7 @@ static void gspca_release(struct video_device *vfd) ...@@ -1323,6 +1326,7 @@ static void gspca_release(struct video_device *vfd)
PDEBUG(D_PROBE, "%s released", PDEBUG(D_PROBE, "%s released",
video_device_node_name(&gspca_dev->vdev)); video_device_node_name(&gspca_dev->vdev));
v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
kfree(gspca_dev->usb_buf); kfree(gspca_dev->usb_buf);
kfree(gspca_dev); kfree(gspca_dev);
} }
...@@ -2347,6 +2351,14 @@ int gspca_dev_probe2(struct usb_interface *intf, ...@@ -2347,6 +2351,14 @@ int gspca_dev_probe2(struct usb_interface *intf,
gspca_dev->sd_desc = sd_desc; gspca_dev->sd_desc = sd_desc;
gspca_dev->nbufread = 2; gspca_dev->nbufread = 2;
gspca_dev->empty_packet = -1; /* don't check the empty packets */ gspca_dev->empty_packet = -1; /* don't check the empty packets */
gspca_dev->vdev = gspca_template;
gspca_dev->vdev.parent = &intf->dev;
gspca_dev->module = module;
gspca_dev->present = 1;
mutex_init(&gspca_dev->usb_lock);
mutex_init(&gspca_dev->queue_lock);
init_waitqueue_head(&gspca_dev->wq);
/* configure the subdriver and initialize the USB device */ /* configure the subdriver and initialize the USB device */
ret = sd_desc->config(gspca_dev, id); ret = sd_desc->config(gspca_dev, id);
...@@ -2355,6 +2367,10 @@ int gspca_dev_probe2(struct usb_interface *intf, ...@@ -2355,6 +2367,10 @@ int gspca_dev_probe2(struct usb_interface *intf,
if (gspca_dev->cam.ctrls != NULL) if (gspca_dev->cam.ctrls != NULL)
ctrls_init(gspca_dev); ctrls_init(gspca_dev);
ret = sd_desc->init(gspca_dev); ret = sd_desc->init(gspca_dev);
if (ret < 0)
goto out;
if (sd_desc->init_controls)
ret = sd_desc->init_controls(gspca_dev);
if (ret < 0) if (ret < 0)
goto out; goto out;
gspca_set_default_mode(gspca_dev); gspca_set_default_mode(gspca_dev);
...@@ -2363,15 +2379,7 @@ int gspca_dev_probe2(struct usb_interface *intf, ...@@ -2363,15 +2379,7 @@ int gspca_dev_probe2(struct usb_interface *intf,
if (ret) if (ret)
goto out; goto out;
mutex_init(&gspca_dev->usb_lock);
mutex_init(&gspca_dev->queue_lock);
init_waitqueue_head(&gspca_dev->wq);
/* init video stuff */ /* init video stuff */
memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
gspca_dev->vdev.parent = &intf->dev;
gspca_dev->module = module;
gspca_dev->present = 1;
ret = video_register_device(&gspca_dev->vdev, ret = video_register_device(&gspca_dev->vdev,
VFL_TYPE_GRABBER, VFL_TYPE_GRABBER,
-1); -1);
...@@ -2391,6 +2399,7 @@ int gspca_dev_probe2(struct usb_interface *intf, ...@@ -2391,6 +2399,7 @@ int gspca_dev_probe2(struct usb_interface *intf,
if (gspca_dev->input_dev) if (gspca_dev->input_dev)
input_unregister_device(gspca_dev->input_dev); input_unregister_device(gspca_dev->input_dev);
#endif #endif
v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
kfree(gspca_dev->usb_buf); kfree(gspca_dev->usb_buf);
kfree(gspca_dev); kfree(gspca_dev);
return ret; return ret;
...@@ -2489,11 +2498,20 @@ EXPORT_SYMBOL(gspca_suspend); ...@@ -2489,11 +2498,20 @@ EXPORT_SYMBOL(gspca_suspend);
int gspca_resume(struct usb_interface *intf) int gspca_resume(struct usb_interface *intf)
{ {
struct gspca_dev *gspca_dev = usb_get_intfdata(intf); struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
int streaming;
gspca_dev->frozen = 0; gspca_dev->frozen = 0;
gspca_dev->sd_desc->init(gspca_dev); gspca_dev->sd_desc->init(gspca_dev);
gspca_input_create_urb(gspca_dev); gspca_input_create_urb(gspca_dev);
if (gspca_dev->streaming) /*
* Most subdrivers send all ctrl values on sd_start and thus
* only write to the device registers on s_ctrl when streaming ->
* Clear streaming to avoid setting all ctrls twice.
*/
streaming = gspca_dev->streaming;
gspca_dev->streaming = 0;
v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
if (streaming)
return gspca_init_transfer(gspca_dev); return gspca_init_transfer(gspca_dev);
return 0; return 0;
} }
......
...@@ -115,6 +115,7 @@ struct sd_desc { ...@@ -115,6 +115,7 @@ struct sd_desc {
/* mandatory operations */ /* mandatory operations */
cam_cf_op config; /* called on probe */ cam_cf_op config; /* called on probe */
cam_op init; /* called on probe and resume */ cam_op init; /* called on probe and resume */
cam_op init_controls; /* called on probe */
cam_op start; /* called on stream on after URBs creation */ cam_op start; /* called on stream on after URBs creation */
cam_pkt_op pkt_scan; cam_pkt_op pkt_scan;
/* optional operations */ /* optional operations */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment