update source for tizen_2.1
[sdk/emulator/qemu.git] / tizen / src / hw / maru_camera_linux_pci.c
1 /*
2  * Implementation of MARU Virtual Camera device by PCI bus on Linux.
3  *
4  * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact:
7  * JinHyung Jo <jinhyung.jo@samsung.com>
8  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23  * MA  02110-1301, USA.
24  *
25  * Contributors:
26  * - S-Core Co., Ltd
27  *
28  */
29
30 #include "qemu-common.h"
31 #include "maru_camera_common.h"
32 #include "pci.h"
33 #include "kvm.h"
34 #include "tizen/src/debug_ch.h"
35
36 #include <linux/videodev2.h>
37
38 #include <sys/stat.h>
39 #include <sys/ioctl.h>
40 #include <sys/mman.h>
41
42 #include <libv4l2.h>
43 #include <libv4lconvert.h>
44
45 MULTI_DEBUG_CHANNEL(tizen, camera_linux);
46
47 #define CLEAR(x) memset(&(x), 0, sizeof(x))
48
49 #define MARUCAM_DEFAULT_BUFFER_COUNT    4
50 #define MARUCAM_DUMMYFRAME_COUNT    2
51
52 #define MARUCAM_CTRL_VALUE_MAX      20
53 #define MARUCAM_CTRL_VALUE_MIN      1
54 #define MARUCAM_CTRL_VALUE_MID      10
55 #define MARUCAM_CTRL_VALUE_STEP     1
56
57 enum {
58     _MC_THREAD_PAUSED,
59     _MC_THREAD_STREAMON,
60     _MC_THREAD_STREAMOFF,
61 };
62
63 typedef struct marucam_framebuffer {
64     void *data;
65     size_t size;
66 } marucam_framebuffer;
67
68 static int n_framebuffer;
69 static struct marucam_framebuffer *framebuffer;
70
71 static const char *dev_name = "/dev/video0";
72 static int v4l2_fd;
73 static int convert_trial;
74 static int ready_count;
75 static int timeout_n;
76
77 static struct v4l2_format dst_fmt;
78
79 static void make_yu12_black(unsigned char *dest, uint32_t width, uint32_t height)
80 {
81     uint32_t x, y;
82     unsigned char *udest, *vdest;
83
84     /* Y */
85     for (y = 0; y < height; y++) {
86         for (x = 0; x < width; x++) {
87             *dest++ = 16;
88         }
89     }
90
91     /* U + V */
92     udest = dest;
93     vdest = dest + width * height / 4;
94
95     for (y = 0; y < height / 2; y++) {
96         for (x = 0; x < width / 2; x++) {
97             *udest++ = *vdest++ = 128;
98         }
99     }
100 }
101
102 static int yioctl(int fd, int req, void *arg)
103 {
104     int r;
105
106     do {
107         r = ioctl(fd, req, arg);
108     } while (r < 0 && errno == EINTR);
109
110     return r;
111 }
112
113 static int xioctl(int fd, int req, void *arg)
114 {
115     int r;
116
117     do {
118         r = v4l2_ioctl(fd, req, arg);
119     } while (r < 0 && errno == EINTR);
120
121     return r;
122 }
123
124 typedef struct tagMaruCamConvertPixfmt {
125     uint32_t fmt;   /* fourcc */
126 } MaruCamConvertPixfmt;
127
128 static MaruCamConvertPixfmt supported_dst_pixfmts[] = {
129         { V4L2_PIX_FMT_YUYV },
130         { V4L2_PIX_FMT_YUV420 },
131         { V4L2_PIX_FMT_YVU420 },
132 };
133
134 typedef struct tagMaruCamConvertFrameInfo {
135     uint32_t width;
136     uint32_t height;
137 } MaruCamConvertFrameInfo;
138
139 static MaruCamConvertFrameInfo supported_dst_frames[] = {
140         { 640, 480 },
141         { 352, 288 },
142         { 320, 240 },
143         { 176, 144 },
144         { 160, 120 },
145 };
146
147 struct marucam_qctrl {
148     uint32_t id;
149     uint32_t hit;
150     int32_t min;
151     int32_t max;
152     int32_t step;
153     int32_t init_val;
154 };
155
156 static struct marucam_qctrl qctrl_tbl[] = {
157     { V4L2_CID_BRIGHTNESS, 0, },
158     { V4L2_CID_CONTRAST, 0, },
159     { V4L2_CID_SATURATION, 0, },
160     { V4L2_CID_SHARPNESS, 0, },
161 };
162
163 static void marucam_reset_controls(void)
164 {
165     uint32_t i;
166     for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) {
167         if (qctrl_tbl[i].hit) {
168             struct v4l2_control ctrl = {0,};
169             qctrl_tbl[i].hit = 0;
170             ctrl.id = qctrl_tbl[i].id;
171             ctrl.value = qctrl_tbl[i].init_val;
172             if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
173                 ERR("Failed to reset control value: id(0x%x), errstr(%s)\n",
174                     ctrl.id, strerror(errno));
175             }
176         }
177     }
178 }
179
180 static int32_t value_convert_from_guest(int32_t min, int32_t max, int32_t value)
181 {
182     double rate = 0.0;
183     int32_t dist = 0, ret = 0;
184
185     dist = max - min;
186
187     if (dist < MARUCAM_CTRL_VALUE_MAX) {
188         rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
189         ret = min + (int32_t)(value / rate);
190     } else {
191         rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
192         ret = min + (int32_t)(rate * value);
193     }
194     return ret;
195 }
196
197 static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value)
198 {
199     double rate  = 0.0;
200     int32_t dist = 0, ret = 0;
201
202     dist = max - min;
203
204     if (dist < MARUCAM_CTRL_VALUE_MAX) {
205         rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
206         ret = (int32_t)((double)(value - min) * rate);
207     } else {
208         rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
209         ret = (int32_t)((double)(value - min) / rate);
210     }
211
212     return ret;
213 }
214
215 static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,
216                         uint32_t width, uint32_t height)
217 {
218     struct v4l2_frmivalenum fival;
219     struct v4l2_streamparm sp;
220     uint32_t min_num = 0, min_denom = 0;
221
222     CLEAR(fival);
223     fival.pixel_format = pixel_format;
224     fival.width = width;
225     fival.height = height;
226
227     if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) {
228         ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n",
229             pixel_format, width, height);
230         return;
231     }
232
233     if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
234         float max_ival = -1.0;
235         do {
236             float cur_ival = (float)fival.discrete.numerator
237                         / (float)fival.discrete.denominator;
238             if (cur_ival > max_ival) {
239                 max_ival = cur_ival;
240                 min_num = fival.discrete.numerator;
241                 min_denom = fival.discrete.denominator;
242             }
243             TRACE("Discrete frame interval %u/%u supported\n",
244                  fival.discrete.numerator, fival.discrete.denominator);
245             fival.index++;
246         } while (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0);
247     } else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) ||
248                 (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) {
249         TRACE("Frame intervals from %u/%u to %u/%u supported",
250             fival.stepwise.min.numerator, fival.stepwise.min.denominator,
251             fival.stepwise.max.numerator, fival.stepwise.max.denominator);
252         if (fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
253             TRACE("with %u/%u step", fival.stepwise.step.numerator,
254                   fival.stepwise.step.denominator);
255         }
256         if (((float)fival.stepwise.max.denominator /
257              (float)fival.stepwise.max.numerator) >
258             ((float)fival.stepwise.min.denominator /
259              (float)fival.stepwise.min.numerator)) {
260             min_num = fival.stepwise.max.numerator;
261             min_denom = fival.stepwise.max.denominator;
262         } else {
263             min_num = fival.stepwise.min.numerator;
264             min_denom = fival.stepwise.min.denominator;
265         }
266     }
267     TRACE("The actual min values: %u/%u\n", min_num, min_denom);
268
269     CLEAR(sp);
270     sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
271     sp.parm.capture.timeperframe.numerator = min_num;
272     sp.parm.capture.timeperframe.denominator = min_denom;
273
274     if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) {
275         ERR("Failed to set to minimum FPS(%u/%u)\n", min_num, min_denom);
276     }
277 }
278
279 static uint32_t stop_capturing(void)
280 {
281     enum v4l2_buf_type type;
282
283     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
284     if (xioctl(v4l2_fd, VIDIOC_STREAMOFF, &type) < 0) {
285         ERR("Failed to ioctl() with VIDIOC_STREAMOFF: %s\n", strerror(errno));
286         return errno;
287     }
288     return 0;
289 }
290
291 static uint32_t start_capturing(void)
292 {
293     enum v4l2_buf_type type;
294
295     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
296     if (xioctl(v4l2_fd, VIDIOC_STREAMON, &type) < 0) {
297         ERR("Failed to ioctl() with VIDIOC_STREAMON: %s\n", strerror(errno));
298         return errno;
299     }
300     return 0;
301 }
302
303 static void free_framebuffers(marucam_framebuffer *fb, int buf_num)
304 {
305     int i;
306
307     if (fb == NULL) {
308         ERR("The framebuffer is NULL. Failed to release the framebuffer\n");
309         return;
310     } else if (buf_num == 0) {
311         ERR("The buffer count is 0. Failed to release the framebuffer\n");
312         return;
313     } else {
314         TRACE("[%s]:fb(0x%p), buf_num(%d)\n", __func__, fb, buf_num);
315     }
316
317     /* Unmap framebuffers. */
318     for (i = 0; i < buf_num; i++) {
319         if (fb[i].data != NULL) {
320             v4l2_munmap(fb[i].data, fb[i].size);
321             fb[i].data = NULL;
322             fb[i].size = 0;
323         } else {
324             ERR("framebuffer[%d].data is NULL.\n", i);
325         }
326     }
327 }
328
329 static uint32_t
330 mmap_framebuffers(marucam_framebuffer **fb, int *buf_num)
331 {
332     struct v4l2_requestbuffers req;
333
334     CLEAR(req);
335     req.count   = MARUCAM_DEFAULT_BUFFER_COUNT;
336     req.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
337     req.memory  = V4L2_MEMORY_MMAP;
338     if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) {
339         if (errno == EINVAL) {
340             ERR("%s does not support memory mapping: %s\n",
341                 dev_name, strerror(errno));
342         } else {
343             ERR("Failed to request bufs: %s\n", strerror(errno));
344         }
345         return errno;
346     }
347     if (req.count == 0) {
348         ERR("Insufficient buffer memory on %s\n", dev_name);
349         return EINVAL;
350     }
351
352     *fb = g_new0(marucam_framebuffer, req.count);
353     if (*fb == NULL) {
354         ERR("Not enough memory to allocate framebuffers\n");
355         return ENOMEM;
356     }
357
358     for (*buf_num = 0; *buf_num < req.count; ++*buf_num) {
359         struct v4l2_buffer buf;
360         CLEAR(buf);
361         buf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
362         buf.memory  = V4L2_MEMORY_MMAP;
363         buf.index   = *buf_num;
364         if (xioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf) < 0) {
365             ERR("Failed to ioctl() with VIDIOC_QUERYBUF: %s\n",
366                 strerror(errno));
367             return errno;
368         }
369
370         (*fb)[*buf_num].size = buf.length;
371         (*fb)[*buf_num].data = v4l2_mmap(NULL,
372                      buf.length,
373                      PROT_READ | PROT_WRITE,
374                      MAP_SHARED,
375                      v4l2_fd, buf.m.offset);
376         if (MAP_FAILED == (*fb)[*buf_num].data) {
377             ERR("Failed to mmap: %s\n", strerror(errno));
378             return errno;
379         }
380
381         /* Queue the mapped buffer. */
382         CLEAR(buf);
383         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
384         buf.memory = V4L2_MEMORY_MMAP;
385         buf.index = *buf_num;
386         if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {
387             ERR("Failed to ioctl() with VIDIOC_QBUF: %s\n", strerror(errno));
388             return errno;
389         }
390     }
391     return 0;
392 }
393
394 static int is_streamon(MaruCamState *state)
395 {
396     int st;
397     qemu_mutex_lock(&state->thread_mutex);
398     st = state->streamon;
399     qemu_mutex_unlock(&state->thread_mutex);
400     return (st == _MC_THREAD_STREAMON);
401 }
402
403 static int is_stream_paused(MaruCamState *state)
404 {
405     int st;
406     qemu_mutex_lock(&state->thread_mutex);
407     st = state->streamon;
408     qemu_mutex_unlock(&state->thread_mutex);
409     return (st == _MC_THREAD_PAUSED);
410 }
411
412 /* sends a frame, YU12/black color  */
413 static void __raise_empty_intr(MaruCamState *state)
414 {
415     void *buf = NULL;
416     qemu_mutex_lock(&state->thread_mutex);
417     if (state->streamon == _MC_THREAD_STREAMON && state->req_frame) {
418         buf = state->vaddr + state->buf_size * (state->req_frame - 1);
419         make_yu12_black(buf, dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height);
420         state->req_frame = 0; /* clear request */
421         state->isr = 0x01;   /* set a flag of raising a interrupt */
422         qemu_bh_schedule(state->tx_bh);
423     }
424     qemu_mutex_unlock(&state->thread_mutex);
425 }
426
427 static void __raise_err_intr(MaruCamState *state)
428 {
429     qemu_mutex_lock(&state->thread_mutex);
430     if (state->streamon == _MC_THREAD_STREAMON) {
431         state->req_frame = 0; /* clear request */
432         state->isr = 0x08;   /* set a error flag of raising a interrupt */
433         qemu_bh_schedule(state->tx_bh);
434     }
435     qemu_mutex_unlock(&state->thread_mutex);
436 }
437
438 static void
439 notify_buffer_ready(MaruCamState *state, void *ptr, size_t size)
440 {
441     void *buf = NULL;
442
443     qemu_mutex_lock(&state->thread_mutex);
444     if (state->streamon == _MC_THREAD_STREAMON) {
445         if (ready_count < MARUCAM_SKIPFRAMES) {
446             /* skip a frame cause first some frame are distorted */
447             ++ready_count;
448             TRACE("Skip %d frame\n", ready_count);
449             qemu_mutex_unlock(&state->thread_mutex);
450             return;
451         }
452         if (state->req_frame == 0) {
453             TRACE("There is no request\n");
454             qemu_mutex_unlock(&state->thread_mutex);
455             return;
456         }
457         buf = state->vaddr + state->buf_size * (state->req_frame - 1);
458         memcpy(buf, ptr, state->buf_size);
459         state->req_frame = 0; /* clear request */
460         state->isr |= 0x01;   /* set a flag of rasing a interrupt */
461         qemu_bh_schedule(state->tx_bh);
462     }
463     qemu_mutex_unlock(&state->thread_mutex);
464 }
465
466 static int read_frame(MaruCamState *state)
467 {
468     struct v4l2_buffer buf;
469
470     CLEAR(buf);
471     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
472     buf.memory = V4L2_MEMORY_MMAP;
473     if (xioctl(v4l2_fd, VIDIOC_DQBUF, &buf) < 0) {
474         switch (errno) {
475         case EAGAIN:
476         case EINTR:
477             ERR("DQBUF error, try again: %s\n", strerror(errno));
478             return 0;
479         case EIO:
480             ERR("The v4l2_read() met the EIO\n");
481             if (convert_trial-- == -1) {
482                 ERR("Try count for v4l2_read is exceeded: %s\n",
483                     strerror(errno));
484                 return -1;
485             }
486             return 0;
487         default:
488             ERR("DQBUF error: %s\n", strerror(errno));
489             return -1;
490         }
491     }
492
493     notify_buffer_ready(state, framebuffer[buf.index].data, buf.bytesused);
494
495     if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {
496         ERR("QBUF error: %s\n", strerror(errno));
497         return -1;
498     }
499     return 0;
500 }
501
502 static int __v4l2_streaming(MaruCamState *state)
503 {
504     fd_set fds;
505     struct timeval tv;
506     int ret;
507
508     FD_ZERO(&fds);
509     FD_SET(v4l2_fd, &fds);
510
511     tv.tv_sec = 1;
512     tv.tv_usec = 0;
513
514     ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv);
515     if (ret < 0) {
516         if (errno == EAGAIN || errno == EINTR) {
517             ERR("Select again: %s\n", strerror(errno));
518             return 0;
519         }
520         ERR("Failed to select: %s\n", strerror(errno));
521         __raise_err_intr(state);
522         return -1;
523     } else if (!ret) {
524         timeout_n++;
525         ERR("Select timed out: count(%u)\n", timeout_n);
526         if (ready_count == 0) {
527             if (timeout_n <= MARUCAM_DUMMYFRAME_COUNT) {
528                 ERR("Sends dummy data to initialize the camera\n");
529                 __raise_empty_intr(state);
530                 return 0;
531             } else {
532                 ERR("Webcam is busy, failed to a read frame."
533                     " Raises an error\n");
534                 __raise_err_intr(state);
535                 return -1;
536             }
537         }
538         if (timeout_n >= 5) {
539             ERR("Webcam is busy, failed to a read frame. Raises an error\n");
540             __raise_err_intr(state);
541             return -1;
542         }
543         return 0;
544     }
545
546     if (!v4l2_fd || (v4l2_fd == -1)) {
547         ERR("The file descriptor is closed or not opened\n");
548         __raise_err_intr(state);
549         return -1;
550     }
551
552     ret = read_frame(state);
553     if (ret < 0) {
554         ERR("Failed to operate the read_frame()\n");
555         __raise_err_intr(state);
556         return -1;
557     }
558
559     /* clear the skip count for select time-out */
560     if (timeout_n > 0) {
561         timeout_n = 0;
562     }
563
564     return 0;
565 }
566
567 /* Worker thread */
568 static void *marucam_worker_thread(void *thread_param)
569 {
570     MaruCamState *state = (MaruCamState *)thread_param;
571
572     while (1) {
573         qemu_mutex_lock(&state->thread_mutex);
574         state->streamon = _MC_THREAD_PAUSED;
575         qemu_cond_wait(&state->thread_cond, &state->thread_mutex);
576         qemu_mutex_unlock(&state->thread_mutex);
577
578         if (state->destroying) {
579             break;
580         }
581
582         convert_trial = 10;
583         ready_count = 0;
584         timeout_n = 0;
585         qemu_mutex_lock(&state->thread_mutex);
586         state->streamon = _MC_THREAD_STREAMON;
587         qemu_mutex_unlock(&state->thread_mutex);
588         INFO("Streaming on ......\n");
589
590         while (1) {
591             if (is_streamon(state)) {
592                 if (__v4l2_streaming(state) < 0) {
593                     INFO("...... Streaming off\n");
594                     break;
595                 }
596             } else {
597                 INFO("...... Streaming off\n");
598                 break;
599             }
600         }
601     }
602
603     return NULL;
604 }
605
606 int marucam_device_check(int log_flag)
607 {
608     int tmp_fd;
609     struct timeval t1, t2;
610     struct stat st;
611     struct v4l2_fmtdesc format;
612     struct v4l2_frmsizeenum size;
613     struct v4l2_capability cap;
614     int ret = 0;
615
616     gettimeofday(&t1, NULL);
617     if (stat(dev_name, &st) < 0) {
618         fprintf(stdout, "[Webcam] <WARNING> Cannot identify '%s': %s\n",
619                 dev_name, strerror(errno));
620     } else {
621         if (!S_ISCHR(st.st_mode)) {
622             fprintf(stdout, "[Webcam] <WARNING>%s is no character device\n",
623                     dev_name);
624         }
625     }
626
627     tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);
628     if (tmp_fd < 0) {
629         fprintf(stdout, "[Webcam] Camera device open failed: %s\n", dev_name);
630         gettimeofday(&t2, NULL);
631         fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",
632                 t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
633         return ret;
634     }
635     if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) {
636         fprintf(stdout, "[Webcam] Could not qeury video capabilities\n");
637         close(tmp_fd);
638         gettimeofday(&t2, NULL);
639         fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",
640                 t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
641         return ret;
642     }
643     if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||
644             !(cap.capabilities & V4L2_CAP_STREAMING)) {
645         fprintf(stdout, "[Webcam] Not supported video driver\n");
646         close(tmp_fd);
647         gettimeofday(&t2, NULL);
648         fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",
649                 t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
650         return ret;
651     }
652     ret = 1;
653
654     if (log_flag) {
655         fprintf(stdout, "[Webcam] Driver: %s\n", cap.driver);
656         fprintf(stdout, "[Webcam] Card:  %s\n", cap.card);
657         fprintf(stdout, "[Webcam] Bus info: %s\n", cap.bus_info);
658
659         CLEAR(format);
660         format.index = 0;
661         format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
662
663         if (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) < 0) {
664             close(tmp_fd);
665             gettimeofday(&t2, NULL);
666             fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",
667                     t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
668             return ret;
669         }
670
671         do {
672             CLEAR(size);
673             size.index = 0;
674             size.pixel_format = format.pixelformat;
675
676             fprintf(stdout, "[Webcam] PixelFormat: %c%c%c%c\n",
677                              (char)(format.pixelformat),
678                              (char)(format.pixelformat >> 8),
679                              (char)(format.pixelformat >> 16),
680                              (char)(format.pixelformat >> 24));
681
682             if (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0) {
683                 close(tmp_fd);
684                 gettimeofday(&t2, NULL);
685                 fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",
686                         t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
687                 return ret;
688             }
689
690             if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
691                 do {
692                     fprintf(stdout, "[Webcam] got discrete frame size %dx%d\n",
693                                     size.discrete.width, size.discrete.height);
694                     size.index++;
695                 } while (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
696             } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
697                 fprintf(stdout, "[Webcam] we have stepwise frame sizes:\n");
698                 fprintf(stdout, "[Webcam] min width: %d, min height: %d\n",
699                         size.stepwise.min_width, size.stepwise.min_height);
700                 fprintf(stdout, "[Webcam] max width: %d, max height: %d\n",
701                         size.stepwise.max_width, size.stepwise.max_height);
702                 fprintf(stdout, "[Webcam] step width: %d, step height: %d\n",
703                         size.stepwise.step_width, size.stepwise.step_height);
704             } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
705                 fprintf(stdout, "[Webcam] we have continuous frame sizes:\n");
706                 fprintf(stdout, "[Webcam] min width: %d, min height: %d\n",
707                         size.stepwise.min_width, size.stepwise.min_height);
708                 fprintf(stdout, "[Webcam] max width: %d, max height: %d\n",
709                         size.stepwise.max_width, size.stepwise.max_height);
710
711             }
712             format.index++;
713         } while (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) >= 0);
714     }
715
716     close(tmp_fd);
717     gettimeofday(&t2, NULL);
718     fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",
719                     t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
720     return ret;
721 }
722
723 void marucam_device_init(MaruCamState *state)
724 {
725     state->destroying = false;
726     qemu_thread_create(&state->thread_id, marucam_worker_thread, (void *)state,
727             QEMU_THREAD_JOINABLE);
728 }
729
730 void marucam_device_exit(MaruCamState *state)
731 {
732     state->destroying = true;
733     qemu_mutex_lock(&state->thread_mutex);
734     qemu_cond_signal(&state->thread_cond);
735     qemu_mutex_unlock(&state->thread_mutex);
736     qemu_thread_join(&state->thread_id);
737 }
738
739 void marucam_device_open(MaruCamState *state)
740 {
741     MaruCamParam *param = state->param;
742
743     param->top = 0;
744     v4l2_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
745     if (v4l2_fd < 0) {
746         ERR("The v4l2 device open failed: %s\n", dev_name);
747         param->errCode = EINVAL;
748         return;
749     }
750     INFO("Opened\n");
751
752     /* FIXME : Do not use fixed values */
753     CLEAR(dst_fmt);
754     dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
755     dst_fmt.fmt.pix.width = 640;
756     dst_fmt.fmt.pix.height = 480;
757     dst_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
758     dst_fmt.fmt.pix.field = V4L2_FIELD_ANY;
759
760     if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) {
761         ERR("Failed to set video format: format(0x%x), width:height(%d:%d), "
762           "errstr(%s)\n", dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.width,
763           dst_fmt.fmt.pix.height, strerror(errno));
764         param->errCode = errno;
765         return;
766     }
767     TRACE("Set the default format: w:h(%dx%d), fmt(0x%x), size(%d), "
768          "color(%d), field(%d)\n",
769          dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height,
770          dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage,
771          dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field);
772 }
773
774 void marucam_device_start_preview(MaruCamState *state)
775 {
776     struct timespec req;
777     MaruCamParam *param = state->param;
778     param->top = 0;
779     req.tv_sec = 0;
780     req.tv_nsec = 10000000;
781
782     INFO("Pixfmt(%c%c%c%C), W:H(%d:%d), buf size(%u)\n",
783          (char)(dst_fmt.fmt.pix.pixelformat),
784          (char)(dst_fmt.fmt.pix.pixelformat >> 8),
785          (char)(dst_fmt.fmt.pix.pixelformat >> 16),
786          (char)(dst_fmt.fmt.pix.pixelformat >> 24),
787          dst_fmt.fmt.pix.width,
788          dst_fmt.fmt.pix.height,
789          dst_fmt.fmt.pix.sizeimage);
790
791     param->errCode = mmap_framebuffers(&framebuffer, &n_framebuffer);
792     if (param->errCode) {
793         ERR("Failed to mmap framebuffers\n");
794         if (framebuffer != NULL) {
795             free_framebuffers(framebuffer, n_framebuffer);
796             g_free(framebuffer);
797             framebuffer = NULL;
798             n_framebuffer = 0;
799         }
800         return;
801     }
802
803     param->errCode = start_capturing();
804     if (param->errCode) {
805         if (framebuffer != NULL) {
806             free_framebuffers(framebuffer, n_framebuffer);
807             g_free(framebuffer);
808             framebuffer = NULL;
809             n_framebuffer = 0;
810         }
811         return;
812     }
813
814     INFO("Starting preview\n");
815     state->buf_size = dst_fmt.fmt.pix.sizeimage;
816     qemu_mutex_lock(&state->thread_mutex);
817     qemu_cond_signal(&state->thread_cond);
818     qemu_mutex_unlock(&state->thread_mutex);
819
820     /* nanosleep until thread is streamon  */
821     while (!is_streamon(state)) {
822         nanosleep(&req, NULL);
823     }
824 }
825
826 void marucam_device_stop_preview(MaruCamState *state)
827 {
828     struct timespec req;
829     struct v4l2_requestbuffers reqbuf;
830     MaruCamParam *param = state->param;
831     param->top = 0;
832     req.tv_sec = 0;
833     req.tv_nsec = 50000000;
834
835     if (is_streamon(state)) {
836         qemu_mutex_lock(&state->thread_mutex);
837         state->streamon = _MC_THREAD_STREAMOFF;
838         qemu_mutex_unlock(&state->thread_mutex);
839
840         /* nanosleep until thread is paused  */
841         while (!is_stream_paused(state)) {
842             nanosleep(&req, NULL);
843         }
844     }
845
846     param->errCode = stop_capturing();
847     if (framebuffer != NULL) {
848         free_framebuffers(framebuffer, n_framebuffer);
849         g_free(framebuffer);
850         framebuffer = NULL;
851         n_framebuffer = 0;
852     }
853     state->buf_size = 0;
854
855     reqbuf.count = 0;
856     reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
857     reqbuf.memory = V4L2_MEMORY_MMAP;
858     if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
859         ERR("Failed to ioctl() with VIDIOC_REQBUF in stop_preview: %s\n",
860             strerror(errno));
861     }
862     INFO("Stopping preview\n");
863 }
864
865 void marucam_device_s_param(MaruCamState *state)
866 {
867     MaruCamParam *param = state->param;
868
869     param->top = 0;
870
871     /* If KVM enabled, We use default FPS of the webcam.
872      * If KVM disabled, we use mininum FPS of the webcam */
873     if (!kvm_enabled()) {
874         set_maxframeinterval(state, dst_fmt.fmt.pix.pixelformat,
875                      dst_fmt.fmt.pix.width,
876                      dst_fmt.fmt.pix.height);
877     }
878 }
879
880 void marucam_device_g_param(MaruCamState *state)
881 {
882     MaruCamParam *param = state->param;
883
884     /* We use default FPS of the webcam
885      * return a fixed value on guest ini file (1/30).
886      */
887     param->top = 0;
888     param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */
889     param->stack[1] = 1; /* numerator */
890     param->stack[2] = 30; /* denominator */
891 }
892
893 void marucam_device_s_fmt(MaruCamState *state)
894 {
895     struct v4l2_format format;
896     MaruCamParam *param = state->param;
897
898     param->top = 0;
899     CLEAR(format);
900     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
901     format.fmt.pix.width = param->stack[0];
902     format.fmt.pix.height = param->stack[1];
903     format.fmt.pix.pixelformat = param->stack[2];
904     format.fmt.pix.field = V4L2_FIELD_ANY;
905
906     if (xioctl(v4l2_fd, VIDIOC_S_FMT, &format) < 0) {
907         ERR("Failed to set video format: format(0x%x), width:height(%d:%d), "
908           "errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width,
909           format.fmt.pix.height, strerror(errno));
910         param->errCode = errno;
911         return;
912     }
913
914     memcpy(&dst_fmt, &format, sizeof(format));
915     param->stack[0] = dst_fmt.fmt.pix.width;
916     param->stack[1] = dst_fmt.fmt.pix.height;
917     param->stack[2] = dst_fmt.fmt.pix.field;
918     param->stack[3] = dst_fmt.fmt.pix.pixelformat;
919     param->stack[4] = dst_fmt.fmt.pix.bytesperline;
920     param->stack[5] = dst_fmt.fmt.pix.sizeimage;
921     param->stack[6] = dst_fmt.fmt.pix.colorspace;
922     param->stack[7] = dst_fmt.fmt.pix.priv;
923     TRACE("Set the format: w:h(%dx%d), fmt(0x%x), size(%d), "
924          "color(%d), field(%d)\n",
925          dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height,
926          dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage,
927          dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field);
928 }
929
930 void marucam_device_g_fmt(MaruCamState *state)
931 {
932     struct v4l2_format format;
933     MaruCamParam *param = state->param;
934
935     param->top = 0;
936     CLEAR(format);
937     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
938
939     if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) {
940         ERR("Failed to get video format: %s\n", strerror(errno));
941         param->errCode = errno;
942     } else {
943         param->stack[0] = format.fmt.pix.width;
944         param->stack[1] = format.fmt.pix.height;
945         param->stack[2] = format.fmt.pix.field;
946         param->stack[3] = format.fmt.pix.pixelformat;
947         param->stack[4] = format.fmt.pix.bytesperline;
948         param->stack[5] = format.fmt.pix.sizeimage;
949         param->stack[6] = format.fmt.pix.colorspace;
950         param->stack[7] = format.fmt.pix.priv;
951         TRACE("Get the format: w:h(%dx%d), fmt(0x%x), size(%d), "
952              "color(%d), field(%d)\n",
953              format.fmt.pix.width, format.fmt.pix.height,
954              format.fmt.pix.pixelformat, format.fmt.pix.sizeimage,
955              format.fmt.pix.colorspace, format.fmt.pix.field);
956     }
957 }
958
959 void marucam_device_try_fmt(MaruCamState *state)
960 {
961     struct v4l2_format format;
962     MaruCamParam *param = state->param;
963
964     param->top = 0;
965     CLEAR(format);
966     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
967     format.fmt.pix.width = param->stack[0];
968     format.fmt.pix.height = param->stack[1];
969     format.fmt.pix.pixelformat = param->stack[2];
970     format.fmt.pix.field = V4L2_FIELD_ANY;
971
972     if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) {
973         ERR("Failed to check video format: format(0x%x), width:height(%d:%d),"
974             " errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width,
975             format.fmt.pix.height, strerror(errno));
976         param->errCode = errno;
977         return;
978     }
979     param->stack[0] = format.fmt.pix.width;
980     param->stack[1] = format.fmt.pix.height;
981     param->stack[2] = format.fmt.pix.field;
982     param->stack[3] = format.fmt.pix.pixelformat;
983     param->stack[4] = format.fmt.pix.bytesperline;
984     param->stack[5] = format.fmt.pix.sizeimage;
985     param->stack[6] = format.fmt.pix.colorspace;
986     param->stack[7] = format.fmt.pix.priv;
987     TRACE("Check the format: w:h(%dx%d), fmt(0x%x), size(%d), "
988          "color(%d), field(%d)\n",
989          format.fmt.pix.width, format.fmt.pix.height,
990          format.fmt.pix.pixelformat, format.fmt.pix.sizeimage,
991          format.fmt.pix.colorspace, format.fmt.pix.field);
992 }
993
994 void marucam_device_enum_fmt(MaruCamState *state)
995 {
996     uint32_t index;
997     MaruCamParam *param = state->param;
998
999     param->top = 0;
1000     index = param->stack[0];
1001
1002     if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
1003         param->errCode = EINVAL;
1004         return;
1005     }
1006     param->stack[1] = 0; /* flags = NONE */
1007     param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */
1008     /* set description */
1009     switch (supported_dst_pixfmts[index].fmt) {
1010     case V4L2_PIX_FMT_YUYV:
1011         memcpy(&param->stack[3], "YUYV", 32);
1012         break;
1013     case V4L2_PIX_FMT_YUV420:
1014         memcpy(&param->stack[3], "YU12", 32);
1015         break;
1016     case V4L2_PIX_FMT_YVU420:
1017         memcpy(&param->stack[3], "YV12", 32);
1018         break;
1019     default:
1020         ERR("Invalid fixel format\n");
1021         param->errCode = EINVAL;
1022         break;
1023     }
1024 }
1025
1026 void marucam_device_qctrl(MaruCamState *state)
1027 {
1028     uint32_t i;
1029     char name[32] = {0,};
1030     struct v4l2_queryctrl ctrl;
1031     MaruCamParam *param = state->param;
1032
1033     param->top = 0;
1034     CLEAR(ctrl);
1035     ctrl.id = param->stack[0];
1036
1037     switch (ctrl.id) {
1038     case V4L2_CID_BRIGHTNESS:
1039         TRACE("Query : BRIGHTNESS\n");
1040         memcpy((void *)name, (void *)"brightness", 32);
1041         i = 0;
1042         break;
1043     case V4L2_CID_CONTRAST:
1044         TRACE("Query : CONTRAST\n");
1045         memcpy((void *)name, (void *)"contrast", 32);
1046         i = 1;
1047         break;
1048     case V4L2_CID_SATURATION:
1049         TRACE("Query : SATURATION\n");
1050         memcpy((void *)name, (void *)"saturation", 32);
1051         i = 2;
1052         break;
1053     case V4L2_CID_SHARPNESS:
1054         TRACE("Query : SHARPNESS\n");
1055         memcpy((void *)name, (void *)"sharpness", 32);
1056         i = 3;
1057         break;
1058     default:
1059         ERR("Invalid control ID\n");
1060         param->errCode = EINVAL;
1061         return;
1062     }
1063
1064     if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) {
1065         if (errno != EINVAL) {
1066             ERR("Failed to query video controls: %s\n", strerror(errno));
1067         }
1068         param->errCode = errno;
1069         return;
1070     } else {
1071         struct v4l2_control sctrl;
1072         CLEAR(sctrl);
1073         sctrl.id = ctrl.id;
1074         if ((ctrl.maximum + ctrl.minimum) == 0) {
1075             sctrl.value = 0;
1076         } else {
1077             sctrl.value = (ctrl.maximum + ctrl.minimum) / 2;
1078         }
1079         if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) {
1080             ERR("Failed to set control value: id(0x%x), value(%d), "
1081                 "errstr(%s)\n", sctrl.id, sctrl.value, strerror(errno));
1082             param->errCode = errno;
1083             return;
1084         }
1085         qctrl_tbl[i].hit = 1;
1086         qctrl_tbl[i].min = ctrl.minimum;
1087         qctrl_tbl[i].max = ctrl.maximum;
1088         qctrl_tbl[i].step = ctrl.step;
1089         qctrl_tbl[i].init_val = ctrl.default_value;
1090     }
1091
1092     /* set fixed values by FW configuration file */
1093     param->stack[0] = ctrl.id;
1094     param->stack[1] = MARUCAM_CTRL_VALUE_MIN;    /* minimum */
1095     param->stack[2] = MARUCAM_CTRL_VALUE_MAX;    /* maximum */
1096     param->stack[3] = MARUCAM_CTRL_VALUE_STEP;   /* step */
1097     param->stack[4] = MARUCAM_CTRL_VALUE_MID;    /* default_value */
1098     param->stack[5] = ctrl.flags;
1099     /* name field setting */
1100     memcpy(&param->stack[6], (void *)name, sizeof(ctrl.name));
1101 }
1102
1103 void marucam_device_s_ctrl(MaruCamState *state)
1104 {
1105     uint32_t i;
1106     struct v4l2_control ctrl;
1107     MaruCamParam *param = state->param;
1108
1109     param->top = 0;
1110     CLEAR(ctrl);
1111     ctrl.id = param->stack[0];
1112
1113     switch (ctrl.id) {
1114     case V4L2_CID_BRIGHTNESS:
1115         i = 0;
1116         TRACE("%d is set to the value of the BRIGHTNESS\n", param->stack[1]);
1117         break;
1118     case V4L2_CID_CONTRAST:
1119         i = 1;
1120         TRACE("%d is set to the value of the CONTRAST\n", param->stack[1]);
1121         break;
1122     case V4L2_CID_SATURATION:
1123         i = 2;
1124         TRACE("%d is set to the value of the SATURATION\n", param->stack[1]);
1125         break;
1126     case V4L2_CID_SHARPNESS:
1127         i = 3;
1128         TRACE("%d is set to the value of the SHARPNESS\n", param->stack[1]);
1129         break;
1130     default:
1131         ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);
1132         param->errCode = EINVAL;
1133         return;
1134     }
1135
1136     ctrl.value = value_convert_from_guest(qctrl_tbl[i].min,
1137             qctrl_tbl[i].max, param->stack[1]);
1138     if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
1139         ERR("Failed to set control value: id(0x%x), value(r:%d, c:%d), "
1140             "errstr(%s)\n", ctrl.id, param->stack[1], ctrl.value,
1141             strerror(errno));
1142         param->errCode = errno;
1143         return;
1144     }
1145 }
1146
1147 void marucam_device_g_ctrl(MaruCamState *state)
1148 {
1149     uint32_t i;
1150     struct v4l2_control ctrl;
1151     MaruCamParam *param = state->param;
1152
1153     param->top = 0;
1154     CLEAR(ctrl);
1155     ctrl.id = param->stack[0];
1156
1157     switch (ctrl.id) {
1158     case V4L2_CID_BRIGHTNESS:
1159         TRACE("Gets the value of the BRIGHTNESS\n");
1160         i = 0;
1161         break;
1162     case V4L2_CID_CONTRAST:
1163         TRACE("Gets the value of the CONTRAST\n");
1164         i = 1;
1165         break;
1166     case V4L2_CID_SATURATION:
1167         TRACE("Gets the value of the SATURATION\n");
1168         i = 2;
1169         break;
1170     case V4L2_CID_SHARPNESS:
1171         TRACE("Gets the value of the SHARPNESS\n");
1172         i = 3;
1173         break;
1174     default:
1175         ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);
1176         param->errCode = EINVAL;
1177         return;
1178     }
1179
1180     if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &ctrl) < 0) {
1181         ERR("Failed to get video control value: %s\n", strerror(errno));
1182         param->errCode = errno;
1183         return;
1184     }
1185     param->stack[0] = value_convert_to_guest(qctrl_tbl[i].min,
1186             qctrl_tbl[i].max, ctrl.value);
1187     TRACE("Value: %d\n", param->stack[0]);
1188 }
1189
1190 void marucam_device_enum_fsizes(MaruCamState *state)
1191 {
1192     uint32_t index, pixfmt, i;
1193     MaruCamParam *param = state->param;
1194
1195     param->top = 0;
1196     index = param->stack[0];
1197     pixfmt = param->stack[1];
1198
1199     if (index >= ARRAY_SIZE(supported_dst_frames)) {
1200         param->errCode = EINVAL;
1201         return;
1202     }
1203     for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
1204         if (supported_dst_pixfmts[i].fmt == pixfmt) {
1205             break;
1206         }
1207     }
1208
1209     if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
1210         param->errCode = EINVAL;
1211         return;
1212     }
1213
1214     param->stack[0] = supported_dst_frames[index].width;
1215     param->stack[1] = supported_dst_frames[index].height;
1216 }
1217
1218 void marucam_device_enum_fintv(MaruCamState *state)
1219 {
1220     MaruCamParam *param = state->param;
1221
1222     param->top = 0;
1223
1224     /* switch by index(param->stack[0]) */
1225     switch (param->stack[0]) {
1226     case 0:
1227         /* we only use 1/30 frame interval */
1228         param->stack[1] = 30;   /* denominator */
1229         break;
1230     default:
1231         param->errCode = EINVAL;
1232         return;
1233     }
1234     param->stack[0] = 1;    /* numerator */
1235 }
1236
1237 void marucam_device_close(MaruCamState *state)
1238 {
1239     if (!is_stream_paused(state)) {
1240         marucam_device_stop_preview(state);
1241     }
1242
1243     marucam_reset_controls();
1244
1245     v4l2_close(v4l2_fd);
1246     v4l2_fd = 0;
1247     INFO("Closed\n");
1248 }