uvc-gadget: Dynamically watch/unwatch uvc device fd
[uvc-gadget.git] / uvc-gadget.c
1 /*
2  * UVC gadget test application
3  *
4  * Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  */
19
20 #include <sys/time.h>
21 #include <sys/ioctl.h>
22 #include <sys/mman.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <sys/select.h>
26
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <signal.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdint.h>
33 #include <string.h>
34 #include <errno.h>
35
36 #include <linux/usb/ch9.h>
37 #include <linux/usb/g_uvc.h>
38 #include <linux/usb/video.h>
39 #include <linux/videodev2.h>
40
41 #include "events.h"
42
43 #define UVC_INTF_CONTROL        0
44 #define UVC_INTF_STREAMING      1
45
46 #define clamp(val, min, max) ({                 \
47         typeof(val) __val = (val);              \
48         typeof(min) __min = (min);              \
49         typeof(max) __max = (max);              \
50         (void) (&__val == &__min);              \
51         (void) (&__val == &__max);              \
52         __val = __val < __min ? __min: __val;   \
53         __val > __max ? __max: __val; })
54
55 #define ARRAY_SIZE(a)   ((sizeof(a) / sizeof(a[0])))
56
57 struct uvc_device
58 {
59         int fd;
60
61         struct uvc_streaming_control probe;
62         struct uvc_streaming_control commit;
63
64         int control;
65
66         unsigned int fcc;
67         unsigned int width;
68         unsigned int height;
69
70         void **mem;
71         unsigned int nbufs;
72         unsigned int bufsize;
73
74         unsigned int bulk;
75         uint8_t color;
76         unsigned int imgsize;
77         void *imgdata;
78
79         struct events events;
80 };
81
82 static struct uvc_device *
83 uvc_open(const char *devname)
84 {
85         struct uvc_device *dev;
86         struct v4l2_capability cap;
87         int ret;
88         int fd;
89
90         fd = open(devname, O_RDWR | O_NONBLOCK);
91         if (fd == -1) {
92                 printf("v4l2 open failed: %s (%d)\n", strerror(errno), errno);
93                 return NULL;
94         }
95
96         printf("open succeeded, file descriptor = %d\n", fd);
97
98         ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
99         if (ret < 0) {
100                 printf("unable to query device: %s (%d)\n", strerror(errno),
101                         errno);
102                 close(fd);
103                 return NULL;
104         }
105
106         printf("device is %s on bus %s\n", cap.card, cap.bus_info);
107
108         dev = malloc(sizeof *dev);
109         if (dev == NULL) {
110                 close(fd);
111                 return NULL;
112         }
113
114         memset(dev, 0, sizeof *dev);
115         dev->fd = fd;
116
117         events_init(&dev->events);
118
119         return dev;
120 }
121
122 static void
123 uvc_close(struct uvc_device *dev)
124 {
125         close(dev->fd);
126         free(dev->imgdata);
127         free(dev->mem);
128         free(dev);
129 }
130
131 /* ---------------------------------------------------------------------------
132  * Video streaming
133  */
134
135 static void
136 uvc_video_fill_buffer(struct uvc_device *dev, struct v4l2_buffer *buf)
137 {
138         unsigned int bpl;
139         unsigned int i;
140
141         switch (dev->fcc) {
142         case V4L2_PIX_FMT_YUYV:
143                 /* Fill the buffer with video data. */
144                 bpl = dev->width * 2;
145                 for (i = 0; i < dev->height; ++i)
146                         memset(dev->mem[buf->index] + i*bpl, dev->color++, bpl);
147
148                 buf->bytesused = bpl * dev->height;
149                 break;
150
151         case V4L2_PIX_FMT_MJPEG:
152                 memcpy(dev->mem[buf->index], dev->imgdata, dev->imgsize);
153                 buf->bytesused = dev->imgsize;
154                 break;
155         }
156 }
157
158 static void
159 uvc_video_process(void *d)
160 {
161         struct uvc_device *dev = d;
162         struct v4l2_buffer buf;
163         int ret;
164
165         memset(&buf, 0, sizeof buf);
166         buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
167         buf.memory = V4L2_MEMORY_MMAP;
168
169         if ((ret = ioctl(dev->fd, VIDIOC_DQBUF, &buf)) < 0) {
170                 printf("Unable to dequeue buffer: %s (%d).\n", strerror(errno),
171                         errno);
172                 return;
173         }
174
175         uvc_video_fill_buffer(dev, &buf);
176
177         if ((ret = ioctl(dev->fd, VIDIOC_QBUF, &buf)) < 0) {
178                 printf("Unable to requeue buffer: %s (%d).\n", strerror(errno),
179                         errno);
180                 return;
181         }
182 }
183
184 static int
185 uvc_video_reqbufs(struct uvc_device *dev, int nbufs)
186 {
187         struct v4l2_requestbuffers rb;
188         struct v4l2_buffer buf;
189         unsigned int i;
190         int ret;
191
192         for (i = 0; i < dev->nbufs; ++i)
193                 munmap(dev->mem[i], dev->bufsize);
194
195         free(dev->mem);
196         dev->mem = 0;
197         dev->nbufs = 0;
198
199         memset(&rb, 0, sizeof rb);
200         rb.count = nbufs;
201         rb.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
202         rb.memory = V4L2_MEMORY_MMAP;
203
204         ret = ioctl(dev->fd, VIDIOC_REQBUFS, &rb);
205         if (ret < 0) {
206                 printf("Unable to allocate buffers: %s (%d).\n",
207                         strerror(errno), errno);
208                 return ret;
209         }
210
211         printf("%u buffers allocated.\n", rb.count);
212
213         /* Map the buffers. */
214         dev->mem = malloc(rb.count * sizeof dev->mem[0]);
215
216         for (i = 0; i < rb.count; ++i) {
217                 memset(&buf, 0, sizeof buf);
218                 buf.index = i;
219                 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
220                 buf.memory = V4L2_MEMORY_MMAP;
221                 ret = ioctl(dev->fd, VIDIOC_QUERYBUF, &buf);
222                 if (ret < 0) {
223                         printf("Unable to query buffer %u: %s (%d).\n", i,
224                                 strerror(errno), errno);
225                         return -1;
226                 }
227                 printf("length: %u offset: %u\n", buf.length, buf.m.offset);
228
229                 dev->mem[i] = mmap(0, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, dev->fd, buf.m.offset);
230                 if (dev->mem[i] == MAP_FAILED) {
231                         printf("Unable to map buffer %u: %s (%d)\n", i,
232                                 strerror(errno), errno);
233                         return -1;
234                 }
235                 printf("Buffer %u mapped at address %p.\n", i, dev->mem[i]);
236         }
237
238         dev->bufsize = buf.length;
239         dev->nbufs = rb.count;
240
241         return 0;
242 }
243
244 static int
245 uvc_video_stream(struct uvc_device *dev, int enable)
246 {
247         struct v4l2_buffer buf;
248         unsigned int i;
249         int type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
250         int ret;
251
252         if (!enable) {
253                 printf("Stopping video stream.\n");
254                 events_unwatch_fd(&dev->events, dev->fd, EVENT_WRITE);
255                 ioctl(dev->fd, VIDIOC_STREAMOFF, &type);
256                 return 0;
257         }
258
259         printf("Starting video stream.\n");
260
261         for (i = 0; i < dev->nbufs; ++i) {
262                 memset(&buf, 0, sizeof buf);
263
264                 buf.index = i;
265                 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
266                 buf.memory = V4L2_MEMORY_MMAP;
267
268                 uvc_video_fill_buffer(dev, &buf);
269
270                 printf("Queueing buffer %u.\n", i);
271                 if ((ret = ioctl(dev->fd, VIDIOC_QBUF, &buf)) < 0) {
272                         printf("Unable to queue buffer: %s (%d).\n",
273                                 strerror(errno), errno);
274                         break;
275                 }
276         }
277
278         ioctl(dev->fd, VIDIOC_STREAMON, &type);
279         events_watch_fd(&dev->events, dev->fd, EVENT_WRITE,
280                         uvc_video_process, dev);
281         return ret;
282 }
283
284 static int
285 uvc_video_set_format(struct uvc_device *dev)
286 {
287         struct v4l2_format fmt;
288         int ret;
289
290         printf("Setting format to 0x%08x %ux%u\n",
291                 dev->fcc, dev->width, dev->height);
292
293         memset(&fmt, 0, sizeof fmt);
294         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
295         fmt.fmt.pix.width = dev->width;
296         fmt.fmt.pix.height = dev->height;
297         fmt.fmt.pix.pixelformat = dev->fcc;
298         fmt.fmt.pix.field = V4L2_FIELD_NONE;
299         if (dev->fcc == V4L2_PIX_FMT_MJPEG)
300                 fmt.fmt.pix.sizeimage = dev->imgsize * 1.5;
301
302         if ((ret = ioctl(dev->fd, VIDIOC_S_FMT, &fmt)) < 0)
303                 printf("Unable to set format: %s (%d).\n",
304                         strerror(errno), errno);
305
306         return ret;
307 }
308
309 static int
310 uvc_video_init(struct uvc_device *dev __attribute__((__unused__)))
311 {
312         return 0;
313 }
314
315 /* ---------------------------------------------------------------------------
316  * Request processing
317  */
318
319 struct uvc_frame_info
320 {
321         unsigned int width;
322         unsigned int height;
323         unsigned int intervals[8];
324 };
325
326 struct uvc_format_info
327 {
328         unsigned int fcc;
329         const struct uvc_frame_info *frames;
330 };
331
332 static const struct uvc_frame_info uvc_frames_yuyv[] = {
333         {  640, 360, { 666666, 10000000, 50000000, 0 }, },
334         { 1280, 720, { 50000000, 0 }, },
335         { 0, 0, { 0, }, },
336 };
337
338 static const struct uvc_frame_info uvc_frames_mjpeg[] = {
339         {  640, 360, { 666666, 10000000, 50000000, 0 }, },
340         { 1280, 720, { 50000000, 0 }, },
341         { 0, 0, { 0, }, },
342 };
343
344 static const struct uvc_format_info uvc_formats[] = {
345         { V4L2_PIX_FMT_YUYV, uvc_frames_yuyv },
346         { V4L2_PIX_FMT_MJPEG, uvc_frames_mjpeg },
347 };
348
349 static void
350 uvc_fill_streaming_control(struct uvc_device *dev,
351                            struct uvc_streaming_control *ctrl,
352                            int iframe, int iformat)
353 {
354         const struct uvc_format_info *format;
355         const struct uvc_frame_info *frame;
356         unsigned int nframes;
357
358         if (iformat < 0)
359                 iformat = ARRAY_SIZE(uvc_formats) + iformat;
360         if (iformat < 0 || iformat >= (int)ARRAY_SIZE(uvc_formats))
361                 return;
362         format = &uvc_formats[iformat];
363
364         nframes = 0;
365         while (format->frames[nframes].width != 0)
366                 ++nframes;
367
368         if (iframe < 0)
369                 iframe = nframes + iframe;
370         if (iframe < 0 || iframe >= (int)nframes)
371                 return;
372         frame = &format->frames[iframe];
373
374         memset(ctrl, 0, sizeof *ctrl);
375
376         ctrl->bmHint = 1;
377         ctrl->bFormatIndex = iformat + 1;
378         ctrl->bFrameIndex = iframe + 1;
379         ctrl->dwFrameInterval = frame->intervals[0];
380         switch (format->fcc) {
381         case V4L2_PIX_FMT_YUYV:
382                 ctrl->dwMaxVideoFrameSize = frame->width * frame->height * 2;
383                 break;
384         case V4L2_PIX_FMT_MJPEG:
385                 ctrl->dwMaxVideoFrameSize = dev->imgsize;
386                 break;
387         }
388         ctrl->dwMaxPayloadTransferSize = 512;   /* TODO this should be filled by the driver. */
389         ctrl->bmFramingInfo = 3;
390         ctrl->bPreferedVersion = 1;
391         ctrl->bMaxVersion = 1;
392 }
393
394 static void
395 uvc_events_process_standard(struct uvc_device *dev, struct usb_ctrlrequest *ctrl,
396                             struct uvc_request_data *resp)
397 {
398         printf("standard request\n");
399         (void)dev;
400         (void)ctrl;
401         (void)resp;
402 }
403
404 static void
405 uvc_events_process_control(struct uvc_device *dev, uint8_t req, uint8_t cs,
406                            struct uvc_request_data *resp)
407 {
408         printf("control request (req %02x cs %02x)\n", req, cs);
409         (void)dev;
410         (void)resp;
411 }
412
413 static void
414 uvc_events_process_streaming(struct uvc_device *dev, uint8_t req, uint8_t cs,
415                              struct uvc_request_data *resp)
416 {
417         struct uvc_streaming_control *ctrl;
418
419         printf("streaming request (req %02x cs %02x)\n", req, cs);
420
421         if (cs != UVC_VS_PROBE_CONTROL && cs != UVC_VS_COMMIT_CONTROL)
422                 return;
423
424         ctrl = (struct uvc_streaming_control *)&resp->data;
425         resp->length = sizeof *ctrl;
426
427         switch (req) {
428         case UVC_SET_CUR:
429                 dev->control = cs;
430                 resp->length = 34;
431                 break;
432
433         case UVC_GET_CUR:
434                 if (cs == UVC_VS_PROBE_CONTROL)
435                         memcpy(ctrl, &dev->probe, sizeof *ctrl);
436                 else
437                         memcpy(ctrl, &dev->commit, sizeof *ctrl);
438                 break;
439
440         case UVC_GET_MIN:
441         case UVC_GET_MAX:
442         case UVC_GET_DEF:
443                 uvc_fill_streaming_control(dev, ctrl, req == UVC_GET_MAX ? -1 : 0,
444                                            req == UVC_GET_MAX ? -1 : 0);
445                 break;
446
447         case UVC_GET_RES:
448                 memset(ctrl, 0, sizeof *ctrl);
449                 break;
450
451         case UVC_GET_LEN:
452                 resp->data[0] = 0x00;
453                 resp->data[1] = 0x22;
454                 resp->length = 2;
455                 break;
456
457         case UVC_GET_INFO:
458                 resp->data[0] = 0x03;
459                 resp->length = 1;
460                 break;
461         }
462 }
463
464 static void
465 uvc_events_process_class(struct uvc_device *dev, struct usb_ctrlrequest *ctrl,
466                          struct uvc_request_data *resp)
467 {
468         if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE)
469                 return;
470
471         switch (ctrl->wIndex & 0xff) {
472         case UVC_INTF_CONTROL:
473                 uvc_events_process_control(dev, ctrl->bRequest, ctrl->wValue >> 8, resp);
474                 break;
475
476         case UVC_INTF_STREAMING:
477                 uvc_events_process_streaming(dev, ctrl->bRequest, ctrl->wValue >> 8, resp);
478                 break;
479
480         default:
481                 break;
482         }
483 }
484
485 static void
486 uvc_events_process_setup(struct uvc_device *dev, struct usb_ctrlrequest *ctrl,
487                          struct uvc_request_data *resp)
488 {
489         dev->control = 0;
490
491         printf("bRequestType %02x bRequest %02x wValue %04x wIndex %04x "
492                 "wLength %04x\n", ctrl->bRequestType, ctrl->bRequest,
493                 ctrl->wValue, ctrl->wIndex, ctrl->wLength);
494
495         switch (ctrl->bRequestType & USB_TYPE_MASK) {
496         case USB_TYPE_STANDARD:
497                 uvc_events_process_standard(dev, ctrl, resp);
498                 break;
499
500         case USB_TYPE_CLASS:
501                 uvc_events_process_class(dev, ctrl, resp);
502                 break;
503
504         default:
505                 break;
506         }
507 }
508
509 static void
510 uvc_events_process_data(struct uvc_device *dev, struct uvc_request_data *data)
511 {
512         struct uvc_streaming_control *target;
513         struct uvc_streaming_control *ctrl;
514         const struct uvc_format_info *format;
515         const struct uvc_frame_info *frame;
516         const unsigned int *interval;
517         unsigned int iformat, iframe;
518         unsigned int nframes;
519
520         switch (dev->control) {
521         case UVC_VS_PROBE_CONTROL:
522                 printf("setting probe control, length = %d\n", data->length);
523                 target = &dev->probe;
524                 break;
525
526         case UVC_VS_COMMIT_CONTROL:
527                 printf("setting commit control, length = %d\n", data->length);
528                 target = &dev->commit;
529                 break;
530
531         default:
532                 printf("setting unknown control, length = %d\n", data->length);
533                 return;
534         }
535
536         ctrl = (struct uvc_streaming_control *)&data->data;
537         iformat = clamp((unsigned int)ctrl->bFormatIndex, 1U,
538                         (unsigned int)ARRAY_SIZE(uvc_formats));
539         format = &uvc_formats[iformat-1];
540
541         nframes = 0;
542         while (format->frames[nframes].width != 0)
543                 ++nframes;
544
545         iframe = clamp((unsigned int)ctrl->bFrameIndex, 1U, nframes);
546         frame = &format->frames[iframe-1];
547         interval = frame->intervals;
548
549         while (interval[0] < ctrl->dwFrameInterval && interval[1])
550                 ++interval;
551
552         target->bFormatIndex = iformat;
553         target->bFrameIndex = iframe;
554         switch (format->fcc) {
555         case V4L2_PIX_FMT_YUYV:
556                 target->dwMaxVideoFrameSize = frame->width * frame->height * 2;
557                 break;
558         case V4L2_PIX_FMT_MJPEG:
559                 if (dev->imgsize == 0)
560                         printf("WARNING: MJPEG requested and no image loaded.\n");
561                 target->dwMaxVideoFrameSize = dev->imgsize;
562                 break;
563         }
564         target->dwFrameInterval = *interval;
565
566         if (dev->control == UVC_VS_COMMIT_CONTROL) {
567                 dev->fcc = format->fcc;
568                 dev->width = frame->width;
569                 dev->height = frame->height;
570
571                 uvc_video_set_format(dev);
572                 if (dev->bulk)
573                         uvc_video_stream(dev, 1);
574         }
575 }
576
577 static void
578 uvc_events_process(void *d)
579 {
580         struct uvc_device *dev = d;
581         struct v4l2_event v4l2_event;
582         struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
583         struct uvc_request_data resp;
584         int ret;
585
586         ret = ioctl(dev->fd, VIDIOC_DQEVENT, &v4l2_event);
587         if (ret < 0) {
588                 printf("VIDIOC_DQEVENT failed: %s (%d)\n", strerror(errno),
589                         errno);
590                 return;
591         }
592
593         memset(&resp, 0, sizeof resp);
594         resp.length = -EL2HLT;
595
596         switch (v4l2_event.type) {
597         case UVC_EVENT_CONNECT:
598         case UVC_EVENT_DISCONNECT:
599                 return;
600
601         case UVC_EVENT_SETUP:
602                 uvc_events_process_setup(dev, &uvc_event->req, &resp);
603                 break;
604
605         case UVC_EVENT_DATA:
606                 uvc_events_process_data(dev, &uvc_event->data);
607                 return;
608
609         case UVC_EVENT_STREAMON:
610                 uvc_video_reqbufs(dev, 4);
611                 uvc_video_stream(dev, 1);
612                 return;
613
614         case UVC_EVENT_STREAMOFF:
615                 uvc_video_stream(dev, 0);
616                 uvc_video_reqbufs(dev, 0);
617                 return;
618         }
619
620         ioctl(dev->fd, UVCIOC_SEND_RESPONSE, &resp);
621         if (ret < 0) {
622                 printf("UVCIOC_S_EVENT failed: %s (%d)\n", strerror(errno),
623                         errno);
624                 return;
625         }
626 }
627
628 static void
629 uvc_events_init(struct uvc_device *dev)
630 {
631         struct v4l2_event_subscription sub;
632
633         uvc_fill_streaming_control(dev, &dev->probe, 0, 0);
634         uvc_fill_streaming_control(dev, &dev->commit, 0, 0);
635
636         if (dev->bulk) {
637                 /* FIXME Crude hack, must be negotiated with the driver. */
638                 dev->probe.dwMaxPayloadTransferSize = 16 * 1024;
639                 dev->commit.dwMaxPayloadTransferSize = 16 * 1024;
640         }
641
642
643         memset(&sub, 0, sizeof sub);
644         sub.type = UVC_EVENT_SETUP;
645         ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
646         sub.type = UVC_EVENT_DATA;
647         ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
648         sub.type = UVC_EVENT_STREAMON;
649         ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
650         sub.type = UVC_EVENT_STREAMOFF;
651         ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
652 }
653
654 /* ---------------------------------------------------------------------------
655  * main
656  */
657
658 static void image_load(struct uvc_device *dev, const char *img)
659 {
660         int fd = -1;
661
662         if (img == NULL)
663                 return;
664
665         fd = open(img, O_RDONLY);
666         if (fd == -1) {
667                 printf("Unable to open MJPEG image '%s'\n", img);
668                 return;
669         }
670
671         dev->imgsize = lseek(fd, 0, SEEK_END);
672         lseek(fd, 0, SEEK_SET);
673         dev->imgdata = malloc(dev->imgsize);
674         if (dev->imgdata == NULL) {
675                 printf("Unable to allocate memory for MJPEG image\n");
676                 dev->imgsize = 0;
677                 return;
678         }
679
680         read(fd, dev->imgdata, dev->imgsize);
681         close(fd);
682 }
683
684 static void usage(const char *argv0)
685 {
686         fprintf(stderr, "Usage: %s [options]\n", argv0);
687         fprintf(stderr, "Available options are\n");
688         fprintf(stderr, " -b            Use bulk mode\n");
689         fprintf(stderr, " -d device     Video device\n");
690         fprintf(stderr, " -h            Print this help screen and exit\n");
691         fprintf(stderr, " -i image      MJPEG image\n");
692 }
693
694 /* Necesssary for and only used by signal handler. */
695 static struct uvc_device *uvc_device;
696
697 static void sigint_handler(int signal __attribute__((__unused__)))
698 {
699         /* Stop the main loop when the user presses CTRL-C */
700         events_stop(&uvc_device->events);
701 }
702
703 int main(int argc, char *argv[])
704 {
705         char *device = "/dev/video0";
706         struct uvc_device *dev;
707         int bulk_mode = 0;
708         char *mjpeg_image = NULL;
709         int opt;
710
711         while ((opt = getopt(argc, argv, "bd:hi:")) != -1) {
712                 switch (opt) {
713                 case 'b':
714                         bulk_mode = 1;
715                         break;
716
717                 case 'd':
718                         device = optarg;
719                         break;
720
721                 case 'h':
722                         usage(argv[0]);
723                         return 0;
724
725                 case 'i':
726                         mjpeg_image = optarg;
727                         break;
728
729                 default:
730                         fprintf(stderr, "Invalid option '-%c'\n", opt);
731                         usage(argv[0]);
732                         return 1;
733                 }
734         }
735
736         dev = uvc_open(device);
737         if (dev == NULL)
738                 return 1;
739
740         image_load(dev, mjpeg_image);
741
742         dev->bulk = bulk_mode;
743
744         uvc_events_init(dev);
745         uvc_video_init(dev);
746
747         /*
748          * Register a signal handler for SIGINT, received when the user presses
749          * CTRL-C. This will allow the main loop to be interrupted, and resources
750          * to be freed cleanly.
751          */
752         uvc_device = dev;
753         signal(SIGINT, sigint_handler);
754
755         events_watch_fd(&dev->events, dev->fd, EVENT_EXCEPTION,
756                         uvc_events_process, dev);
757
758         /* Main capture loop */
759         events_loop(&dev->events);
760
761         events_cleanup(&dev->events);
762         uvc_close(dev);
763         return 0;
764 }
765