All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hans de Goede <j.w.r.degoede@hhs.nl>
To: Brandon Philips <brandon@ifup.org>
Cc: video4linux-list@redhat.com, spca50x-devs@lists.sourceforge.net
Subject: Re: [New Driver]: usbvideo2 webcam core + pac207 driver using it.
Date: Fri, 04 Apr 2008 09:00:06 +0200	[thread overview]
Message-ID: <47F5D1F6.2020906@hhs.nl> (raw)
In-Reply-To: <20080403212728.GE14369@plankton.ifup.org>

Brandon Philips wrote:
> On 22:53 Fri 28 Mar 2008, Hans de Goede wrote:
>>  I'm currently posting these as .c files for easy reading and
>>  compilation / testing, but I still hope to get a lot of feedback / a
>>  thorough review, esp of the core <-> pac207 split version as I hope
>>  to submit that as a patch for mainline inclusion soon.
> 
> The driver look pretty good.  Comments inline.
> 

Thanks for the review!

>> struct pac207_decompress_table_t {
>> 	u8 is_abs;
>> 	u8 len;
>> 	s8 val;
>> };
> 
> Why add the _t?
> 

So that I can write "struct pac207_decompress_table_t 
pac207_decompress_table[256];" further on.

>> int pac207_read_reg(struct usbvideo2_device* cam, u16 index)
>> {
>> 	struct usb_device* udev = cam->usbdev;
>> 	u8* buff = cam->control_buffer;
>> 	int res;
>>
>> 	res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
>> 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
>> 			0x00, index, buff, 1, USBVIDEO2_CTRL_TIMEOUT);
>> 	if (res < 0)
>> 		DBG(1, "Failed to read a register (index 0x%04X, error %d)",
>> 			index, res);
>>
>> 	return (res >= 0) ? (int)(*buff) : res;
> 
> Why not do the obvious thing and return from the if (res < 0) statement?
> 

Good point.

>> /*****************************************************************************/
>>
>> /* auto gain and exposure algorithm based on the knee algorithm described here:
>>    http://ytse.tricolour.net/docs/LowLightOptimization.html */
> 
> URL is dead.
> 

Huh, you're right it was still alive when I wrote my mail, lets give it some 
time to come back (I hope it does).

>> #define CLIP(color) (unsigned char)(((color)>0xFF)?0xff:(((color)<0)?0:(color)))
> 
> Add a comment about what this is doing?  Could you just do it as a
> static function instead?
> 

What it does it obvious isn't it? Sure I could make this into a funciton that 
indeed would be somewhat more readable.

>> static int
>> pac207_vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
>> {
>> 	struct usbvideo2_device* cam = fh;
>> 	struct pac207_data *data = cam->cam_data;
>> 	int new_value = a->value;
>> 	int err;
>>
>> 	if ((err = pac207_vidioc_g_ctrl(file, fh, a)))
>> 		return err;
>>
>> 	if (a->value == new_value)
>> 		return 0;
> 
> This all needs some locking to protect from multi-threaded applications.
> Otherwise the hardware and data structures could be in two different
> states.
> 

They are all called with the usbvideo2 "core" fileop_mutex lock held, as is 
documented in usbvideo2.h

<snip>

> 
>> static void usbvideo2_urb_complete(struct urb *urb)
>> {
>> 	struct usbvideo2_device* cam = urb->context;
>> 	struct usbvideo2_frame_t** f;
>> 	int i, ret;
>>
>> 	switch (urb->status) {
>> 		case 0:
>> 			break;
>> 		case -ENOENT:		/* usb_kill_urb() called. */
>> 		case -ECONNRESET:	/* usb_unlink_urb() called. */
>> 		case -ESHUTDOWN:	/* The endpoint is being disabled. */
>> 			return;
>> 		default:
>> 			goto resubmit_urb;
>> 	}
>>
>> 	f = &cam->frame_current;
>>
>> 	if (!(*f)) {
>> 		if (list_empty(&cam->inqueue))
>> 			goto resubmit_urb;
>>
>> 		(*f) = list_entry(cam->inqueue.next, struct usbvideo2_frame_t,
>> 					frame);
>> 	} 
> 
> Don't you want to take a spinlock here?  Most accesses of inqueue seem
> to take a spinlock.
> 

Good catch! Note that this bug is present in the current in mainline zc0301, 
et61x251, and sn9c102 drivers too!!

(I modelled my driver after these).

<snip>

>> static void usbvideo2_vm_close(struct vm_area_struct* vma)
>> {
>> 	/* NOTE: buffers are not freed here */
> 
> Why is that worth noting?
> 

I guess it isn't this was copied verbatim from the zc0301 driver.

>> 	struct usbvideo2_frame_t* f = vma->vm_private_data;
>> 	f->vma_use_count--;
>> }
>>
>>
>> static int
>> usbvideo2_vidioc_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *b)
>> {
>> 	u32 i;
>> 	struct usbvideo2_device* cam = fh;
>>
>> 	if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
>> 			b->memory != V4L2_MEMORY_MMAP)
>> 		return -EINVAL;
>>
>> 	if (cam->io == IO_READ) {
>> 		DBG(2, "Close and open the device again to choose the "
>> 			"mmap I/O method");
>> 		return -EBUSY;
>> 	}
> 
> Again, why is close then open required?
> 

This whole check is just there to give a hint to the applicaiton writer, that 
mixing mmap and read won't work. If a read() call is made, then it will request 
a number of buffers, and effectively do a transfer_on ioctl, starting the 
stream. If this check is removed, the usbvideo2_vidioc_reqbufs() ioctl will 
still fail if done after a read call is made, because the next check will fail:

         if (cam->stream == STREAM_ON) {
                 return -EBUSY;
         }

Thic check is mandatory as freeing the buffers will the usb isoc stream is 
active is a bad idea! So I can remove the if (cam->io == IO_READ) { check 
without any ill effects, its just there to give a hint to application writers 
why switching between mmap <-> read will fial most of the time.


>> static int
>> usbvideo2_vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
>> {
>> 	struct usbvideo2_device* cam = fh;
>> 	struct usbvideo2_frame_t *f;
>> 	unsigned long lock_flags;
>> 	long timeout;
>>
>> 	if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP ||
>> 			cam->stream == STREAM_OFF)
>> 		return -EINVAL;
>>
>> 	if (list_empty(&cam->outqueue)) {
>> 		if (file->f_flags & O_NONBLOCK)
>> 			return -EAGAIN;
>>
>> 		timeout = wait_event_interruptible_timeout(cam->wait_frame,
>> 				!list_empty(&cam->outqueue) ||
>> 				cam->disconnected,
>> 				msecs_to_jiffies(USBVIDEO2_FRAME_TIMEOUT) );
>> 		if (cam->disconnected)
>> 			return -ENODEV;
>>
>> 		if (timeout <= 0)
>> 			return (timeout < 0)? timeout : -EIO;
>> 	}
> 
> Where is the locking?  What happens if two threads call dqbuf on this
> device at the same time?  
> 

All ioctl handlers gets called through usbvideo2_ioctl(), which takes the 
fileop_mutex, then checks if the device hasn't been disconnected from 
underneath us, and then calls video_ioctl2(...). This video_ioctl2() wrapping 
is needed to check for disconnected devices, and as it was needed anyway also 
was a good central place to add locking, simplifying all the ioctl handlers, 
esp. there error exit paths.

> 
>> struct usbvideo2_frame_t {
>> 	void* bufmem;
>> 	struct v4l2_buffer buf;
>> 	enum usbvideo2_frame_state state;
>> 	struct list_head frame;
>> 	unsigned long vma_use_count;
>> };
> 
> Why the _t on the end?
> 

No special reason in this case.

Thanks & Regards,

Hans


p.s.

I'm currently trying to merge my work and the work to port gspca as a whole to 
v4l2 of Jean-François Moine, so don't expect a new iteration of this soon, as I 
first want to have a clear path for merging these 2 works.


--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list

  reply	other threads:[~2008-04-04  7:11 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-28 21:53 [New Driver]: usbvideo2 webcam core + pac207 driver using it Hans de Goede
2008-04-03 21:27 ` Brandon Philips
2008-04-04  7:00   ` Hans de Goede [this message]
2008-04-04 18:56     ` Brandon Philips
     [not found]   ` <20080404144935.3b457c69.zaitcev@redhat.com>
2008-04-05  7:36     ` Hans de Goede
     [not found] ` <20080404184855.963369c5.zaitcev@redhat.com>
2008-04-05  7:52   ` Hans de Goede
  -- strict thread matches above, loose matches on Subject: below --
2008-03-28 21:52 Hans de Goede

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=47F5D1F6.2020906@hhs.nl \
    --to=j.w.r.degoede@hhs.nl \
    --cc=brandon@ifup.org \
    --cc=spca50x-devs@lists.sourceforge.net \
    --cc=video4linux-list@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.