From: Luc S. <lu...@sa...> - 2006-01-04 12:30:51
|
Some comments about the current driver. I'll try tonight the driver, and thanks for writing the driver. Luc > > /* > * usbvideo.c -- USB Video Class driver > * > * Copyright (C) 2005 Now you can update the year :-) > * Laurent Pinchart (lau...@sk...) > * > * This program is free software; you can redistribute it and/or modify > * it under the terms of the GNU General Public License as published by > * the Free Software Foundation; either version 2 of the License, or > * (at your option) any later version. > * > */ > * Don't try to open the driver multiple times ! This will crash and make your > * computer explode (well, maybe not, but still, don't do it). I plan to fix > * that in the very near future. You have been warned. You can just put a counter in the uvc_v4l2_open() and when the counter != 0 don't try to continue. > struct uvc_terminal { > struct list_head list; > > __u8 id; > __u16 type; > char name[64]; > > union { > struct { > __u16 wObjectiveFocalLengthMin; > __u16 wObjectiveFocalLengthMax; > __u16 wOcularFocalLength; > __u8 bControlSize; > __u8 *bmControls; > } camera; > > struct { > __u8 bSourceID; > } output; > }; > }; union without name can't be build with gcc2.95 is it ok ? > > struct uvc_unit { > struct list_head list; > > int id; > int type; > char name[64]; > }; > > struct uvc_control_desc uvc_ctrls[] = { > { put a static here too. > /* > * Allocate the video buffers. > * > * Pages are reserved to make sure they will not be swaped, as they will be > * filled in URB completion handler. > * > * Buffers will be individually mapped, so they must all be page aligned. > */ > static int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, > unsigned int buflength) > { > unsigned int bufsize = PAGE_ALIGN(buflength); > unsigned int i; > void *mem = NULL; > int ret; > > if (nbuffers > UVC_MAX_VIDEO_BUFFERS) > nbuffers = UVC_MAX_VIDEO_BUFFERS; > > down(&queue->lock); > > if ((ret = uvc_free_buffers(queue)) < 0) > goto done; > > /* Decrement the number of buffers until allocation succeeds. */ > for (; nbuffers > 0; --nbuffers) { > mem = vmalloc_32(nbuffers * bufsize); > if (mem != NULL) > break; > } > > if (mem == NULL) > return -ENOMEM; ^^^^ return without a up() ret = -ENOMEM; goto done; > > for (i = 0; i < nbuffers; ++i) { > memset(&queue->buffer[i], 0, sizeof queue->buffer[i]); > queue->buffer[i].size = bufsize; > queue->buffer[i].buf.index = i; > queue->buffer[i].buf.m.offset = i * bufsize; Is any buffersize aligned on a page boudary ? > queue->buffer[i].buf.length = buflength; > queue->buffer[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; > queue->buffer[i].buf.sequence = 0; > queue->buffer[i].buf.field = V4L2_FIELD_NONE; > queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP; > queue->buffer[i].buf.flags = 0; > init_waitqueue_head(&queue->buffer[i].wait); > } > > queue->mem = mem; > queue->count = nbuffers; > ret = nbuffers; > > done: > up(&queue->lock); > return ret; > } > > /* > * Dequeue a video buffer. If nonblocking is false, block until a buffer is > * available. > */ > static int uvc_dequeue_buffer(struct uvc_video_queue *queue, > struct v4l2_buffer *v4l2_buf, int nonblocking) > { > struct uvc_buffer *buf; > int ret = 0; > > if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || > v4l2_buf->memory != V4L2_MEMORY_MMAP) > return -EINVAL; > > down(&queue->lock); > if (list_empty(&queue->mainqueue)) { > ret = -EINVAL; > goto done; > } > > buf = list_entry(queue->mainqueue.next, struct uvc_buffer, stream); > if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0) > goto done; > > switch (buf->state) { > case UVC_BUF_STATE_ERROR: > ret = -EIO; ^^^^ ? need a goto done or is it wanted ? > case UVC_BUF_STATE_DONE: > buf->state = UVC_BUF_STATE_IDLE; > break; > > case UVC_BUF_STATE_IDLE: > case UVC_BUF_STATE_QUEUED: > case UVC_BUF_STATE_ACTIVE: > default: > ret = -EINVAL; > goto done; > } > > list_del(&buf->stream); > memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf); > > done: > up(&queue->lock); > return ret; > } > > /* > * Queue a video buffer. Attempting to queue a buffer that has already been > * queued will return -EINVAL. > */ > static int uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf) > { > struct uvc_buffer *buf; > unsigned long flags; > int ret = 0; > > if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || > v4l2_buf->memory != V4L2_MEMORY_MMAP) > return -EINVAL; > > down(&queue->lock); > if (v4l2_buf->index >= queue->count) { > ret = -EINVAL; > goto done; > } > > buf = &queue->buffer[v4l2_buf->index]; > if (buf->state != UVC_BUF_STATE_IDLE) { > ret = -EINVAL; > goto done; > } > > buf->state = UVC_BUF_STATE_QUEUED; > buf->buf.bytesused = 0; > list_add_tail(&buf->stream, &queue->mainqueue); > spin_lock_irqsave(&queue->irqlock, flags); > list_add_tail(&buf->queue, &queue->irqqueue); > spin_unlock_irqrestore(&queue->irqlock, flags); > > done: > up(&queue->lock); > return ret; > } > } > > static int uvc_set_video_ctrl(struct uvc_video_device *video, > struct uvc_streaming_control *ctrl, int probe) > { > __u8 data[34]; is it not posible to create a structure and access it ? i think it will more readable than data[2] ? > __u8 size; > > size = video->dev->uvc_version > 0x0100 ? 34 : 26; > memset(data, 0, sizeof data); > > *(__le16*)&data[0] = cpu_to_le32(ctrl->bmHint); > data[2] = ctrl->bFormatIndex; > data[3] = ctrl->bFrameIndex; > *(__le32*)&data[4] = cpu_to_le32(ctrl->dwFrameInterval); > *(__le16*)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate); > *(__le16*)&data[10] = cpu_to_le16(ctrl->wPFrameRate); > *(__le16*)&data[12] = cpu_to_le16(ctrl->wCompQuality); > *(__le16*)&data[14] = cpu_to_le16(ctrl->wCompWindowSize); > *(__le16*)&data[16] = cpu_to_le16(ctrl->wDelay); |