~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/usb/gadget/uvc_v4l2.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      uvc_v4l2.c  --  USB Video Class Gadget driver
 
3
 *
 
4
 *      Copyright (C) 2009-2010
 
5
 *          Laurent Pinchart (laurent.pinchart@ideasonboard.com)
 
6
 *
 
7
 *      This program is free software; you can redistribute it and/or modify
 
8
 *      it under the terms of the GNU General Public License as published by
 
9
 *      the Free Software Foundation; either version 2 of the License, or
 
10
 *      (at your option) any later version.
 
11
 */
 
12
 
 
13
#include <linux/kernel.h>
 
14
#include <linux/device.h>
 
15
#include <linux/errno.h>
 
16
#include <linux/list.h>
 
17
#include <linux/mutex.h>
 
18
#include <linux/videodev2.h>
 
19
#include <linux/vmalloc.h>
 
20
#include <linux/wait.h>
 
21
 
 
22
#include <media/v4l2-dev.h>
 
23
#include <media/v4l2-event.h>
 
24
#include <media/v4l2-ioctl.h>
 
25
 
 
26
#include "uvc.h"
 
27
#include "uvc_queue.h"
 
28
 
 
29
/* --------------------------------------------------------------------------
 
30
 * Requests handling
 
31
 */
 
32
 
 
33
static int
 
34
uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
 
35
{
 
36
        struct usb_composite_dev *cdev = uvc->func.config->cdev;
 
37
        struct usb_request *req = uvc->control_req;
 
38
 
 
39
        if (data->length < 0)
 
40
                return usb_ep_set_halt(cdev->gadget->ep0);
 
41
 
 
42
        req->length = min(uvc->event_length, data->length);
 
43
        req->zero = data->length < uvc->event_length;
 
44
        req->dma = DMA_ADDR_INVALID;
 
45
 
 
46
        memcpy(req->buf, data->data, data->length);
 
47
 
 
48
        return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
 
49
}
 
50
 
 
51
/* --------------------------------------------------------------------------
 
52
 * V4L2
 
53
 */
 
54
 
 
55
struct uvc_format
 
56
{
 
57
        u8 bpp;
 
58
        u32 fcc;
 
59
};
 
60
 
 
61
static struct uvc_format uvc_formats[] = {
 
62
        { 16, V4L2_PIX_FMT_YUYV  },
 
63
        { 0,  V4L2_PIX_FMT_MJPEG },
 
64
};
 
65
 
 
66
static int
 
67
uvc_v4l2_get_format(struct uvc_video *video, struct v4l2_format *fmt)
 
68
{
 
69
        fmt->fmt.pix.pixelformat = video->fcc;
 
70
        fmt->fmt.pix.width = video->width;
 
71
        fmt->fmt.pix.height = video->height;
 
72
        fmt->fmt.pix.field = V4L2_FIELD_NONE;
 
73
        fmt->fmt.pix.bytesperline = video->bpp * video->width / 8;
 
74
        fmt->fmt.pix.sizeimage = video->imagesize;
 
75
        fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
 
76
        fmt->fmt.pix.priv = 0;
 
77
 
 
78
        return 0;
 
79
}
 
80
 
 
81
static int
 
82
uvc_v4l2_set_format(struct uvc_video *video, struct v4l2_format *fmt)
 
83
{
 
84
        struct uvc_format *format;
 
85
        unsigned int imagesize;
 
86
        unsigned int bpl;
 
87
        unsigned int i;
 
88
 
 
89
        for (i = 0; i < ARRAY_SIZE(uvc_formats); ++i) {
 
90
                format = &uvc_formats[i];
 
91
                if (format->fcc == fmt->fmt.pix.pixelformat)
 
92
                        break;
 
93
        }
 
94
 
 
95
        if (i == ARRAY_SIZE(uvc_formats)) {
 
96
                printk(KERN_INFO "Unsupported format 0x%08x.\n",
 
97
                        fmt->fmt.pix.pixelformat);
 
98
                return -EINVAL;
 
99
        }
 
100
 
 
101
        bpl = format->bpp * fmt->fmt.pix.width / 8;
 
102
        imagesize = bpl ? bpl * fmt->fmt.pix.height : fmt->fmt.pix.sizeimage;
 
103
 
 
104
        video->fcc = format->fcc;
 
105
        video->bpp = format->bpp;
 
106
        video->width = fmt->fmt.pix.width;
 
107
        video->height = fmt->fmt.pix.height;
 
108
        video->imagesize = imagesize;
 
109
 
 
110
        fmt->fmt.pix.field = V4L2_FIELD_NONE;
 
111
        fmt->fmt.pix.bytesperline = bpl;
 
112
        fmt->fmt.pix.sizeimage = imagesize;
 
113
        fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
 
114
        fmt->fmt.pix.priv = 0;
 
115
 
 
116
        return 0;
 
117
}
 
118
 
 
119
static int
 
120
uvc_v4l2_open(struct file *file)
 
121
{
 
122
        struct video_device *vdev = video_devdata(file);
 
123
        struct uvc_device *uvc = video_get_drvdata(vdev);
 
124
        struct uvc_file_handle *handle;
 
125
 
 
126
        handle = kzalloc(sizeof(*handle), GFP_KERNEL);
 
127
        if (handle == NULL)
 
128
                return -ENOMEM;
 
129
 
 
130
        v4l2_fh_init(&handle->vfh, vdev);
 
131
        v4l2_fh_add(&handle->vfh);
 
132
 
 
133
        handle->device = &uvc->video;
 
134
        file->private_data = &handle->vfh;
 
135
 
 
136
        uvc_function_connect(uvc);
 
137
        return 0;
 
138
}
 
139
 
 
140
static int
 
141
uvc_v4l2_release(struct file *file)
 
142
{
 
143
        struct video_device *vdev = video_devdata(file);
 
144
        struct uvc_device *uvc = video_get_drvdata(vdev);
 
145
        struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
 
146
        struct uvc_video *video = handle->device;
 
147
 
 
148
        uvc_function_disconnect(uvc);
 
149
 
 
150
        uvc_video_enable(video, 0);
 
151
        mutex_lock(&video->queue.mutex);
 
152
        if (uvc_free_buffers(&video->queue) < 0)
 
153
                printk(KERN_ERR "uvc_v4l2_release: Unable to free "
 
154
                                "buffers.\n");
 
155
        mutex_unlock(&video->queue.mutex);
 
156
 
 
157
        file->private_data = NULL;
 
158
        v4l2_fh_del(&handle->vfh);
 
159
        v4l2_fh_exit(&handle->vfh);
 
160
        kfree(handle);
 
161
        return 0;
 
162
}
 
163
 
 
164
static long
 
165
uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
166
{
 
167
        struct video_device *vdev = video_devdata(file);
 
168
        struct uvc_device *uvc = video_get_drvdata(vdev);
 
169
        struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
 
170
        struct usb_composite_dev *cdev = uvc->func.config->cdev;
 
171
        struct uvc_video *video = &uvc->video;
 
172
        int ret = 0;
 
173
 
 
174
        switch (cmd) {
 
175
        /* Query capabilities */
 
176
        case VIDIOC_QUERYCAP:
 
177
        {
 
178
                struct v4l2_capability *cap = arg;
 
179
 
 
180
                memset(cap, 0, sizeof *cap);
 
181
                strncpy(cap->driver, "g_uvc", sizeof(cap->driver));
 
182
                strncpy(cap->card, cdev->gadget->name, sizeof(cap->card));
 
183
                strncpy(cap->bus_info, dev_name(&cdev->gadget->dev),
 
184
                        sizeof cap->bus_info);
 
185
                cap->version = DRIVER_VERSION_NUMBER;
 
186
                cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
 
187
                break;
 
188
        }
 
189
 
 
190
        /* Get & Set format */
 
191
        case VIDIOC_G_FMT:
 
192
        {
 
193
                struct v4l2_format *fmt = arg;
 
194
 
 
195
                if (fmt->type != video->queue.type)
 
196
                        return -EINVAL;
 
197
 
 
198
                return uvc_v4l2_get_format(video, fmt);
 
199
        }
 
200
 
 
201
        case VIDIOC_S_FMT:
 
202
        {
 
203
                struct v4l2_format *fmt = arg;
 
204
 
 
205
                if (fmt->type != video->queue.type)
 
206
                        return -EINVAL;
 
207
 
 
208
                return uvc_v4l2_set_format(video, fmt);
 
209
        }
 
210
 
 
211
        /* Buffers & streaming */
 
212
        case VIDIOC_REQBUFS:
 
213
        {
 
214
                struct v4l2_requestbuffers *rb = arg;
 
215
 
 
216
                if (rb->type != video->queue.type ||
 
217
                    rb->memory != V4L2_MEMORY_MMAP)
 
218
                        return -EINVAL;
 
219
 
 
220
                ret = uvc_alloc_buffers(&video->queue, rb->count,
 
221
                                        video->imagesize);
 
222
                if (ret < 0)
 
223
                        return ret;
 
224
 
 
225
                rb->count = ret;
 
226
                ret = 0;
 
227
                break;
 
228
        }
 
229
 
 
230
        case VIDIOC_QUERYBUF:
 
231
        {
 
232
                struct v4l2_buffer *buf = arg;
 
233
 
 
234
                if (buf->type != video->queue.type)
 
235
                        return -EINVAL;
 
236
 
 
237
                return uvc_query_buffer(&video->queue, buf);
 
238
        }
 
239
 
 
240
        case VIDIOC_QBUF:
 
241
                if ((ret = uvc_queue_buffer(&video->queue, arg)) < 0)
 
242
                        return ret;
 
243
 
 
244
                return uvc_video_pump(video);
 
245
 
 
246
        case VIDIOC_DQBUF:
 
247
                return uvc_dequeue_buffer(&video->queue, arg,
 
248
                        file->f_flags & O_NONBLOCK);
 
249
 
 
250
        case VIDIOC_STREAMON:
 
251
        {
 
252
                int *type = arg;
 
253
 
 
254
                if (*type != video->queue.type)
 
255
                        return -EINVAL;
 
256
 
 
257
                return uvc_video_enable(video, 1);
 
258
        }
 
259
 
 
260
        case VIDIOC_STREAMOFF:
 
261
        {
 
262
                int *type = arg;
 
263
 
 
264
                if (*type != video->queue.type)
 
265
                        return -EINVAL;
 
266
 
 
267
                return uvc_video_enable(video, 0);
 
268
        }
 
269
 
 
270
        /* Events */
 
271
        case VIDIOC_DQEVENT:
 
272
        {
 
273
                struct v4l2_event *event = arg;
 
274
 
 
275
                ret = v4l2_event_dequeue(&handle->vfh, event,
 
276
                                         file->f_flags & O_NONBLOCK);
 
277
                if (ret == 0 && event->type == UVC_EVENT_SETUP) {
 
278
                        struct uvc_event *uvc_event = (void *)&event->u.data;
 
279
 
 
280
                        /* Tell the complete callback to generate an event for
 
281
                         * the next request that will be enqueued by
 
282
                         * uvc_event_write.
 
283
                         */
 
284
                        uvc->event_setup_out =
 
285
                                !(uvc_event->req.bRequestType & USB_DIR_IN);
 
286
                        uvc->event_length = uvc_event->req.wLength;
 
287
                }
 
288
 
 
289
                return ret;
 
290
        }
 
291
 
 
292
        case VIDIOC_SUBSCRIBE_EVENT:
 
293
        {
 
294
                struct v4l2_event_subscription *sub = arg;
 
295
 
 
296
                if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST)
 
297
                        return -EINVAL;
 
298
 
 
299
                return v4l2_event_subscribe(&handle->vfh, arg, 2);
 
300
        }
 
301
 
 
302
        case VIDIOC_UNSUBSCRIBE_EVENT:
 
303
                return v4l2_event_unsubscribe(&handle->vfh, arg);
 
304
 
 
305
        case UVCIOC_SEND_RESPONSE:
 
306
                ret = uvc_send_response(uvc, arg);
 
307
                break;
 
308
 
 
309
        default:
 
310
                return -ENOIOCTLCMD;
 
311
        }
 
312
 
 
313
        return ret;
 
314
}
 
315
 
 
316
static long
 
317
uvc_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
318
{
 
319
        return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl);
 
320
}
 
321
 
 
322
static int
 
323
uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 
324
{
 
325
        struct video_device *vdev = video_devdata(file);
 
326
        struct uvc_device *uvc = video_get_drvdata(vdev);
 
327
 
 
328
        return uvc_queue_mmap(&uvc->video.queue, vma);
 
329
}
 
330
 
 
331
static unsigned int
 
332
uvc_v4l2_poll(struct file *file, poll_table *wait)
 
333
{
 
334
        struct video_device *vdev = video_devdata(file);
 
335
        struct uvc_device *uvc = video_get_drvdata(vdev);
 
336
        struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
 
337
        unsigned int mask = 0;
 
338
 
 
339
        poll_wait(file, &handle->vfh.wait, wait);
 
340
        if (v4l2_event_pending(&handle->vfh))
 
341
                mask |= POLLPRI;
 
342
 
 
343
        mask |= uvc_queue_poll(&uvc->video.queue, file, wait);
 
344
 
 
345
        return mask;
 
346
}
 
347
 
 
348
static struct v4l2_file_operations uvc_v4l2_fops = {
 
349
        .owner          = THIS_MODULE,
 
350
        .open           = uvc_v4l2_open,
 
351
        .release        = uvc_v4l2_release,
 
352
        .ioctl          = uvc_v4l2_ioctl,
 
353
        .mmap           = uvc_v4l2_mmap,
 
354
        .poll           = uvc_v4l2_poll,
 
355
};
 
356