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->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 = queue->mem + buf->buf.m.offset + queue->buf_used;
51 nbytes = min((unsigned int)len, buf->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->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->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->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_buffer *buf;
165 unsigned long flags;
166 int ret;
167
168 switch (req->status) {
169 case 0:
170 break;
171
172 case -ESHUTDOWN:
173 printk(KERN_INFO "VS request cancelled.\n");
174 goto requeue;
175
176 default:
177 printk(KERN_INFO "VS request completed with status %d.\n",
178 req->status);
179 goto requeue;
180 }
181
182 spin_lock_irqsave(&video->queue.irqlock, flags);
183 buf = uvc_queue_head(&video->queue);
184 if (buf == NULL) {
185 spin_unlock_irqrestore(&video->queue.irqlock, flags);
186 goto requeue;
187 }
188
189 video->encode(req, video, buf);
190
191 if ((ret = usb_ep_queue(ep, req, GFP_ATOMIC)) < 0) {
192 printk(KERN_INFO "Failed to queue request (%d).\n", ret);
193 usb_ep_set_halt(ep);
194 spin_unlock_irqrestore(&video->queue.irqlock, flags);
195 goto requeue;
196 }
197 spin_unlock_irqrestore(&video->queue.irqlock, flags);
198
199 return;
200
201requeue:
202 spin_lock_irqsave(&video->req_lock, flags);
203 list_add_tail(&req->list, &video->req_free);
204 spin_unlock_irqrestore(&video->req_lock, flags);
205}
206
207static int
208uvc_video_free_requests(struct uvc_video *video)
209{
210 unsigned int i;
211
212 for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
213 if (video->req[i]) {
214 usb_ep_free_request(video->ep, video->req[i]);
215 video->req[i] = NULL;
216 }
217
218 if (video->req_buffer[i]) {
219 kfree(video->req_buffer[i]);
220 video->req_buffer[i] = NULL;
221 }
222 }
223
224 INIT_LIST_HEAD(&video->req_free);
225 video->req_size = 0;
226 return 0;
227}
228
229static int
230uvc_video_alloc_requests(struct uvc_video *video)
231{
232 unsigned int i;
233 int ret = -ENOMEM;
234
235 BUG_ON(video->req_size);
236
237 for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
238 video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL);
239 if (video->req_buffer[i] == NULL)
240 goto error;
241
242 video->req[i] = usb_ep_alloc_request(video->ep, GFP_KERNEL);
243 if (video->req[i] == NULL)
244 goto error;
245
246 video->req[i]->buf = video->req_buffer[i];
247 video->req[i]->length = 0;
248 video->req[i]->dma = DMA_ADDR_INVALID;
249 video->req[i]->complete = uvc_video_complete;
250 video->req[i]->context = video;
251
252 list_add_tail(&video->req[i]->list, &video->req_free);
253 }
254
255 video->req_size = video->ep->maxpacket;
256 return 0;
257
258error:
259 uvc_video_free_requests(video);
260 return ret;
261}
262
263
264
265
266
267
268
269
270
271
272
273static int
274uvc_video_pump(struct uvc_video *video)
275{
276 struct usb_request *req;
277 struct uvc_buffer *buf;
278 unsigned long flags;
279 int ret;
280
281
282
283
284
285 while (1) {
286
287
288
289 spin_lock_irqsave(&video->req_lock, flags);
290 if (list_empty(&video->req_free)) {
291 spin_unlock_irqrestore(&video->req_lock, flags);
292 return 0;
293 }
294 req = list_first_entry(&video->req_free, struct usb_request,
295 list);
296 list_del(&req->list);
297 spin_unlock_irqrestore(&video->req_lock, flags);
298
299
300
301
302 spin_lock_irqsave(&video->queue.irqlock, flags);
303 buf = uvc_queue_head(&video->queue);
304 if (buf == NULL) {
305 spin_unlock_irqrestore(&video->queue.irqlock, flags);
306 break;
307 }
308
309 video->encode(req, video, buf);
310
311
312 if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) {
313 printk(KERN_INFO "Failed to queue request (%d)\n", ret);
314 usb_ep_set_halt(video->ep);
315 spin_unlock_irqrestore(&video->queue.irqlock, flags);
316 break;
317 }
318 spin_unlock_irqrestore(&video->queue.irqlock, flags);
319 }
320
321 spin_lock_irqsave(&video->req_lock, flags);
322 list_add_tail(&req->list, &video->req_free);
323 spin_unlock_irqrestore(&video->req_lock, flags);
324 return 0;
325}
326
327
328
329
330static int
331uvc_video_enable(struct uvc_video *video, int enable)
332{
333 unsigned int i;
334 int ret;
335
336 if (video->ep == NULL) {
337 printk(KERN_INFO "Video enable failed, device is "
338 "uninitialized.\n");
339 return -ENODEV;
340 }
341
342 if (!enable) {
343 for (i = 0; i < UVC_NUM_REQUESTS; ++i)
344 usb_ep_dequeue(video->ep, video->req[i]);
345
346 uvc_video_free_requests(video);
347 uvc_queue_enable(&video->queue, 0);
348 return 0;
349 }
350
351 if ((ret = uvc_queue_enable(&video->queue, 1)) < 0)
352 return ret;
353
354 if ((ret = uvc_video_alloc_requests(video)) < 0)
355 return ret;
356
357 if (video->max_payload_size) {
358 video->encode = uvc_video_encode_bulk;
359 video->payload_size = 0;
360 } else
361 video->encode = uvc_video_encode_isoc;
362
363 return uvc_video_pump(video);
364}
365
366
367
368
369static int
370uvc_video_init(struct uvc_video *video)
371{
372 INIT_LIST_HEAD(&video->req_free);
373 spin_lock_init(&video->req_lock);
374
375 video->fcc = V4L2_PIX_FMT_YUYV;
376 video->bpp = 16;
377 video->width = 320;
378 video->height = 240;
379 video->imagesize = 320 * 240 * 2;
380
381
382 uvc_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT);
383 return 0;
384}
385
386