diff options
Diffstat (limited to 'drivers/media/video/vino.c')
-rw-r--r-- | drivers/media/video/vino.c | 290 |
1 files changed, 114 insertions, 176 deletions
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 675067f92d96..8da4dd1e0e94 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c | |||
@@ -3102,22 +3102,14 @@ out: | |||
3102 | static int vino_enum_fmt_vid_cap(struct file *file, void *__fh, | 3102 | static int vino_enum_fmt_vid_cap(struct file *file, void *__fh, |
3103 | struct v4l2_fmtdesc *fd) | 3103 | struct v4l2_fmtdesc *fd) |
3104 | { | 3104 | { |
3105 | enum v4l2_buf_type type = fd->type; | 3105 | dprintk("format index = %d\n", fd->index); |
3106 | int index = fd->index; | ||
3107 | 3106 | ||
3108 | dprintk("format index = %d\n", index); | 3107 | if (fd->index >= VINO_DATA_FMT_COUNT) |
3109 | |||
3110 | if ((fd->index < 0) || | ||
3111 | (fd->index >= VINO_DATA_FMT_COUNT)) | ||
3112 | return -EINVAL; | 3108 | return -EINVAL; |
3113 | dprintk("format name = %s\n", | 3109 | dprintk("format name = %s\n", vino_data_formats[fd->index].description); |
3114 | vino_data_formats[index].description); | 3110 | |
3115 | 3111 | fd->pixelformat = vino_data_formats[fd->index].pixelformat; | |
3116 | memset(fd, 0, sizeof(struct v4l2_fmtdesc)); | 3112 | strcpy(fd->description, vino_data_formats[fd->index].description); |
3117 | fd->index = index; | ||
3118 | fd->type = type; | ||
3119 | fd->pixelformat = vino_data_formats[index].pixelformat; | ||
3120 | strcpy(fd->description, vino_data_formats[index].description); | ||
3121 | return 0; | 3113 | return 0; |
3122 | } | 3114 | } |
3123 | 3115 | ||
@@ -3327,28 +3319,18 @@ static int vino_g_parm(struct file *file, void *__fh, | |||
3327 | { | 3319 | { |
3328 | struct vino_channel_settings *vcs = video_drvdata(file); | 3320 | struct vino_channel_settings *vcs = video_drvdata(file); |
3329 | unsigned long flags; | 3321 | unsigned long flags; |
3322 | struct v4l2_captureparm *cp = &sp->parm.capture; | ||
3330 | 3323 | ||
3331 | switch (sp->type) { | 3324 | cp->capability = V4L2_CAP_TIMEPERFRAME; |
3332 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | 3325 | cp->timeperframe.numerator = 1; |
3333 | struct v4l2_captureparm *cp = &sp->parm.capture; | ||
3334 | memset(cp, 0, sizeof(struct v4l2_captureparm)); | ||
3335 | 3326 | ||
3336 | cp->capability = V4L2_CAP_TIMEPERFRAME; | 3327 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
3337 | cp->timeperframe.numerator = 1; | ||
3338 | 3328 | ||
3339 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); | 3329 | cp->timeperframe.denominator = vcs->fps; |
3340 | 3330 | ||
3341 | cp->timeperframe.denominator = vcs->fps; | 3331 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); |
3342 | 3332 | ||
3343 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | 3333 | /* TODO: cp->readbuffers = xxx; */ |
3344 | |||
3345 | // TODO: cp->readbuffers = xxx; | ||
3346 | break; | ||
3347 | } | ||
3348 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3349 | default: | ||
3350 | return -EINVAL; | ||
3351 | } | ||
3352 | 3334 | ||
3353 | return 0; | 3335 | return 0; |
3354 | } | 3336 | } |
@@ -3358,32 +3340,21 @@ static int vino_s_parm(struct file *file, void *__fh, | |||
3358 | { | 3340 | { |
3359 | struct vino_channel_settings *vcs = video_drvdata(file); | 3341 | struct vino_channel_settings *vcs = video_drvdata(file); |
3360 | unsigned long flags; | 3342 | unsigned long flags; |
3343 | struct v4l2_captureparm *cp = &sp->parm.capture; | ||
3361 | 3344 | ||
3362 | switch (sp->type) { | 3345 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); |
3363 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
3364 | struct v4l2_captureparm *cp = &sp->parm.capture; | ||
3365 | |||
3366 | spin_lock_irqsave(&vino_drvdata->input_lock, flags); | ||
3367 | |||
3368 | if ((cp->timeperframe.numerator == 0) || | ||
3369 | (cp->timeperframe.denominator == 0)) { | ||
3370 | /* reset framerate */ | ||
3371 | vino_set_default_framerate(vcs); | ||
3372 | } else { | ||
3373 | vino_set_framerate(vcs, cp->timeperframe.denominator / | ||
3374 | cp->timeperframe.numerator); | ||
3375 | } | ||
3376 | |||
3377 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | ||
3378 | 3346 | ||
3379 | // TODO: set buffers according to cp->readbuffers | 3347 | if ((cp->timeperframe.numerator == 0) || |
3380 | break; | 3348 | (cp->timeperframe.denominator == 0)) { |
3381 | } | 3349 | /* reset framerate */ |
3382 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 3350 | vino_set_default_framerate(vcs); |
3383 | default: | 3351 | } else { |
3384 | return -EINVAL; | 3352 | vino_set_framerate(vcs, cp->timeperframe.denominator / |
3353 | cp->timeperframe.numerator); | ||
3385 | } | 3354 | } |
3386 | 3355 | ||
3356 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); | ||
3357 | |||
3387 | return 0; | 3358 | return 0; |
3388 | } | 3359 | } |
3389 | 3360 | ||
@@ -3391,42 +3362,35 @@ static int vino_reqbufs(struct file *file, void *__fh, | |||
3391 | struct v4l2_requestbuffers *rb) | 3362 | struct v4l2_requestbuffers *rb) |
3392 | { | 3363 | { |
3393 | struct vino_channel_settings *vcs = video_drvdata(file); | 3364 | struct vino_channel_settings *vcs = video_drvdata(file); |
3365 | |||
3394 | if (vcs->reading) | 3366 | if (vcs->reading) |
3395 | return -EBUSY; | 3367 | return -EBUSY; |
3396 | 3368 | ||
3397 | switch (rb->type) { | 3369 | /* TODO: check queue type */ |
3398 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | 3370 | if (rb->memory != V4L2_MEMORY_MMAP) { |
3399 | // TODO: check queue type | 3371 | dprintk("type not mmap\n"); |
3400 | if (rb->memory != V4L2_MEMORY_MMAP) { | 3372 | return -EINVAL; |
3401 | dprintk("type not mmap\n"); | 3373 | } |
3402 | return -EINVAL; | ||
3403 | } | ||
3404 | 3374 | ||
3405 | dprintk("count = %d\n", rb->count); | 3375 | dprintk("count = %d\n", rb->count); |
3406 | if (rb->count > 0) { | 3376 | if (rb->count > 0) { |
3407 | if (vino_is_capturing(vcs)) { | 3377 | if (vino_is_capturing(vcs)) { |
3408 | dprintk("busy, capturing\n"); | 3378 | dprintk("busy, capturing\n"); |
3409 | return -EBUSY; | 3379 | return -EBUSY; |
3410 | } | 3380 | } |
3411 | 3381 | ||
3412 | if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) { | 3382 | if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) { |
3413 | dprintk("busy, buffers still mapped\n"); | 3383 | dprintk("busy, buffers still mapped\n"); |
3414 | return -EBUSY; | 3384 | return -EBUSY; |
3415 | } else { | ||
3416 | vcs->streaming = 0; | ||
3417 | vino_queue_free(&vcs->fb_queue); | ||
3418 | vino_queue_init(&vcs->fb_queue, &rb->count); | ||
3419 | } | ||
3420 | } else { | 3385 | } else { |
3421 | vcs->streaming = 0; | 3386 | vcs->streaming = 0; |
3422 | vino_capture_stop(vcs); | ||
3423 | vino_queue_free(&vcs->fb_queue); | 3387 | vino_queue_free(&vcs->fb_queue); |
3388 | vino_queue_init(&vcs->fb_queue, &rb->count); | ||
3424 | } | 3389 | } |
3425 | break; | 3390 | } else { |
3426 | } | 3391 | vcs->streaming = 0; |
3427 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 3392 | vino_capture_stop(vcs); |
3428 | default: | 3393 | vino_queue_free(&vcs->fb_queue); |
3429 | return -EINVAL; | ||
3430 | } | 3394 | } |
3431 | 3395 | ||
3432 | return 0; | 3396 | return 0; |
@@ -3474,35 +3438,27 @@ static int vino_querybuf(struct file *file, void *__fh, | |||
3474 | struct v4l2_buffer *b) | 3438 | struct v4l2_buffer *b) |
3475 | { | 3439 | { |
3476 | struct vino_channel_settings *vcs = video_drvdata(file); | 3440 | struct vino_channel_settings *vcs = video_drvdata(file); |
3441 | struct vino_framebuffer *fb; | ||
3442 | |||
3477 | if (vcs->reading) | 3443 | if (vcs->reading) |
3478 | return -EBUSY; | 3444 | return -EBUSY; |
3479 | 3445 | ||
3480 | switch (b->type) { | 3446 | /* TODO: check queue type */ |
3481 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | 3447 | if (b->index >= vino_queue_get_length(&vcs->fb_queue)) { |
3482 | struct vino_framebuffer *fb; | 3448 | dprintk("invalid index = %d\n", |
3483 | 3449 | b->index); | |
3484 | // TODO: check queue type | 3450 | return -EINVAL; |
3485 | if (b->index >= vino_queue_get_length(&vcs->fb_queue)) { | ||
3486 | dprintk("invalid index = %d\n", | ||
3487 | b->index); | ||
3488 | return -EINVAL; | ||
3489 | } | ||
3490 | |||
3491 | fb = vino_queue_get_buffer(&vcs->fb_queue, | ||
3492 | b->index); | ||
3493 | if (fb == NULL) { | ||
3494 | dprintk("vino_queue_get_buffer() failed"); | ||
3495 | return -EINVAL; | ||
3496 | } | ||
3497 | |||
3498 | vino_v4l2_get_buffer_status(vcs, fb, b); | ||
3499 | break; | ||
3500 | } | 3451 | } |
3501 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 3452 | |
3502 | default: | 3453 | fb = vino_queue_get_buffer(&vcs->fb_queue, |
3454 | b->index); | ||
3455 | if (fb == NULL) { | ||
3456 | dprintk("vino_queue_get_buffer() failed"); | ||
3503 | return -EINVAL; | 3457 | return -EINVAL; |
3504 | } | 3458 | } |
3505 | 3459 | ||
3460 | vino_v4l2_get_buffer_status(vcs, fb, b); | ||
3461 | |||
3506 | return 0; | 3462 | return 0; |
3507 | } | 3463 | } |
3508 | 3464 | ||
@@ -3510,36 +3466,28 @@ static int vino_qbuf(struct file *file, void *__fh, | |||
3510 | struct v4l2_buffer *b) | 3466 | struct v4l2_buffer *b) |
3511 | { | 3467 | { |
3512 | struct vino_channel_settings *vcs = video_drvdata(file); | 3468 | struct vino_channel_settings *vcs = video_drvdata(file); |
3469 | struct vino_framebuffer *fb; | ||
3470 | int ret; | ||
3471 | |||
3513 | if (vcs->reading) | 3472 | if (vcs->reading) |
3514 | return -EBUSY; | 3473 | return -EBUSY; |
3515 | 3474 | ||
3516 | switch (b->type) { | 3475 | /* TODO: check queue type */ |
3517 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | 3476 | if (b->memory != V4L2_MEMORY_MMAP) { |
3518 | struct vino_framebuffer *fb; | 3477 | dprintk("type not mmap\n"); |
3519 | int ret; | 3478 | return -EINVAL; |
3520 | 3479 | } | |
3521 | // TODO: check queue type | ||
3522 | if (b->memory != V4L2_MEMORY_MMAP) { | ||
3523 | dprintk("type not mmap\n"); | ||
3524 | return -EINVAL; | ||
3525 | } | ||
3526 | 3480 | ||
3527 | fb = vino_capture_enqueue(vcs, b->index); | 3481 | fb = vino_capture_enqueue(vcs, b->index); |
3528 | if (fb == NULL) | 3482 | if (fb == NULL) |
3529 | return -EINVAL; | 3483 | return -EINVAL; |
3530 | 3484 | ||
3531 | vino_v4l2_get_buffer_status(vcs, fb, b); | 3485 | vino_v4l2_get_buffer_status(vcs, fb, b); |
3532 | 3486 | ||
3533 | if (vcs->streaming) { | 3487 | if (vcs->streaming) { |
3534 | ret = vino_capture_next(vcs, 1); | 3488 | ret = vino_capture_next(vcs, 1); |
3535 | if (ret) | 3489 | if (ret) |
3536 | return ret; | 3490 | return ret; |
3537 | } | ||
3538 | break; | ||
3539 | } | ||
3540 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3541 | default: | ||
3542 | return -EINVAL; | ||
3543 | } | 3491 | } |
3544 | 3492 | ||
3545 | return 0; | 3493 | return 0; |
@@ -3550,73 +3498,63 @@ static int vino_dqbuf(struct file *file, void *__fh, | |||
3550 | { | 3498 | { |
3551 | struct vino_channel_settings *vcs = video_drvdata(file); | 3499 | struct vino_channel_settings *vcs = video_drvdata(file); |
3552 | unsigned int nonblocking = file->f_flags & O_NONBLOCK; | 3500 | unsigned int nonblocking = file->f_flags & O_NONBLOCK; |
3501 | struct vino_framebuffer *fb; | ||
3502 | unsigned int incoming, outgoing; | ||
3503 | int err; | ||
3504 | |||
3553 | if (vcs->reading) | 3505 | if (vcs->reading) |
3554 | return -EBUSY; | 3506 | return -EBUSY; |
3555 | 3507 | ||
3556 | switch (b->type) { | 3508 | /* TODO: check queue type */ |
3557 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | 3509 | |
3558 | struct vino_framebuffer *fb; | 3510 | err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); |
3559 | unsigned int incoming, outgoing; | 3511 | if (err) { |
3560 | int err; | 3512 | dprintk("vino_queue_get_incoming() failed\n"); |
3513 | return -EINVAL; | ||
3514 | } | ||
3515 | err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing); | ||
3516 | if (err) { | ||
3517 | dprintk("vino_queue_get_outgoing() failed\n"); | ||
3518 | return -EINVAL; | ||
3519 | } | ||
3561 | 3520 | ||
3562 | // TODO: check queue type | 3521 | dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing); |
3563 | 3522 | ||
3564 | err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); | 3523 | if (outgoing == 0) { |
3565 | if (err) { | 3524 | if (incoming == 0) { |
3566 | dprintk("vino_queue_get_incoming() failed\n"); | 3525 | dprintk("no incoming or outgoing buffers\n"); |
3567 | return -EINVAL; | 3526 | return -EINVAL; |
3568 | } | 3527 | } |
3569 | err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing); | 3528 | if (nonblocking) { |
3570 | if (err) { | 3529 | dprintk("non-blocking I/O was selected and " |
3571 | dprintk("vino_queue_get_outgoing() failed\n"); | 3530 | "there are no buffers to dequeue\n"); |
3572 | return -EINVAL; | 3531 | return -EAGAIN; |
3573 | } | 3532 | } |
3574 | 3533 | ||
3575 | dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing); | 3534 | err = vino_wait_for_frame(vcs); |
3576 | 3535 | if (err) { | |
3577 | if (outgoing == 0) { | ||
3578 | if (incoming == 0) { | ||
3579 | dprintk("no incoming or outgoing buffers\n"); | ||
3580 | return -EINVAL; | ||
3581 | } | ||
3582 | if (nonblocking) { | ||
3583 | dprintk("non-blocking I/O was selected and " | ||
3584 | "there are no buffers to dequeue\n"); | ||
3585 | return -EAGAIN; | ||
3586 | } | ||
3587 | |||
3588 | err = vino_wait_for_frame(vcs); | 3536 | err = vino_wait_for_frame(vcs); |
3589 | if (err) { | 3537 | if (err) { |
3590 | err = vino_wait_for_frame(vcs); | 3538 | /* interrupted or no frames captured because of |
3591 | if (err) { | 3539 | * frame skipping */ |
3592 | /* interrupted or | 3540 | /* vino_capture_failed(vcs); */ |
3593 | * no frames captured because | 3541 | return -EIO; |
3594 | * of frame skipping */ | ||
3595 | // vino_capture_failed(vcs); | ||
3596 | return -EIO; | ||
3597 | } | ||
3598 | } | 3542 | } |
3599 | } | 3543 | } |
3544 | } | ||
3600 | 3545 | ||
3601 | fb = vino_queue_remove(&vcs->fb_queue, &b->index); | 3546 | fb = vino_queue_remove(&vcs->fb_queue, &b->index); |
3602 | if (fb == NULL) { | 3547 | if (fb == NULL) { |
3603 | dprintk("vino_queue_remove() failed\n"); | 3548 | dprintk("vino_queue_remove() failed\n"); |
3604 | return -EINVAL; | 3549 | return -EINVAL; |
3605 | } | 3550 | } |
3606 | |||
3607 | err = vino_check_buffer(vcs, fb); | ||
3608 | 3551 | ||
3609 | vino_v4l2_get_buffer_status(vcs, fb, b); | 3552 | err = vino_check_buffer(vcs, fb); |
3610 | 3553 | ||
3611 | if (err) | 3554 | vino_v4l2_get_buffer_status(vcs, fb, b); |
3612 | return -EIO; | ||
3613 | 3555 | ||
3614 | break; | 3556 | if (err) |
3615 | } | 3557 | return -EIO; |
3616 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3617 | default: | ||
3618 | return -EINVAL; | ||
3619 | } | ||
3620 | 3558 | ||
3621 | return 0; | 3559 | return 0; |
3622 | } | 3560 | } |