Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 285699
b: refs/heads/master
c: c20d78c
h: refs/heads/master
i:
  285697: c8d3c89
  285695: 6001b76
v: v3
  • Loading branch information
Hans de Goede authored and Mauro Carvalho Chehab committed Jan 6, 2012
1 parent d6eca6d commit f65e1ea
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 83 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f4af65958a6ea987ff61504ad9f053f8ba8da674
refs/heads/master: c20d78cde37018caa0313469c9320424995cc489
70 changes: 61 additions & 9 deletions trunk/drivers/media/video/pwc/pwc-ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -649,10 +649,20 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
{
unsigned char buf;
int r;

mutex_lock(&pdev->udevlock);
if (!pdev->udev) {
r = -ENODEV;
goto leave;
}

buf = flags & 0x03; // only lower two bits are currently used
return send_control_msg(pdev,
r = send_control_msg(pdev,
SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, &buf, sizeof(buf));
leave:
mutex_unlock(&pdev->udevlock);
return r;
}

int pwc_mpt_reset(struct pwc_device *pdev, int flags)
Expand All @@ -669,6 +679,13 @@ int pwc_mpt_reset(struct pwc_device *pdev, int flags)
static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
{
unsigned char buf[4];
int r;

mutex_lock(&pdev->udevlock);
if (!pdev->udev) {
r = -ENODEV;
goto leave;
}

/* set new relative angle; angles are expressed in degrees * 100,
but cam as .5 degree resolution, hence divide by 200. Also
Expand All @@ -681,8 +698,11 @@ static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
buf[1] = (pan >> 8) & 0xFF;
buf[2] = tilt & 0xFF;
buf[3] = (tilt >> 8) & 0xFF;
return send_control_msg(pdev,
r = send_control_msg(pdev,
SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, &buf, sizeof(buf));
leave:
mutex_unlock(&pdev->udevlock);
return r;
}

int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
Expand Down Expand Up @@ -718,14 +738,22 @@ static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *st
int ret;
unsigned char buf[5];

mutex_lock(&pdev->udevlock);
if (!pdev->udev) {
ret = -ENODEV;
goto leave;
}

ret = recv_control_msg(pdev,
GET_MPT_CTL, PT_STATUS_FORMATTER, &buf, sizeof(buf));
if (ret < 0)
return ret;
goto leave;
status->status = buf[0] & 0x7; // 3 bits are used for reporting
status->time_pan = (buf[1] << 8) + buf[2];
status->time_tilt = (buf[3] << 8) + buf[4];
return 0;
leave:
mutex_unlock(&pdev->udevlock);
return ret;
}

#ifdef CONFIG_USB_PWC_DEBUG
Expand Down Expand Up @@ -794,31 +822,39 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)

switch(cmd) {
case VIDIOCPWCRUSER:
ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER);
ret = v4l2_ctrl_s_ctrl(pdev->restore_user, 0);
break;

case VIDIOCPWCSUSER:
ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER);
ret = v4l2_ctrl_s_ctrl(pdev->save_user, 0);
break;

case VIDIOCPWCFACTORY:
ret = pwc_button_ctrl(pdev, RESTORE_FACTORY_DEFAULTS_FORMATTER);
ret = v4l2_ctrl_s_ctrl(pdev->restore_factory, 0);
break;

case VIDIOCPWCSCQUAL:
{
ARG_DEF(int, qual)

if (vb2_is_streaming(&pdev->vb_queue)) {
mutex_lock(&pdev->udevlock);
if (!pdev->udev) {
ret = -ENODEV;
goto leave;
}

if (pdev->iso_init) {
ret = -EBUSY;
break;
goto leave;
}

ARG_IN(qual)
if (ARGR(qual) < 0 || ARGR(qual) > 3)
ret = -EINVAL;
else
ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
leave:
mutex_unlock(&pdev->udevlock);
break;
}

Expand Down Expand Up @@ -939,8 +975,16 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
{
ARG_DEF(struct pwc_leds, leds)

mutex_lock(&pdev->udevlock);
if (!pdev->udev) {
ret = -ENODEV;
break;
}

ARG_IN(leds)
ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);

mutex_unlock(&pdev->udevlock);
break;
}

Expand All @@ -949,8 +993,16 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
{
ARG_DEF(struct pwc_leds, leds)

mutex_lock(&pdev->udevlock);
if (!pdev->udev) {
ret = -ENODEV;
break;
}

ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
ARG_OUT(leds)

mutex_unlock(&pdev->udevlock);
break;
}

Expand Down
7 changes: 7 additions & 0 deletions trunk/drivers/media/video/pwc/pwc-dec23.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
}
pdec = pwc->decompress_data;

mutex_init(&pdec->lock);

if (DEVICE_USE_CODEC3(type)) {
flags = cmd[2] & 0x18;
if (flags == 8)
Expand Down Expand Up @@ -858,6 +860,9 @@ void pwc_dec23_decompress(const struct pwc_device *pwc,
int flags)
{
int bandlines_left, stride, bytes_per_block;
struct pwc_dec23_private *pdec = pwc->decompress_data;

mutex_lock(&pdec->lock);

bandlines_left = pwc->image.y / 4;
bytes_per_block = pwc->view.x * 4;
Expand Down Expand Up @@ -917,4 +922,6 @@ void pwc_dec23_decompress(const struct pwc_device *pwc,

}
}

mutex_unlock(&pdec->lock);
}
2 changes: 2 additions & 0 deletions trunk/drivers/media/video/pwc/pwc-dec23.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

struct pwc_dec23_private
{
struct mutex lock;

unsigned int scalebits;
unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */

Expand Down
75 changes: 42 additions & 33 deletions trunk/drivers/media/video/pwc/pwc-if.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,12 +515,11 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
}

/*
* Release all queued buffers, no need to take queued_bufs_lock, since all
* iso urbs have been killed when we're called so pwc_isoc_handler won't run.
*/
static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
{
unsigned long flags = 0;

spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
while (!list_empty(&pdev->queued_bufs)) {
struct pwc_frame_buf *buf;

Expand All @@ -529,6 +528,7 @@ static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
list_del(&buf->list);
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
}

/*********
Expand Down Expand Up @@ -642,6 +642,22 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
/***************************************************************************/
/* Video4Linux functions */

int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file)
{
int r = 0;

mutex_lock(&pdev->capt_file_lock);
if (pdev->capt_file != NULL &&
pdev->capt_file != file) {
r = -EBUSY;
goto leave;
}
pdev->capt_file = file;
leave:
mutex_unlock(&pdev->capt_file_lock);
return r;
}

static void pwc_video_release(struct v4l2_device *v)
{
struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
Expand Down Expand Up @@ -684,12 +700,9 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
if (!pdev->udev)
return -ENODEV;

if (pdev->capt_file != NULL &&
pdev->capt_file != file)
if (pwc_test_n_set_capt_file(pdev, file))
return -EBUSY;

pdev->capt_file = file;

return vb2_read(&pdev->vb_queue, buf, count, ppos,
file->f_flags & O_NONBLOCK);
}
Expand Down Expand Up @@ -785,16 +798,24 @@ static void buffer_queue(struct vb2_buffer *vb)
unsigned long flags = 0;

spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
list_add_tail(&buf->list, &pdev->queued_bufs);
/* Check the device has not disconnected between prep and queuing */
if (pdev->udev)
list_add_tail(&buf->list, &pdev->queued_bufs);
else
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
}

static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);
int r;

if (!pdev->udev)
return -ENODEV;
mutex_lock(&pdev->udevlock);
if (!pdev->udev) {
r = -ENODEV;
goto leave;
}

/* Turn on camera and set LEDS on */
pwc_camera_power(pdev, 1);
Expand All @@ -806,35 +827,29 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
}
pwc_set_leds(pdev, led_on, led_off);

return pwc_isoc_init(pdev);
r = pwc_isoc_init(pdev);
leave:
mutex_unlock(&pdev->udevlock);
return r;
}

static int stop_streaming(struct vb2_queue *vq)
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);

mutex_lock(&pdev->udevlock);
if (pdev->udev) {
pwc_set_leds(pdev, 0, 0);
pwc_camera_power(pdev, 0);
pwc_isoc_cleanup(pdev);
}
mutex_unlock(&pdev->udevlock);

pwc_cleanup_queued_bufs(pdev);

return 0;
}

static void pwc_lock(struct vb2_queue *vq)
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);
mutex_lock(&pdev->modlock);
}

static void pwc_unlock(struct vb2_queue *vq)
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);
mutex_unlock(&pdev->modlock);
}

static struct vb2_ops pwc_vb_queue_ops = {
.queue_setup = queue_setup,
.buf_init = buffer_init,
Expand All @@ -844,8 +859,6 @@ static struct vb2_ops pwc_vb_queue_ops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
.wait_prepare = pwc_unlock,
.wait_finish = pwc_lock,
};

/***************************************************************************/
Expand Down Expand Up @@ -1137,7 +1150,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
}
pwc_construct(pdev); /* set min/max sizes correct */

mutex_init(&pdev->modlock);
mutex_init(&pdev->capt_file_lock);
mutex_init(&pdev->udevlock);
spin_lock_init(&pdev->queued_bufs_lock);
INIT_LIST_HEAD(&pdev->queued_bufs);
Expand All @@ -1158,7 +1171,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id

/* Init video_device structure */
memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
pdev->vdev.lock = &pdev->modlock;
strcpy(pdev->vdev.name, name);
set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
video_set_drvdata(&pdev->vdev, pdev);
Expand Down Expand Up @@ -1285,16 +1297,13 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);

mutex_lock(&pdev->udevlock);
mutex_lock(&pdev->modlock);

/* No need to keep the urbs around after disconnection */
pwc_isoc_cleanup(pdev);
pwc_cleanup_queued_bufs(pdev);
pdev->udev = NULL;

mutex_unlock(&pdev->modlock);
mutex_unlock(&pdev->udevlock);

pwc_cleanup_queued_bufs(pdev);

pwc_remove_sysfs_files(pdev);
video_unregister_device(&pdev->vdev);
v4l2_device_unregister(&pdev->v4l2_dev);
Expand Down
Loading

0 comments on commit f65e1ea

Please sign in to comment.