1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/kernel.h>
14#include <linux/device.h>
15#include <linux/errno.h>
16#include <linux/usb/ch9.h>
17#include <linux/usb/gadget.h>
18#include <linux/usb/video.h>
19
20#include <media/v4l2-dev.h>
21
22#include "uvc.h"
23#include "uvc_queue.h"
24#include "uvc_video.h"
25
26
27
28
29
30static int
31uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
32 u8 *data, int len)
33{
34 data[0] = 2;
35 data[1] = UVC_STREAM_EOH | video->fid;
36
37 if (buf->bytesused - video->queue.buf_used <= len - 2)
38 data[1] |= UVC_STREAM_EOF;
39
40 return 2;
41}
42
43static int
44uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,
45 u8 *data, int len)
46{
47 struct uvc_video_queue *queue = &video->queue;
48 unsigned int nbytes;
49 void *mem;
50
51
52 mem = buf->mem + queue->buf_used;
53 nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
54
55 memcpy(data, mem, nbytes);
56 queue->buf_used += nbytes;
57
58 return nbytes;
59}
60
61static void
62uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
63 struct uvc_buffer *buf)
64{
65 void *mem = req->buf;
66 int len = video->req_size;
67 int ret;
68
69
70 if (video->payload_size == 0) {
71 ret = uvc_video_encode_header(video, buf, mem, len);
72 video->payload_size += ret;
73 mem += ret;
74 len -= ret;
75 }
76
77
78 len = min((int)(video->max_payload_size - video->payload_size), len);
79 ret = uvc_video_encode_data(video, buf, mem, len);
80
81 video->payload_size += ret;
82 len -= ret;
83
84 req->length = video->req_size - len;
85 req->zero = video->payload_size == video->max_payload_size;
86
87 if (buf->bytesused == video->queue.buf_used) {
88 video->queue.buf_used = 0;
89 buf->state = UVC_BUF_STATE_DONE;
90 uvcg_queue_next_buffer(&video->queue, buf);
91 video->fid ^= UVC_STREAM_FID;
92
93 video->payload_size = 0;
94 }
95
96 if (video->payload_size == video->max_payload_size ||
97 buf->bytesused == video->queue.buf_used)
98 video->payload_size = 0;
99}
100
101static void
102uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
103 struct uvc_buffer *buf)
104{
105 void *mem = req->buf;
106 int len = video->req_size;
107 int ret;
108
109
110 ret = uvc_video_encode_header(video, buf, mem, len);
111 mem += ret;
112 len -= ret;
113
114
115 ret = uvc_video_encode_data(video, buf, mem, len);
116 len -= ret;
117
118 req->length = video->req_size - len;
119
120 if (buf->bytesused == video->queue.buf_used) {
121 video->queue.buf_used = 0;
122 buf->state = UVC_BUF_STATE_DONE;
123 uvcg_queue_next_buffer(&video->queue, buf);
124 video->fid ^= UVC_STREAM_FID;
125 }
126}
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162static void
163uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
164{
165 struct uvc_video *video = req->context;
166 struct uvc_video_queue *queue = &video->queue;
167 struct uvc_buffer *buf;
168 unsigned long flags;
169 int ret;
170
171 switch (req->status) {
172 case 0:
173 break;
174
175 case -ESHUTDOWN:
176 printk(KERN_DEBUG "VS request cancelled.\n");
177 uvcg_queue_cancel(queue, 1);
178 goto requeue;
179
180 default:
181 printk(KERN_INFO "VS request completed with status %d.\n",
182 req->status);
183 uvcg_queue_cancel(queue, 0);
184 goto requeue;
185 }
186
187 spin_lock_irqsave(&video->queue.irqlock, flags);
188 buf = uvcg_queue_head(&video->queue);
189 if (buf == NULL) {
190 spin_unlock_irqrestore(&video->queue.irqlock, flags);
191 goto requeue;
192 }
193
194 video->encode(req, video, buf);
195
196 if ((ret = usb_ep_queue(ep, req, GFP_ATOMIC)) < 0) {
197 printk(KERN_INFO "Failed to queue request (%d).\n", ret);
198 usb_ep_set_halt(ep);
199 spin_unlock_irqrestore(&video->queue.irqlock, flags);
200 uvcg_queue_cancel(queue, 0);
201 goto requeue;
202 }
203 spin_unlock_irqrestore(&video->queue.irqlock, flags);
204
205 return;
206
207requeue:
208 spin_lock_irqsave(&video->req_lock, flags);
209 list_add_tail(&req->list, &video->req_free);
210 spin_unlock_irqrestore(&video->req_lock, flags);
211}
212
213static int
214uvc_video_free_requests(struct uvc_video *video)
215{
216 unsigned int i;
217
218 for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
219 if (video->req[i]) {
220 usb_ep_free_request(video->ep, video->req[i]);
221 video->req[i] = NULL;
222 }
223
224 if (video->req_buffer[i]) {
225 kfree(video->req_buffer[i]);
226 video->req_buffer[i] = NULL;
227 }
228 }
229
230 INIT_LIST_HEAD(&video->req_free);
231 video->req_size = 0;
232 return 0;
233}
234
235static int
236uvc_video_alloc_requests(struct uvc_video *video)
237{
238 unsigned int req_size;
239 unsigned int i;
240 int ret = -ENOMEM;
241
242 BUG_ON(video->req_size);
243
244 req_size = video->ep->maxpacket
245 * max_t(unsigned int, video->ep->maxburst, 1)
246 * (video->ep->mult + 1);
247
248 for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
249 video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
250 if (video->req_buffer[i] == NULL)
251 goto error;
252
253 video->req[i] = usb_ep_alloc_request(video->ep, GFP_KERNEL);
254 if (video->req[i] == NULL)
255 goto error;
256
257 video->req[i]->buf = video->req_buffer[i];
258 video->req[i]->length = 0;
259 video->req[i]->complete = uvc_video_complete;
260 video->req[i]->context = video;
261
262 list_add_tail(&video->req[i]->list, &video->req_free);
263 }
264
265 video->req_size = req_size;
266
267 return 0;
268
269error:
270 uvc_video_free_requests(video);
271 return ret;
272}
273
274
275
276
277
278
279
280
281
282
283
284int uvcg_video_pump(struct uvc_video *video)
285{
286 struct uvc_video_queue *queue = &video->queue;
287 struct usb_request *req;
288 struct uvc_buffer *buf;
289 unsigned long flags;
290 int ret;
291
292
293
294
295
296 while (1) {
297
298
299
300 spin_lock_irqsave(&video->req_lock, flags);
301 if (list_empty(&video->req_free)) {
302 spin_unlock_irqrestore(&video->req_lock, flags);
303 return 0;
304 }
305 req = list_first_entry(&video->req_free, struct usb_request,
306 list);
307 list_del(&req->list);
308 spin_unlock_irqrestore(&video->req_lock, flags);
309
310
311
312
313 spin_lock_irqsave(&queue->irqlock, flags);
314 buf = uvcg_queue_head(queue);
315 if (buf == NULL) {
316 spin_unlock_irqrestore(&queue->irqlock, flags);
317 break;
318 }
319
320 video->encode(req, video, buf);
321
322
323 ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
324 if (ret < 0) {
325 printk(KERN_INFO "Failed to queue request (%d)\n", ret);
326 usb_ep_set_halt(video->ep);
327 spin_unlock_irqrestore(&queue->irqlock, flags);
328 uvcg_queue_cancel(queue, 0);
329 break;
330 }
331 spin_unlock_irqrestore(&queue->irqlock, flags);
332 }
333
334 spin_lock_irqsave(&video->req_lock, flags);
335 list_add_tail(&req->list, &video->req_free);
336 spin_unlock_irqrestore(&video->req_lock, flags);
337 return 0;
338}
339
340
341
342
343int uvcg_video_enable(struct uvc_video *video, int enable)
344{
345 unsigned int i;
346 int ret;
347
348 if (video->ep == NULL) {
349 printk(KERN_INFO "Video enable failed, device is "
350 "uninitialized.\n");
351 return -ENODEV;
352 }
353
354 if (!enable) {
355 for (i = 0; i < UVC_NUM_REQUESTS; ++i)
356 if (video->req[i])
357 usb_ep_dequeue(video->ep, video->req[i]);
358
359 uvc_video_free_requests(video);
360 uvcg_queue_enable(&video->queue, 0);
361 return 0;
362 }
363
364 if ((ret = uvcg_queue_enable(&video->queue, 1)) < 0)
365 return ret;
366
367 if ((ret = uvc_video_alloc_requests(video)) < 0)
368 return ret;
369
370 if (video->max_payload_size) {
371 video->encode = uvc_video_encode_bulk;
372 video->payload_size = 0;
373 } else
374 video->encode = uvc_video_encode_isoc;
375
376 return uvcg_video_pump(video);
377}
378
379
380
381
382int uvcg_video_init(struct uvc_video *video)
383{
384 INIT_LIST_HEAD(&video->req_free);
385 spin_lock_init(&video->req_lock);
386
387 video->fcc = V4L2_PIX_FMT_YUYV;
388 video->bpp = 16;
389 video->width = 320;
390 video->height = 240;
391 video->imagesize = 320 * 240 * 2;
392
393
394 uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT,
395 &video->mutex);
396 return 0;
397}
398
399