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