2 * Virtual Camera device(PCI) for Linux host.
4 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
7 * JinHyung Jo <jinhyung.jo@samsung.com>
8 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
9 * DongKyun Yun <dk77.yun@samsung.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 #include "qemu-common.h"
31 #include "qemu-common.h"
35 #include "tizen/src/debug_ch.h"
37 #include <linux/videodev2.h>
40 #include <libv4lconvert.h>
42 MULTI_DEBUG_CHANNEL(tizen, camera_linux);
45 static int convert_trial;
47 static struct v4l2_format dst_fmt;
49 static int xioctl(int fd, int req, void *arg)
54 r = v4l2_ioctl(fd, req, arg);
55 } while ( r < 0 && errno == EINTR);
60 #define SVCAM_CTRL_VALUE_MAX 20
61 #define SVCAM_CTRL_VALUE_MIN 1
62 #define SVCAM_CTRL_VALUE_MID 10
63 #define SVCAM_CTRL_VALUE_STEP 1
74 static struct svcam_qctrl qctrl_tbl[] = {
75 { V4L2_CID_BRIGHTNESS, 0, },
76 { V4L2_CID_CONTRAST, 0, },
77 { V4L2_CID_SATURATION,0, },
78 { V4L2_CID_SHARPNESS, 0, },
81 static void svcam_reset_controls(void)
84 for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) {
85 if (qctrl_tbl[i].hit) {
86 struct v4l2_control ctrl = {0,};
87 ctrl.id = qctrl_tbl[i].id;
88 ctrl.value = qctrl_tbl[i].init_val;
89 if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
90 ERR("failed to set video control value while reset values : %s\n", strerror(errno));
96 static int32_t value_convert_from_guest(int32_t min, int32_t max, int32_t value)
99 int32_t dist = 0, ret = 0;
103 if (dist < SVCAM_CTRL_VALUE_MAX) {
104 rate = (double)SVCAM_CTRL_VALUE_MAX / (double)dist;
105 ret = min + (int32_t)(value / rate);
107 rate = (double)dist / (double)SVCAM_CTRL_VALUE_MAX;
108 ret = min + (int32_t)(rate * value);
113 static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value)
116 int32_t dist = 0, ret = 0;
120 if (dist < SVCAM_CTRL_VALUE_MAX) {
121 rate = (double)SVCAM_CTRL_VALUE_MAX / (double)dist;
122 ret = (int32_t)((double)(value - min) * rate);
124 rate = (double)dist / (double)SVCAM_CTRL_VALUE_MAX;
125 ret = (int32_t)((double)(value - min) / rate);
131 static int __v4l2_grab(SVCamState *state)
134 static uint32_t index = 0;
140 FD_SET(v4l2_fd, &fds);
145 ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv);
149 ERR("select : %s\n", strerror(errno));
158 WARN("file descriptor is closed or not opened \n");
162 buf = state->vaddr + (state->buf_size * index);
163 ret = v4l2_read(v4l2_fd, buf, state->buf_size);
168 ERR("v4l2_read failed : %s\n", strerror(errno));
174 if (convert_trial-- == -1) {
175 ERR("Try count for v4l2_read is exceeded\n");
184 pthread_mutex_lock(&state->thread->mutex_lock);
185 if (state->streamon) {
186 if (state->req_frame) {
187 qemu_irq_raise(state->dev.irq[2]);
188 state->req_frame = 0;
194 pthread_mutex_unlock(&state->thread->mutex_lock);
200 static void *svcam_worker_thread(void *thread_param)
202 SVCamThreadInfo* thread = (SVCamThreadInfo*)thread_param;
205 pthread_mutex_lock(&thread->mutex_lock);
206 thread->state->streamon = 0;
208 pthread_cond_wait(&thread->thread_cond, &thread->mutex_lock);
209 pthread_mutex_unlock(&thread->mutex_lock);
210 INFO("Streaming on ......\n");
214 pthread_mutex_lock(&thread->mutex_lock);
215 if (thread->state->streamon) {
216 pthread_mutex_unlock(&thread->mutex_lock);
217 if (__v4l2_grab(thread->state) < 0) {
218 INFO("...... Streaming off\n");
219 goto wait_worker_thread;
222 pthread_mutex_unlock(&thread->mutex_lock);
223 goto wait_worker_thread;
229 void svcam_device_init(SVCamState* state)
231 SVCamThreadInfo *thread = state->thread;
233 if (pthread_cond_init(&thread->thread_cond, NULL)) {
234 ERR("failed to initialize thread condition\n");
237 if (pthread_mutex_init(&thread->mutex_lock, NULL)) {
238 ERR("failed to initialize mutex\n");
242 if (pthread_create(&thread->thread_id, NULL, svcam_worker_thread, (void*)thread) != 0) {
243 perror("failed to create a worker thread for webcam connection\n");
249 void svcam_device_open(SVCamState* state)
251 struct v4l2_capability cap;
252 SVCamParam *param = state->thread->param;
255 v4l2_fd = v4l2_open("/dev/video0", O_RDWR | O_NONBLOCK);
257 ERR("v4l2 device open failed.(/dev/video0)\n");
258 param->errCode = EINVAL;
261 if (xioctl(v4l2_fd, VIDIOC_QUERYCAP, &cap) < 0) {
262 ERR("Could not qeury video capabilities\n");
264 param->errCode = EINVAL;
267 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||
268 !(cap.capabilities & V4L2_CAP_STREAMING)) {
269 ERR("Not supported video driver.\n");
271 param->errCode = EINVAL;
275 memset(&dst_fmt, 0, sizeof(dst_fmt));
279 // SVCAM_CMD_START_PREVIEW
280 void svcam_device_start_preview(SVCamState* state)
282 pthread_mutex_lock(&state->thread->mutex_lock);
284 state->buf_size = dst_fmt.fmt.pix.sizeimage;
285 if (pthread_cond_signal(&state->thread->thread_cond))
286 ERR("failed to send a signal to the worker thread\n");
287 pthread_mutex_unlock(&state->thread->mutex_lock);
290 // SVCAM_CMD_STOP_PREVIEW
291 void svcam_device_stop_preview(SVCamState* state)
293 pthread_mutex_lock(&state->thread->mutex_lock);
296 pthread_mutex_unlock(&state->thread->mutex_lock);
300 void svcam_device_s_param(SVCamState* state)
302 struct v4l2_streamparm sp;
303 SVCamParam *param = state->thread->param;
306 memset(&sp, 0, sizeof(struct v4l2_streamparm));
307 sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
308 sp.parm.capture.timeperframe.numerator = param->stack[0];
309 sp.parm.capture.timeperframe.denominator = param->stack[1];
311 if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) {
312 ERR("failed to set FPS: %s\n", strerror(errno));
313 param->errCode = errno;
317 void svcam_device_g_param(SVCamState* state)
319 struct v4l2_streamparm sp;
320 SVCamParam *param = state->thread->param;
323 memset(&sp, 0, sizeof(struct v4l2_streamparm));
324 sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
326 if (xioctl(v4l2_fd, VIDIOC_G_PARM, &sp) < 0) {
327 ERR("failed to get FPS: %s\n", strerror(errno));
328 param->errCode = errno;
331 param->stack[0] = sp.parm.capture.capability;
332 param->stack[1] = sp.parm.capture.timeperframe.numerator;
333 param->stack[2] = sp.parm.capture.timeperframe.denominator;
336 void svcam_device_s_fmt(SVCamState* state)
338 SVCamParam *param = state->thread->param;
341 memset(&dst_fmt, 0, sizeof(struct v4l2_format));
342 dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
343 dst_fmt.fmt.pix.width = param->stack[0];
344 dst_fmt.fmt.pix.height = param->stack[1];
345 dst_fmt.fmt.pix.pixelformat = param->stack[2];
346 dst_fmt.fmt.pix.field = param->stack[3];
348 if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) {
349 ERR("failed to set video format: %s\n", strerror(errno));
350 param->errCode = errno;
354 param->stack[0] = dst_fmt.fmt.pix.width;
355 param->stack[1] = dst_fmt.fmt.pix.height;
356 param->stack[2] = dst_fmt.fmt.pix.field;
357 param->stack[3] = dst_fmt.fmt.pix.pixelformat;
358 param->stack[4] = dst_fmt.fmt.pix.bytesperline;
359 param->stack[5] = dst_fmt.fmt.pix.sizeimage;
360 param->stack[6] = dst_fmt.fmt.pix.colorspace;
361 param->stack[7] = dst_fmt.fmt.pix.priv;
364 void svcam_device_g_fmt(SVCamState* state)
366 struct v4l2_format format;
367 SVCamParam *param = state->thread->param;
370 memset(&format, 0, sizeof(struct v4l2_format));
371 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
373 if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) {
374 ERR("failed to get video format: %s\n", strerror(errno));
375 param->errCode = errno;
377 param->stack[0] = format.fmt.pix.width;
378 param->stack[1] = format.fmt.pix.height;
379 param->stack[2] = format.fmt.pix.field;
380 param->stack[3] = format.fmt.pix.pixelformat;
381 param->stack[4] = format.fmt.pix.bytesperline;
382 param->stack[5] = format.fmt.pix.sizeimage;
383 param->stack[6] = format.fmt.pix.colorspace;
384 param->stack[7] = format.fmt.pix.priv;
385 memcpy(&dst_fmt, &format, sizeof(format));
389 void svcam_device_try_fmt(SVCamState* state)
391 struct v4l2_format format;
392 SVCamParam *param = state->thread->param;
395 memset(&format, 0, sizeof(struct v4l2_format));
396 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
397 format.fmt.pix.width = param->stack[0];
398 format.fmt.pix.height = param->stack[1];
399 format.fmt.pix.pixelformat = param->stack[2];
400 format.fmt.pix.field = param->stack[3];
402 if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) {
403 ERR("failed to check video format: %s\n", strerror(errno));
404 param->errCode = errno;
407 param->stack[0] = format.fmt.pix.width;
408 param->stack[1] = format.fmt.pix.height;
409 param->stack[2] = format.fmt.pix.field;
410 param->stack[3] = format.fmt.pix.pixelformat;
411 param->stack[4] = format.fmt.pix.bytesperline;
412 param->stack[5] = format.fmt.pix.sizeimage;
413 param->stack[6] = format.fmt.pix.colorspace;
414 param->stack[7] = format.fmt.pix.priv;
417 void svcam_device_enum_fmt(SVCamState* state)
419 struct v4l2_fmtdesc format;
420 SVCamParam *param = state->thread->param;
423 memset(&format, 0, sizeof(struct v4l2_fmtdesc));
424 format.index = param->stack[0];
425 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
427 if (xioctl(v4l2_fd, VIDIOC_ENUM_FMT, &format) < 0) {
429 ERR("failed to enumerate video formats: %s\n", strerror(errno));
430 param->errCode = errno;
433 param->stack[0] = format.index;
434 param->stack[1] = format.flags;
435 param->stack[2] = format.pixelformat;
436 /* set description */
437 memcpy(¶m->stack[3], format.description, sizeof(format.description));
440 void svcam_device_qctrl(SVCamState* state)
443 char name[32] = {0,};
444 struct v4l2_queryctrl ctrl;
445 SVCamParam *param = state->thread->param;
448 memset(&ctrl, 0, sizeof(struct v4l2_queryctrl));
449 ctrl.id = param->stack[0];
452 case V4L2_CID_BRIGHTNESS:
453 TRACE("Query : BRIGHTNESS\n");
454 memcpy((void*)name, (void*)"brightness", 32);
457 case V4L2_CID_CONTRAST:
458 TRACE("Query : CONTRAST\n");
459 memcpy((void*)name, (void*)"contrast", 32);
462 case V4L2_CID_SATURATION:
463 TRACE("Query : SATURATION\n");
464 memcpy((void*)name, (void*)"saturation", 32);
467 case V4L2_CID_SHARPNESS:
468 TRACE("Query : SHARPNESS\n");
469 memcpy((void*)name, (void*)"sharpness", 32);
473 param->errCode = EINVAL;
477 if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) {
479 ERR("failed to query video controls : %s\n", strerror(errno));
480 param->errCode = errno;
483 struct v4l2_control sctrl;
484 memset(&sctrl, 0, sizeof(struct v4l2_control));
486 if ((ctrl.maximum + ctrl.minimum) == 0) {
489 sctrl.value = (ctrl.maximum + ctrl.minimum) / 2;
491 if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) {
492 ERR("failed to set video control value : %s\n", strerror(errno));
493 param->errCode = errno;
496 qctrl_tbl[i].hit = 1;
497 qctrl_tbl[i].min = ctrl.minimum;
498 qctrl_tbl[i].max = ctrl.maximum;
499 qctrl_tbl[i].step = ctrl.step;
500 qctrl_tbl[i].init_val = ctrl.default_value;
503 // set fixed values by FW configuration file
504 param->stack[0] = ctrl.id;
505 param->stack[1] = SVCAM_CTRL_VALUE_MIN; // minimum
506 param->stack[2] = SVCAM_CTRL_VALUE_MAX; // maximum
507 param->stack[3] = SVCAM_CTRL_VALUE_STEP;// step
508 param->stack[4] = SVCAM_CTRL_VALUE_MID; // default_value
509 param->stack[5] = ctrl.flags;
510 /* name field setting */
511 memcpy(¶m->stack[6], (void*)name, sizeof(ctrl.name));
514 void svcam_device_s_ctrl(SVCamState* state)
517 struct v4l2_control ctrl;
518 SVCamParam *param = state->thread->param;
521 memset(&ctrl, 0, sizeof(struct v4l2_control));
522 ctrl.id = param->stack[0];
525 case V4L2_CID_BRIGHTNESS:
527 TRACE("%d is set to the value of the BRIGHTNESS\n", param->stack[1]);
529 case V4L2_CID_CONTRAST:
531 TRACE("%d is set to the value of the CONTRAST\n", param->stack[1]);
533 case V4L2_CID_SATURATION:
535 TRACE("%d is set to the value of the SATURATION\n", param->stack[1]);
537 case V4L2_CID_SHARPNESS:
539 TRACE("%d is set to the value of the SHARPNESS\n", param->stack[1]);
542 ERR("our emulator does not support this control : 0x%x\n", ctrl.id);
543 param->errCode = EINVAL;
547 ctrl.value = value_convert_from_guest(qctrl_tbl[i].min,
548 qctrl_tbl[i].max, param->stack[1]);
549 if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
550 ERR("failed to set video control value : value(%d), %s\n", param->stack[1], strerror(errno));
551 param->errCode = errno;
556 void svcam_device_g_ctrl(SVCamState* state)
559 struct v4l2_control ctrl;
560 SVCamParam *param = state->thread->param;
563 memset(&ctrl, 0, sizeof(struct v4l2_control));
564 ctrl.id = param->stack[0];
567 case V4L2_CID_BRIGHTNESS:
568 TRACE("Gets the value of the BRIGHTNESS\n");
571 case V4L2_CID_CONTRAST:
572 TRACE("Gets the value of the CONTRAST\n");
575 case V4L2_CID_SATURATION:
576 TRACE("Gets the value of the SATURATION\n");
579 case V4L2_CID_SHARPNESS:
580 TRACE("Gets the value of the SHARPNESS\n");
584 ERR("our emulator does not support this control : 0x%x\n", ctrl.id);
585 param->errCode = EINVAL;
589 if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &ctrl) < 0) {
590 ERR("failed to get video control value : %s\n", strerror(errno));
591 param->errCode = errno;
594 param->stack[0] = value_convert_to_guest(qctrl_tbl[i].min,
595 qctrl_tbl[i].max, ctrl.value);
596 TRACE("Value : %d\n", param->stack[0]);
599 void svcam_device_enum_fsizes(SVCamState* state)
601 struct v4l2_frmsizeenum fsize;
602 SVCamParam *param = state->thread->param;
605 memset(&fsize, 0, sizeof(struct v4l2_frmsizeenum));
606 fsize.index = param->stack[0];
607 fsize.pixel_format = param->stack[1];
609 if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMESIZES, &fsize) < 0) {
611 ERR("failed to get frame sizes : %s\n", strerror(errno));
612 param->errCode = errno;
616 if (fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
617 param->stack[0] = fsize.discrete.width;
618 param->stack[1] = fsize.discrete.height;
620 param->errCode = EINVAL;
621 ERR("Not Supported mode, we only support DISCRETE\n");
625 void svcam_device_enum_fintv(SVCamState* state)
627 struct v4l2_frmivalenum ival;
628 SVCamParam *param = state->thread->param;
631 memset(&ival, 0, sizeof(struct v4l2_frmivalenum));
632 ival.index = param->stack[0];
633 ival.pixel_format = param->stack[1];
634 ival.width = param->stack[2];
635 ival.height = param->stack[3];
637 if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0) {
639 ERR("failed to get frame intervals : %s\n", strerror(errno));
640 param->errCode = errno;
644 if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
645 param->stack[0] = ival.discrete.numerator;
646 param->stack[1] = ival.discrete.denominator;
648 param->errCode = EINVAL;
649 ERR("Not Supported mode, we only support DISCRETE\n");
654 void svcam_device_close(SVCamState* state)
656 pthread_mutex_lock(&state->thread->mutex_lock);
658 pthread_mutex_unlock(&state->thread->mutex_lock);
660 svcam_reset_controls();