uvc-gadget: Use events library
[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                 ioctl(dev->fd, VIDIOC_STREAMOFF, &type);
255                 return 0;
256         }
257
258         printf("Starting video stream.\n");
259
260         for (i = 0; i < dev->nbufs; ++i) {
261                 memset(&buf, 0, sizeof buf);
262
263                 buf.index = i;
264                 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
265                 buf.memory = V4L2_MEMORY_MMAP;
266
267                 uvc_video_fill_buffer(dev, &buf);
268
269                 printf("Queueing buffer %u.\n", i);
270                 if ((ret = ioctl(dev->fd, VIDIOC_QBUF, &buf)) < 0) {
271                         printf("Unable to queue buffer: %s (%d).\n",
272                                 strerror(errno), errno);
273                         break;
274                 }
275         }
276
277         ioctl(dev->fd, VIDIOC_STREAMON, &type);
278         return ret;
279 }
280
281 static int
282 uvc_video_set_format(struct uvc_device *dev)
283 {
284         struct v4l2_format fmt;
285         int ret;
286
287         printf("Setting format to 0x%08x %ux%u\n",
288                 dev->fcc, dev->width, dev->height);
289
290         memset(&fmt, 0, sizeof fmt);
291         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
292         fmt.fmt.pix.width = dev->width;
293         fmt.fmt.pix.height = dev->height;
294         fmt.fmt.pix.pixelformat = dev->fcc;
295         fmt.fmt.pix.field = V4L2_FIELD_NONE;
296         if (dev->fcc == V4L2_PIX_FMT_MJPEG)
297                 fmt.fmt.pix.sizeimage = dev->imgsize * 1.5;
298
299         if ((ret = ioctl(dev->fd, VIDIOC_S_FMT, &fmt)) < 0)
300                 printf("Unable to set format: %s (%d).\n",
301                         strerror(errno), errno);
302
303         return ret;
304 }
305
306 static int
307 uvc_video_init(struct uvc_device *dev __attribute__((__unused__)))
308 {
309         return 0;
310 }
311
312 /* ---------------------------------------------------------------------------
313  * Request processing
314  */
315
316 struct uvc_frame_info
317 {
318         unsigned int width;
319         unsigned int height;
320         unsigned int intervals[8];
321 };
322
323 struct uvc_format_info
324 {
325         unsigned int fcc;
326         const struct uvc_frame_info *frames;
327 };
328
329 static const struct uvc_frame_info uvc_frames_yuyv[] = {
330         {  640, 360, { 666666, 10000000, 50000000, 0 }, },
331         { 1280, 720, { 50000000, 0 }, },
332         { 0, 0, { 0, }, },
333 };
334
335 static const struct uvc_frame_info uvc_frames_mjpeg[] = {
336         {  640, 360, { 666666, 10000000, 50000000, 0 }, },
337         { 1280, 720, { 50000000, 0 }, },
338         { 0, 0, { 0, }, },
339 };
340
341 static const struct uvc_format_info uvc_formats[] = {
342         { V4L2_PIX_FMT_YUYV, uvc_frames_yuyv },
343         { V4L2_PIX_FMT_MJPEG, uvc_frames_mjpeg },
344 };
345
346 static void
347 uvc_fill_streaming_control(struct uvc_device *dev,
348                            struct uvc_streaming_control *ctrl,
349                            int iframe, int iformat)
350 {
351         const struct uvc_format_info *format;
352         const struct uvc_frame_info *frame;
353         unsigned int nframes;
354
355         if (iformat < 0)
356                 iformat = ARRAY_SIZE(uvc_formats) + iformat;
357         if (iformat < 0 || iformat >= (int)ARRAY_SIZE(uvc_formats))
358                 return;
359         format = &uvc_formats[iformat];
360
361         nframes = 0;
362         while (format->frames[nframes].width != 0)
363                 ++nframes;
364
365         if (iframe < 0)
366                 iframe = nframes + iframe;
367         if (iframe < 0 || iframe >= (int)nframes)
368                 return;
369         frame = &format->frames[iframe];
370
371         memset(ctrl, 0, sizeof *ctrl);
372
373         ctrl->bmHint = 1;
374         ctrl->bFormatIndex = iformat + 1;
375         ctrl->bFrameIndex = iframe + 1;
376         ctrl->dwFrameInterval = frame->intervals[0];
377         switch (format->fcc) {
378         case V4L2_PIX_FMT_YUYV:
379                 ctrl->dwMaxVideoFrameSize = frame->width * frame->height * 2;
380                 break;
381         case V4L2_PIX_FMT_MJPEG:
382                 ctrl->dwMaxVideoFrameSize = dev->imgsize;
383                 break;
384         }
385         ctrl->dwMaxPayloadTransferSize = 512;   /* TODO this should be filled by the driver. */
386         ctrl->bmFramingInfo = 3;
387         ctrl->bPreferedVersion = 1;
388         ctrl->bMaxVersion = 1;
389 }
390
391 static void
392 uvc_events_process_standard(struct uvc_device *dev, struct usb_ctrlrequest *ctrl,
393                             struct uvc_request_data *resp)
394 {
395         printf("standard request\n");
396         (void)dev;
397         (void)ctrl;
398         (void)resp;
399 }
400
401 static void
402 uvc_events_process_control(struct uvc_device *dev, uint8_t req, uint8_t cs,
403                            struct uvc_request_data *resp)
404 {
405         printf("control request (req %02x cs %02x)\n", req, cs);
406         (void)dev;
407         (void)resp;
408 }
409
410 static void
411 uvc_events_process_streaming(struct uvc_device *dev, uint8_t req, uint8_t cs,
412                              struct uvc_request_data *resp)
413 {
414         struct uvc_streaming_control *ctrl;
415
416         printf("streaming request (req %02x cs %02x)\n", req, cs);
417
418         if (cs != UVC_VS_PROBE_CONTROL && cs != UVC_VS_COMMIT_CONTROL)
419                 return;
420
421         ctrl = (struct uvc_streaming_control *)&resp->data;
422         resp->length = sizeof *ctrl;
423
424         switch (req) {
425         case UVC_SET_CUR:
426                 dev->control = cs;
427                 resp->length = 34;
428                 break;
429
430         case UVC_GET_CUR:
431                 if (cs == UVC_VS_PROBE_CONTROL)
432                         memcpy(ctrl, &dev->probe, sizeof *ctrl);
433                 else
434                         memcpy(ctrl, &dev->commit, sizeof *ctrl);
435                 break;
436
437         case UVC_GET_MIN:
438         case UVC_GET_MAX:
439         case UVC_GET_DEF:
440                 uvc_fill_streaming_control(dev, ctrl, req == UVC_GET_MAX ? -1 : 0,
441                                            req == UVC_GET_MAX ? -1 : 0);
442                 break;
443
444         case UVC_GET_RES:
445                 memset(ctrl, 0, sizeof *ctrl);
446                 break;
447
448         case UVC_GET_LEN:
449                 resp->data[0] = 0x00;
450                 resp->data[1] = 0x22;
451                 resp->length = 2;
452                 break;
453
454         case UVC_GET_INFO:
455                 resp->data[0] = 0x03;
456                 resp->length = 1;
457                 break;
458         }
459 }
460
461 static void
462 uvc_events_process_class(struct uvc_device *dev, struct usb_ctrlrequest *ctrl,
463                          struct uvc_request_data *resp)
464 {
465         if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE)
466                 return;
467
468         switch (ctrl->wIndex & 0xff) {
469         case UVC_INTF_CONTROL:
470                 uvc_events_process_control(dev, ctrl->bRequest, ctrl->wValue >> 8, resp);
471                 break;
472
473         case UVC_INTF_STREAMING:
474                 uvc_events_process_streaming(dev, ctrl->bRequest, ctrl->wValue >> 8, resp);
475                 break;
476
477         default:
478                 break;
479         }
480 }
481
482 static void
483 uvc_events_process_setup(struct uvc_device *dev, struct usb_ctrlrequest *ctrl,
484                          struct uvc_request_data *resp)
485 {
486         dev->control = 0;
487
488         printf("bRequestType %02x bRequest %02x wValue %04x wIndex %04x "
489                 "wLength %04x\n", ctrl->bRequestType, ctrl->bRequest,
490                 ctrl->wValue, ctrl->wIndex, ctrl->wLength);
491
492         switch (ctrl->bRequestType & USB_TYPE_MASK) {
493         case USB_TYPE_STANDARD:
494                 uvc_events_process_standard(dev, ctrl, resp);
495                 break;
496
497         case USB_TYPE_CLASS:
498                 uvc_events_process_class(dev, ctrl, resp);
499                 break;
500
501         default:
502                 break;
503         }
504 }
505
506 static void
507 uvc_events_process_data(struct uvc_device *dev, struct uvc_request_data *data)
508 {
509         struct uvc_streaming_control *target;
510         struct uvc_streaming_control *ctrl;
511         const struct uvc_format_info *format;
512         const struct uvc_frame_info *frame;
513         const unsigned int *interval;
514         unsigned int iformat, iframe;
515         unsigned int nframes;
516
517         switch (dev->control) {
518         case UVC_VS_PROBE_CONTROL:
519                 printf("setting probe control, length = %d\n", data->length);
520                 target = &dev->probe;
521                 break;
522
523         case UVC_VS_COMMIT_CONTROL:
524                 printf("setting commit control, length = %d\n", data->length);
525                 target = &dev->commit;
526                 break;
527
528         default:
529                 printf("setting unknown control, length = %d\n", data->length);
530                 return;
531         }
532
533         ctrl = (struct uvc_streaming_control *)&data->data;
534         iformat = clamp((unsigned int)ctrl->bFormatIndex, 1U,
535                         (unsigned int)ARRAY_SIZE(uvc_formats));
536         format = &uvc_formats[iformat-1];
537
538         nframes = 0;
539         while (format->frames[nframes].width != 0)
540                 ++nframes;
541
542         iframe = clamp((unsigned int)ctrl->bFrameIndex, 1U, nframes);
543         frame = &format->frames[iframe-1];
544         interval = frame->intervals;
545
546         while (interval[0] < ctrl->dwFrameInterval && interval[1])
547                 ++interval;
548
549         target->bFormatIndex = iformat;
550         target->bFrameIndex = iframe;
551         switch (format->fcc) {
552         case V4L2_PIX_FMT_YUYV:
553                 target->dwMaxVideoFrameSize = frame->width * frame->height * 2;
554                 break;
555         case V4L2_PIX_FMT_MJPEG:
556                 if (dev->imgsize == 0)
557                         printf("WARNING: MJPEG requested and no image loaded.\n");
558                 target->dwMaxVideoFrameSize = dev->imgsize;
559                 break;
560         }
561         target->dwFrameInterval = *interval;
562
563         if (dev->control == UVC_VS_COMMIT_CONTROL) {
564                 dev->fcc = format->fcc;
565                 dev->width = frame->width;
566                 dev->height = frame->height;
567
568                 uvc_video_set_format(dev);
569                 if (dev->bulk)
570                         uvc_video_stream(dev, 1);
571         }
572 }
573
574 static void
575 uvc_events_process(void *d)
576 {
577         struct uvc_device *dev = d;
578         struct v4l2_event v4l2_event;
579         struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
580         struct uvc_request_data resp;
581         int ret;
582
583         ret = ioctl(dev->fd, VIDIOC_DQEVENT, &v4l2_event);
584         if (ret < 0) {
585                 printf("VIDIOC_DQEVENT failed: %s (%d)\n", strerror(errno),
586                         errno);
587                 return;
588         }
589
590         memset(&resp, 0, sizeof resp);
591         resp.length = -EL2HLT;
592
593         switch (v4l2_event.type) {
594         case UVC_EVENT_CONNECT:
595         case UVC_EVENT_DISCONNECT:
596                 return;
597
598         case UVC_EVENT_SETUP:
599                 uvc_events_process_setup(dev, &uvc_event->req, &resp);
600                 break;
601
602         case UVC_EVENT_DATA:
603                 uvc_events_process_data(dev, &uvc_event->data);
604                 return;
605
606         case UVC_EVENT_STREAMON:
607                 uvc_video_reqbufs(dev, 4);
608                 uvc_video_stream(dev, 1);
609                 return;
610
611         case UVC_EVENT_STREAMOFF:
612                 uvc_video_stream(dev, 0);
613                 uvc_video_reqbufs(dev, 0);
614                 return;
615         }
616
617         ioctl(dev->fd, UVCIOC_SEND_RESPONSE, &resp);
618         if (ret < 0) {
619                 printf("UVCIOC_S_EVENT failed: %s (%d)\n", strerror(errno),
620                         errno);
621                 return;
622         }
623 }
624
625 static void
626 uvc_events_init(struct uvc_device *dev)
627 {
628         struct v4l2_event_subscription sub;
629
630         uvc_fill_streaming_control(dev, &dev->probe, 0, 0);
631         uvc_fill_streaming_control(dev, &dev->commit, 0, 0);
632
633         if (dev->bulk) {
634                 /* FIXME Crude hack, must be negotiated with the driver. */
635                 dev->probe.dwMaxPayloadTransferSize = 16 * 1024;
636                 dev->commit.dwMaxPayloadTransferSize = 16 * 1024;
637         }
638
639
640         memset(&sub, 0, sizeof sub);
641         sub.type = UVC_EVENT_SETUP;
642         ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
643         sub.type = UVC_EVENT_DATA;
644         ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
645         sub.type = UVC_EVENT_STREAMON;
646         ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
647         sub.type = UVC_EVENT_STREAMOFF;
648         ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
649 }
650
651 /* ---------------------------------------------------------------------------
652  * main
653  */
654
655 static void image_load(struct uvc_device *dev, const char *img)
656 {
657         int fd = -1;
658
659         if (img == NULL)
660                 return;
661
662         fd = open(img, O_RDONLY);
663         if (fd == -1) {
664                 printf("Unable to open MJPEG image '%s'\n", img);
665                 return;
666         }
667
668         dev->imgsize = lseek(fd, 0, SEEK_END);
669         lseek(fd, 0, SEEK_SET);
670         dev->imgdata = malloc(dev->imgsize);
671         if (dev->imgdata == NULL) {
672                 printf("Unable to allocate memory for MJPEG image\n");
673                 dev->imgsize = 0;
674                 return;
675         }
676
677         read(fd, dev->imgdata, dev->imgsize);
678         close(fd);
679 }
680
681 static void usage(const char *argv0)
682 {
683         fprintf(stderr, "Usage: %s [options]\n", argv0);
684         fprintf(stderr, "Available options are\n");
685         fprintf(stderr, " -b            Use bulk mode\n");
686         fprintf(stderr, " -d device     Video device\n");
687         fprintf(stderr, " -h            Print this help screen and exit\n");
688         fprintf(stderr, " -i image      MJPEG image\n");
689 }
690
691 /* Necesssary for and only used by signal handler. */
692 static struct uvc_device *uvc_device;
693
694 static void sigint_handler(int signal __attribute__((__unused__)))
695 {
696         /* Stop the main loop when the user presses CTRL-C */
697         events_stop(&uvc_device->events);
698 }
699
700 int main(int argc, char *argv[])
701 {
702         char *device = "/dev/video0";
703         struct uvc_device *dev;
704         int bulk_mode = 0;
705         char *mjpeg_image = NULL;
706         int opt;
707
708         while ((opt = getopt(argc, argv, "bd:hi:")) != -1) {
709                 switch (opt) {
710                 case 'b':
711                         bulk_mode = 1;
712                         break;
713
714                 case 'd':
715                         device = optarg;
716                         break;
717
718                 case 'h':
719                         usage(argv[0]);
720                         return 0;
721
722                 case 'i':
723                         mjpeg_image = optarg;
724                         break;
725
726                 default:
727                         fprintf(stderr, "Invalid option '-%c'\n", opt);
728                         usage(argv[0]);
729                         return 1;
730                 }
731         }
732
733         dev = uvc_open(device);
734         if (dev == NULL)
735                 return 1;
736
737         image_load(dev, mjpeg_image);
738
739         dev->bulk = bulk_mode;
740
741         uvc_events_init(dev);
742         uvc_video_init(dev);
743
744         /*
745          * Register a signal handler for SIGINT, received when the user presses
746          * CTRL-C. This will allow the main loop to be interrupted, and resources
747          * to be freed cleanly.
748          */
749         uvc_device = dev;
750         signal(SIGINT, sigint_handler);
751
752         events_watch_fd(&dev->events, dev->fd, EVENT_WRITE,
753                         uvc_video_process, dev);
754         events_watch_fd(&dev->events, dev->fd, EVENT_EXCEPTION,
755                         uvc_events_process, dev);
756
757         /* Main capture loop */
758         events_loop(&dev->events);
759
760         events_cleanup(&dev->events);
761         uvc_close(dev);
762         return 0;
763 }
764