]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/gspca/gspca.c
V4L/DVB (9853): gspca: Webcam 093a:2622 added in pac7311.
[linux-2.6-omap-h63xx.git] / drivers / media / video / gspca / gspca.c
index 7f8b798deb1b97476ece636401e0e8ca6254562b..a5c21ca959d8339c63cd7b576850f12f7226863b 100644 (file)
@@ -300,7 +300,6 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
                frame->v4l2_buf.bytesused = frame->data_end - frame->data;
                frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
                frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
-               atomic_inc(&gspca_dev->nevent);
                wake_up_interruptible(&gspca_dev->wq);  /* event = new frame */
                i = (gspca_dev->fr_i + 1) % gspca_dev->nframes;
                gspca_dev->fr_i = i;
@@ -394,7 +393,6 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
        gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
        gspca_dev->last_packet_type = DISCARD_PACKET;
        gspca_dev->sequence = 0;
-       atomic_set(&gspca_dev->nevent, 0);
        return 0;
 }
 
@@ -628,7 +626,6 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
                        goto out;
                }
                gspca_dev->streaming = 1;
-               atomic_set(&gspca_dev->nevent, 0);
 
                /* some bulk transfers are started by the subdriver */
                if (gspca_dev->alt == 0 && gspca_dev->cam.bulk_nurbs == 0)
@@ -642,8 +639,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
                                        "usb_submit_urb [%d] err %d", n, ret);
                                gspca_dev->streaming = 0;
                                destroy_urbs(gspca_dev);
-                               if (ret == -ENOSPC)
+                               if (ret == -ENOSPC) {
+                                       msleep(20);     /* wait for kill
+                                                        * complete */
                                        break;  /* try the previous alt */
+                               }
                                goto out;
                        }
                }
@@ -661,7 +661,7 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
 
        ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
        if (ret < 0)
-               PDEBUG(D_ERR|D_STREAM, "set interface 0 err %d", ret);
+               PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret);
        return ret;
 }
 
@@ -669,7 +669,6 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
 static void gspca_stream_off(struct gspca_dev *gspca_dev)
 {
        gspca_dev->streaming = 0;
-       atomic_set(&gspca_dev->nevent, 0);
        if (gspca_dev->present
            && gspca_dev->sd_desc->stopN)
                gspca_dev->sd_desc->stopN(gspca_dev);
@@ -1072,6 +1071,35 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
        return -EINVAL;
 }
 
+/*fixme: have an audio flag in gspca_dev?*/
+static int vidioc_s_audio(struct file *file, void *priv,
+                        struct v4l2_audio *audio)
+{
+       if (audio->index != 0)
+               return -EINVAL;
+       return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+                        struct v4l2_audio *audio)
+{
+       memset(audio, 0, sizeof *audio);
+       strcpy(audio->name, "Microphone");
+       return 0;
+}
+
+static int vidioc_enumaudio(struct file *file, void *priv,
+                        struct v4l2_audio *audio)
+{
+       if (audio->index != 0)
+               return -EINVAL;
+
+       strcpy(audio->name, "Microphone");
+       audio->capability = 0;
+       audio->mode = 0;
+       return 0;
+}
+
 static int vidioc_querymenu(struct file *file, void *priv,
                            struct v4l2_querymenu *qmenu)
 {
@@ -1255,7 +1283,6 @@ static int vidioc_streamoff(struct file *file, void *priv,
        gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
        gspca_dev->last_packet_type = DISCARD_PACKET;
        gspca_dev->sequence = 0;
-       atomic_set(&gspca_dev->nevent, 0);
        ret = 0;
 out:
        mutex_unlock(&gspca_dev->queue_lock);
@@ -1459,33 +1486,22 @@ static int frame_wait(struct gspca_dev *gspca_dev,
        i = gspca_dev->fr_o;
        j = gspca_dev->fr_queue[i];
        frame = &gspca_dev->frame[j];
-       if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) {
-               atomic_dec(&gspca_dev->nevent);
-               goto ok;
-       }
-       if (nonblock_ing)                       /* no frame yet */
-               return -EAGAIN;
 
-       /* wait till a frame is ready */
-       for (;;) {
+       if (!(frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE)) {
+               if (nonblock_ing)
+                       return -EAGAIN;
+
+               /* wait till a frame is ready */
                ret = wait_event_interruptible_timeout(gspca_dev->wq,
-                                       atomic_read(&gspca_dev->nevent) > 0,
-                                       msecs_to_jiffies(3000));
-               if (ret <= 0) {
-                       if (ret < 0)
-                               return ret;     /* interrupt */
-                       return -EIO;            /* timeout */
-               }
-               atomic_dec(&gspca_dev->nevent);
-               if (!gspca_dev->streaming || !gspca_dev->present)
+                       (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) ||
+                       !gspca_dev->streaming || !gspca_dev->present,
+                       msecs_to_jiffies(3000));
+               if (ret < 0)
+                       return ret;
+               if (ret == 0 || !gspca_dev->streaming || !gspca_dev->present)
                        return -EIO;
-               i = gspca_dev->fr_o;
-               j = gspca_dev->fr_queue[i];
-               frame = &gspca_dev->frame[j];
-               if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
-                       break;
        }
-ok:
+
        gspca_dev->fr_o = (i + 1) % gspca_dev->nframes;
        PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d",
                gspca_dev->fr_q,
@@ -1800,6 +1816,9 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = {
        .vidioc_queryctrl       = vidioc_queryctrl,
        .vidioc_g_ctrl          = vidioc_g_ctrl,
        .vidioc_s_ctrl          = vidioc_s_ctrl,
+       .vidioc_g_audio         = vidioc_g_audio,
+       .vidioc_s_audio         = vidioc_s_audio,
+       .vidioc_enumaudio       = vidioc_enumaudio,
        .vidioc_querymenu       = vidioc_querymenu,
        .vidioc_enum_input      = vidioc_enum_input,
        .vidioc_g_input         = vidioc_g_input,
@@ -1873,10 +1892,10 @@ int gspca_dev_probe(struct usb_interface *intf,
        gspca_dev->empty_packet = -1;   /* don't check the empty packets */
 
        /* configure the subdriver and initialize the USB device */
-       ret = gspca_dev->sd_desc->config(gspca_dev, id);
+       ret = sd_desc->config(gspca_dev, id);
        if (ret < 0)
                goto out;
-       ret = gspca_dev->sd_desc->init(gspca_dev);
+       ret = sd_desc->init(gspca_dev);
        if (ret < 0)
                goto out;
        ret = gspca_set_alt0(gspca_dev);
@@ -1890,9 +1909,8 @@ int gspca_dev_probe(struct usb_interface *intf,
        init_waitqueue_head(&gspca_dev->wq);
 
        /* init video stuff */
-       gspca_dev->vdev = video_device_alloc();
-       memcpy(gspca_dev->vdev, &gspca_template, sizeof gspca_template);
-       gspca_dev->vdev->parent = &dev->dev;
+       memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
+       gspca_dev->vdev.parent = &dev->dev;
        gspca_dev->module = module;
        gspca_dev->present = 1;
        ret = video_register_device(&gspca_dev->vdev,