Hi Ezequiel,

On 05/26/2012 07:50 PM, Hans Verkuil wrote:
>> +/*
>> + * IOCTL vidioc handling
>> + */
>> +static int vidioc_reqbufs(struct file *file, void *priv,
>> +                      struct v4l2_requestbuffers *p)
>> +{
>> +    struct stk1160 *dev = video_drvdata(file);
>> +    return vb2_reqbufs(&dev->vb_vidq, p);
>> +}
>> +
>> +static int vidioc_querybuf(struct file *file, void *priv, struct 
>> v4l2_buffer *p)
>> +{
>> +    struct stk1160 *dev = video_drvdata(file);
>> +    return vb2_querybuf(&dev->vb_vidq, p);
>> +}
>> +
>> +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> +{
>> +    struct stk1160 *dev = video_drvdata(file);
>> +    return vb2_qbuf(&dev->vb_vidq, p);
>> +}
>> +
>> +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer 
>> *p)
>> +{
>> +    struct stk1160 *dev = video_drvdata(file);
>> +    return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags&  O_NONBLOCK);
>> +}
>> +
>> +static int vidioc_streamon(struct file *file, void *priv, enum 
>> v4l2_buf_type i)
>> +{
>> +    struct stk1160 *dev = video_drvdata(file);
>> +    return vb2_streamon(&dev->vb_vidq, i);
>> +}
>> +
>> +static int vidioc_streamoff(struct file *file, void *priv, enum 
>> v4l2_buf_type i)
>> +{
>> +    struct stk1160 *dev = video_drvdata(file);
>> +    return vb2_streamoff(&dev->vb_vidq, i);
>> +}
>> +
>> +static int vidioc_querycap(struct file *file,
>> +            void *priv, struct v4l2_capability *dev)
>> +{
>> +    strcpy(dev->driver, "stk1160");
>> +    strcpy(dev->card, "stk1160");
>> +    dev->version = STK1160_VERSION_NUM;

You can drop this line, it's overwritten with KERNEL_VERSION in v4l2-ioctl.c.
Also I could imagine there might be better names, than "dev", for capabilities.

>> +    dev->capabilities =
>> +            V4L2_CAP_VIDEO_CAPTURE |
>> +            V4L2_CAP_STREAMING |
>> +            V4L2_CAP_READWRITE;
>> +    return 0;
>> +}
>> +
>> +static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
>> +            struct v4l2_fmtdesc *f)
>> +{
>> +    if (f->index != 0)
>> +            return -EINVAL;
>> +
>> +    strlcpy(f->description, format[f->index].name, sizeof(f->description));
>> +    f->pixelformat = format[f->index].fourcc;
>> +    return 0;
>> +}
>> +
>> +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
>> +                                    struct v4l2_format *f)
>> +{
>> +    struct stk1160 *dev = video_drvdata(file);
>> +
>> +    f->fmt.pix.width = dev->width;
>> +    f->fmt.pix.height = dev->height;
>> +    f->fmt.pix.field = V4L2_FIELD_INTERLACED;
>> +    f->fmt.pix.pixelformat = dev->fmt->fourcc;
>> +    f->fmt.pix.bytesperline = dev->width<<  1;
                                  ^^^^^^^^^^^^^^^^
Probably better to just write: dev->width * 2.

>> +    f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline;
>> +    f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
>> +
>> +    return 0;
>> +}
>> +
>> +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
>> +                    struct v4l2_format *f)
>> +{
>> +    struct stk1160 *dev = video_drvdata(file);
>> +
>> +    if (f->fmt.pix.pixelformat != format[0].fourcc) {

I would rename format[] to stk1160_formats[], but it might just be me.

>> +            stk1160_err("fourcc format 0x%08x invalid\n",
>> +                    f->fmt.pix.pixelformat);
>> +            return -EINVAL;
>> +    }
>> +
>> +    /*
>> +     * User can't choose size at his own will,
>> +     * so we just return him the current size chosen
>> +     * at standard selection.
>> +     * TODO: Implement frame scaling?
>> +     */
>> +
>> +    f->fmt.pix.width = dev->width;
>> +    f->fmt.pix.height = dev->height;
>> +    f->fmt.pix.field = V4L2_FIELD_INTERLACED;
>> +    f->fmt.pix.bytesperline = dev->width<<  1;

dev->width * 2;

>> +    f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline;
>> +    f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
>> +
>> +    return 0;
>> +}
...
>> +/*
>> + * Videobuf2 operations
>> + */
>> +static int queue_setup(struct vb2_queue *vq, const struct v4l2_format 
>> *v4l_fmt,
>> +                            unsigned int *nbuffers, unsigned int *nplanes,
>> +                            unsigned int sizes[], void *alloc_ctxs[])
>> +{
>> +    struct stk1160 *dev = vb2_get_drv_priv(vq);
>> +    unsigned long size;
>> +
>> +    size = dev->width * dev->height * 2;
>> +
>> +    /*
>> +     * Here we can change the number of buffers being requested.
>> +     * For instance, we could set a minimum and a maximum,
>> +     * like this:
>> +     */
>> +    if (*nbuffers<  STK1160_MIN_VIDEO_BUFFERS)
>> +            *nbuffers = STK1160_MIN_VIDEO_BUFFERS;
>> +    else if (*nbuffers>  STK1160_MAX_VIDEO_BUFFERS)
>> +            *nbuffers = STK1160_MAX_VIDEO_BUFFERS;

Could be also done as:

        *buffers = clamp(*buffers, STK1160_MIN_VIDEO_BUFFERS,
                         STK1160_MAX_VIDEO_BUFFERS);
>> +
>> +    /* This means a packed colorformat */
>> +    *nplanes = 1;
>> +
>> +    sizes[0] = size;
>> +
>> +    /*
>> +     * videobuf2-vmalloc allocator is context-less so no need to set
>> +     * alloc_ctxs array.
>> +     */
>> +
>> +    if (v4l_fmt) {
>> +            stk1160_info("selected format %d (%d)\n",
>> +                    v4l_fmt->fmt.pix.pixelformat,
>> +                    dev->fmt->fourcc);
>> +    }

This log is not exactly right. You just ignore v4l_fmt, so it is not selected
anywhere. The *v4l_fmt argument is here for ioctls like VIDIOC_CREATE_BUFS,
and in case you wanted to support this ioctl you would need to do something 
like:
        pix = &v4l_fmt->fmt.pix;
        sizes[0] = pix->width * pix->height * 2;

Of course with any required sanity checks.

But this driver does not implement vidioc_create_bufs/vidioc_prepare_buf ioctl
callbacks are not, so the code is generally OK.

>> +
>> +    stk1160_info("%s: buffer count %d, each %ld bytes\n",
>> +                    __func__, *nbuffers, size);
>> +
>> +    return 0;
>> +}
>> +
>> +static int buffer_init(struct vb2_buffer *vb)
>> +{
>> +    return 0;
>> +}
>> +
>> +static int buffer_prepare(struct vb2_buffer *vb)
>> +{
>> +    struct stk1160 *dev = vb2_get_drv_priv(vb->vb2_queue);
>> +    struct stk1160_buffer *buf =
>> +                    container_of(vb, struct stk1160_buffer, vb);
>> +
>> +    /* If the device is disconnected, reject the buffer */
>> +    if (!dev->udev)
>> +            return -ENODEV;
>> +
>> +    buf->mem = vb2_plane_vaddr(vb, 0);
>> +    buf->length = vb2_plane_size(vb, 0);

Where do you check if the buffer you get from vb2 has correct parameters 
for your hardware (with current settings) to start writing data to it ?

It seems that this driver supports just one pixel format and resolution,
but still would be good to do such checks in buf_prepare().

And initialization of buf->mem, buf->length is better done from
buffer_queue() op. This way there would be no need to take dev->buf_lock 
spinlock also in buf_prepare() to protect the driver's buffer (queue),
which isn't done but it should in buffer_prepare() btw.

>> +    buf->bytesused = 0;
>> +    buf->pos = 0;
>> +
>> +    return 0;
>> +}
>> +
>> +static int buffer_finish(struct vb2_buffer *vb)
>> +{
>> +    return 0;
>> +}
>> +
>> +static void buffer_cleanup(struct vb2_buffer *vb)
>> +{
>> +}

buf_init, buf_finish, buf_cleanup are optional callbacks, so if you 
don't use them they could be removed altogether.

>> +
>> +static void buffer_queue(struct vb2_buffer *vb)
>> +{
>> +    unsigned long flags = 0;
>> +    struct stk1160 *dev = vb2_get_drv_priv(vb->vb2_queue);
>> +    struct stk1160_buffer *buf =
>> +            container_of(vb, struct stk1160_buffer, vb);
>> +
>> +    spin_lock_irqsave(&dev->buf_lock, flags);
>> +    if (!dev->udev) {
>> +            /*
>> +             * If the device is disconnected return the buffer to userspace
>> +             * directly. The next QBUF call will fail with -ENODEV.
>> +             */
>> +            vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
>> +    } else {
>> +            list_add_tail(&buf->list,&dev->avail_bufs);
>> +    }
>> +    spin_unlock_irqrestore(&dev->buf_lock, flags);
>> +}

--
Regards,
Sylwester
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to