video.c revision 1.24
1/* $NetBSD: video.c,v 1.24 2010/12/14 03:25:16 jmcneill Exp $ */ 2 3/* 4 * Copyright (c) 2008 Patrick Mahoney <pat@polycrystal.org> 5 * All rights reserved. 6 * 7 * This code was written by Patrick Mahoney (pat@polycrystal.org) as 8 * part of Google Summer of Code 2008. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * This ia a Video4Linux 2 compatible /dev/video driver for NetBSD 34 * 35 * See http://v4l2spec.bytesex.org/ for Video4Linux 2 specifications 36 */ 37 38#include <sys/cdefs.h> 39__KERNEL_RCSID(0, "$NetBSD: video.c,v 1.24 2010/12/14 03:25:16 jmcneill Exp $"); 40 41#include "video.h" 42#if NVIDEO > 0 43 44#include <sys/param.h> 45#include <sys/ioctl.h> 46#include <sys/fcntl.h> 47#include <sys/vnode.h> 48#include <sys/poll.h> 49#include <sys/select.h> 50#include <sys/kmem.h> 51#include <sys/pool.h> 52#include <sys/conf.h> 53#include <sys/types.h> 54#include <sys/device.h> 55#include <sys/condvar.h> 56#include <sys/queue.h> 57#include <sys/videoio.h> 58 59#include <dev/video_if.h> 60 61/* #define VIDEO_DEBUG 1 */ 62 63#ifdef VIDEO_DEBUG 64#define DPRINTF(x) do { if (videodebug) printf x; } while (0) 65#define DPRINTFN(n,x) do { if (videodebug>(n)) printf x; } while (0) 66int videodebug = VIDEO_DEBUG; 67#else 68#define DPRINTF(x) 69#define DPRINTFN(n,x) 70#endif 71 72#define PAGE_ALIGN(a) (((a) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) 73 74#define VIDEO_DRIVER_VERSION 1 75 76/* TODO: move to sys/intr.h */ 77#define IPL_VIDEO IPL_VM 78#define splvideo() splvm() 79 80#define VIDEO_MIN_BUFS 2 81#define VIDEO_MAX_BUFS 32 82#define VIDEO_NUM_BUFS 4 83 84/* Scatter Buffer - an array of fixed size (PAGE_SIZE) chunks 85 * allocated non-contiguously and functions to get data into and out 86 * of the scatter buffer. */ 87struct scatter_buf { 88 pool_cache_t sb_pool; 89 size_t sb_size; /* size in bytes */ 90 size_t sb_npages; /* number of pages */ 91 uint8_t **sb_page_ary; /* array of page pointers */ 92}; 93 94struct scatter_io { 95 struct scatter_buf *sio_buf; 96 off_t sio_offset; 97 size_t sio_resid; 98}; 99 100static void scatter_buf_init(struct scatter_buf *); 101static void scatter_buf_destroy(struct scatter_buf *); 102static int scatter_buf_set_size(struct scatter_buf *, size_t); 103static paddr_t scatter_buf_map(struct scatter_buf *, off_t); 104 105static bool scatter_io_init(struct scatter_buf *, off_t, size_t, struct scatter_io *); 106static bool scatter_io_next(struct scatter_io *, void **, size_t *); 107static void scatter_io_undo(struct scatter_io *, size_t); 108static void scatter_io_copyin(struct scatter_io *, const void *); 109/* static void scatter_io_copyout(struct scatter_io *, void *); */ 110static int scatter_io_uiomove(struct scatter_io *, struct uio *); 111 112 113enum video_stream_method { 114 VIDEO_STREAM_METHOD_NONE, 115 VIDEO_STREAM_METHOD_READ, 116 VIDEO_STREAM_METHOD_MMAP, 117 VIDEO_STREAM_METHOD_USERPTR 118}; 119 120struct video_buffer { 121 struct v4l2_buffer *vb_buf; 122 SIMPLEQ_ENTRY(video_buffer) entries; 123}; 124 125SIMPLEQ_HEAD(sample_queue, video_buffer); 126 127struct video_stream { 128 int vs_flags; /* flags given to open() */ 129 130 struct video_format vs_format; 131 132 int vs_frameno; /* toggles between 0 and 1, 133 * or -1 if new */ 134 uint32_t vs_sequence; /* absoulte frame/sample number in 135 * sequence, wraps around */ 136 bool vs_drop; /* drop payloads from current 137 * frameno? */ 138 139 enum v4l2_buf_type vs_type; 140 uint8_t vs_nbufs; 141 struct video_buffer **vs_buf; 142 143 struct scatter_buf vs_data; /* stores video data for MMAP 144 * and READ */ 145 146 /* Video samples may exist in different locations. Initially, 147 * samples are queued into the ingress queue. The driver 148 * grabs these in turn and fills them with video data. Once 149 * filled, they are moved to the egress queue. Samples are 150 * dequeued either by user with MMAP method or, with READ 151 * method, videoread() works from the fist sample in the 152 * ingress queue without dequeing. In the first case, the 153 * user re-queues the buffer when finished, and videoread() 154 * does the same when all data has been read. The sample now 155 * returns to the ingress queue. */ 156 struct sample_queue vs_ingress; /* samples under driver control */ 157 struct sample_queue vs_egress; /* samples headed for userspace */ 158 159 bool vs_streaming; 160 enum video_stream_method vs_method; /* method by which 161 * userspace will read 162 * samples */ 163 164 kmutex_t vs_lock; /* Lock to manipulate queues. 165 * Should also be held when 166 * changing number of 167 * buffers. */ 168 kcondvar_t vs_sample_cv; /* signaled on new 169 * ingress sample */ 170 struct selinfo vs_sel; 171 172 uint32_t vs_bytesread; /* bytes read() from current 173 * sample thus far */ 174}; 175 176struct video_softc { 177 device_t sc_dev; 178 device_t hw_dev; /* Hardware (parent) device */ 179 void * hw_softc; /* Hardware device private softc */ 180 const struct video_hw_if *hw_if; /* Hardware interface */ 181 182 u_int sc_open; 183 int sc_refcnt; 184 int sc_opencnt; 185 bool sc_dying; 186 187 struct video_stream sc_stream_in; 188}; 189static int video_print(void *, const char *); 190 191static int video_match(device_t, cfdata_t, void *); 192static void video_attach(device_t, device_t, void *); 193static int video_detach(device_t, int); 194static int video_activate(device_t, enum devact); 195 196dev_type_open(videoopen); 197dev_type_close(videoclose); 198dev_type_read(videoread); 199dev_type_write(videowrite); 200dev_type_ioctl(videoioctl); 201dev_type_poll(videopoll); 202dev_type_mmap(videommap); 203 204const struct cdevsw video_cdevsw = { 205 videoopen, videoclose, videoread, videowrite, videoioctl, 206 nostop, notty, videopoll, videommap, nokqfilter, D_OTHER 207}; 208 209#define VIDEOUNIT(n) (minor(n)) 210 211CFATTACH_DECL_NEW(video, sizeof(struct video_softc), 212 video_match, video_attach, video_detach, video_activate); 213 214extern struct cfdriver video_cd; 215 216static const char * video_pixel_format_str(enum video_pixel_format); 217 218/* convert various values from V4L2 to native values of this driver */ 219static uint16_t v4l2id_to_control_id(uint32_t); 220static uint32_t control_flags_to_v4l2flags(uint32_t); 221static enum v4l2_ctrl_type control_type_to_v4l2type(enum video_control_type); 222 223static void v4l2_format_to_video_format(const struct v4l2_format *, 224 struct video_format *); 225static void video_format_to_v4l2_format(const struct video_format *, 226 struct v4l2_format *); 227static void v4l2_standard_to_video_standard(v4l2_std_id, 228 enum video_standard *); 229static void video_standard_to_v4l2_standard(enum video_standard, 230 struct v4l2_standard *); 231static void v4l2_input_to_video_input(const struct v4l2_input *, 232 struct video_input *); 233static void video_input_to_v4l2_input(const struct video_input *, 234 struct v4l2_input *); 235static void v4l2_audio_to_video_audio(const struct v4l2_audio *, 236 struct video_audio *); 237static void video_audio_to_v4l2_audio(const struct video_audio *, 238 struct v4l2_audio *); 239static void v4l2_tuner_to_video_tuner(const struct v4l2_tuner *, 240 struct video_tuner *); 241static void video_tuner_to_v4l2_tuner(const struct video_tuner *, 242 struct v4l2_tuner *); 243 244/* V4L2 api functions, typically called from videoioctl() */ 245static int video_enum_format(struct video_softc *, struct v4l2_fmtdesc *); 246static int video_get_format(struct video_softc *, 247 struct v4l2_format *); 248static int video_set_format(struct video_softc *, 249 struct v4l2_format *); 250static int video_try_format(struct video_softc *, 251 struct v4l2_format *); 252static int video_enum_standard(struct video_softc *, 253 struct v4l2_standard *); 254static int video_get_standard(struct video_softc *, v4l2_std_id *); 255static int video_set_standard(struct video_softc *, v4l2_std_id); 256static int video_enum_input(struct video_softc *, struct v4l2_input *); 257static int video_get_input(struct video_softc *, int *); 258static int video_set_input(struct video_softc *, int); 259static int video_enum_audio(struct video_softc *, struct v4l2_audio *); 260static int video_get_audio(struct video_softc *, struct v4l2_audio *); 261static int video_set_audio(struct video_softc *, struct v4l2_audio *); 262static int video_get_tuner(struct video_softc *, struct v4l2_tuner *); 263static int video_set_tuner(struct video_softc *, struct v4l2_tuner *); 264static int video_get_frequency(struct video_softc *, 265 struct v4l2_frequency *); 266static int video_set_frequency(struct video_softc *, 267 struct v4l2_frequency *); 268static int video_query_control(struct video_softc *, 269 struct v4l2_queryctrl *); 270static int video_get_control(struct video_softc *, 271 struct v4l2_control *); 272static int video_set_control(struct video_softc *, 273 const struct v4l2_control *); 274static int video_request_bufs(struct video_softc *, 275 struct v4l2_requestbuffers *); 276static int video_query_buf(struct video_softc *, struct v4l2_buffer *); 277static int video_queue_buf(struct video_softc *, struct v4l2_buffer *); 278static int video_dequeue_buf(struct video_softc *, struct v4l2_buffer *); 279static int video_stream_on(struct video_softc *, enum v4l2_buf_type); 280static int video_stream_off(struct video_softc *, enum v4l2_buf_type); 281 282static struct video_buffer * video_buffer_alloc(void); 283static void video_buffer_free(struct video_buffer *); 284 285 286/* functions for video_stream */ 287static void video_stream_init(struct video_stream *); 288static void video_stream_fini(struct video_stream *); 289 290static int video_stream_setup_bufs(struct video_stream *, 291 enum video_stream_method, 292 uint8_t); 293static void video_stream_teardown_bufs(struct video_stream *); 294 295static int video_stream_realloc_bufs(struct video_stream *, uint8_t); 296#define video_stream_free_bufs(vs) \ 297 video_stream_realloc_bufs((vs), 0) 298 299static void video_stream_enqueue(struct video_stream *, 300 struct video_buffer *); 301static struct video_buffer * video_stream_dequeue(struct video_stream *); 302static void video_stream_write(struct video_stream *, 303 const struct video_payload *); 304static void video_stream_sample_done(struct video_stream *); 305 306#ifdef VIDEO_DEBUG 307/* debugging */ 308static const char * video_ioctl_str(u_long); 309#endif 310 311 312static int 313video_match(device_t parent, cfdata_t match, void *aux) 314{ 315 struct video_attach_args *args; 316 317 args = aux; 318 DPRINTF(("video_match: hw=%p\n", args->hw_if)); 319 return 1; 320} 321 322 323static void 324video_attach(device_t parent, device_t self, void *aux) 325{ 326 struct video_softc *sc; 327 struct video_attach_args *args; 328 329 sc = device_private(self); 330 args = aux; 331 332 sc->sc_dev = self; 333 sc->hw_dev = parent; 334 sc->hw_if = args->hw_if; 335 sc->hw_softc = device_private(parent); 336 337 sc->sc_open = 0; 338 sc->sc_refcnt = 0; 339 sc->sc_opencnt = 0; 340 sc->sc_dying = false; 341 342 video_stream_init(&sc->sc_stream_in); 343 344 aprint_naive("\n"); 345 aprint_normal(": %s\n", sc->hw_if->get_devname(sc->hw_softc)); 346 347 DPRINTF(("video_attach: sc=%p hwif=%p\n", sc, sc->hw_if)); 348 349 if (!pmf_device_register(self, NULL, NULL)) 350 aprint_error_dev(self, "couldn't establish power handler\n"); 351} 352 353 354static int 355video_activate(device_t self, enum devact act) 356{ 357 struct video_softc *sc = device_private(self); 358 359 DPRINTF(("video_activate: sc=%p\n", sc)); 360 switch (act) { 361 case DVACT_DEACTIVATE: 362 sc->sc_dying = true; 363 return 0; 364 default: 365 return EOPNOTSUPP; 366 } 367} 368 369 370static int 371video_detach(device_t self, int flags) 372{ 373 struct video_softc *sc; 374 int maj, mn; 375 376 sc = device_private(self); 377 DPRINTF(("video_detach: sc=%p flags=%d\n", sc, flags)); 378 379 sc->sc_dying = true; 380 381 pmf_device_deregister(self); 382 383 maj = cdevsw_lookup_major(&video_cdevsw); 384 mn = device_unit(self); 385 /* close open instances */ 386 vdevgone(maj, mn, mn, VCHR); 387 388 video_stream_fini(&sc->sc_stream_in); 389 390 return 0; 391} 392 393 394static int 395video_print(void *aux, const char *pnp) 396{ 397 struct video_attach_args *arg; 398 399 if (pnp != NULL) { 400 DPRINTF(("video_print: have pnp\n")); 401 arg = aux; 402 aprint_normal("%s at %s\n", "video", pnp); 403 } else { 404 DPRINTF(("video_print: pnp is NULL\n")); 405 } 406 return UNCONF; 407} 408 409 410/* 411 * Called from hardware driver. This is where the MI audio driver 412 * gets probed/attached to the hardware driver. 413 */ 414device_t 415video_attach_mi(const struct video_hw_if *hw_if, device_t parent) 416{ 417 struct video_attach_args args; 418 419 args.hw_if = hw_if; 420 return config_found_ia(parent, "videobus", &args, video_print); 421} 422 423/* video_submit_payload - called by hardware driver to submit payload data */ 424void 425video_submit_payload(device_t self, const struct video_payload *payload) 426{ 427 struct video_softc *sc; 428 429 sc = device_private(self); 430 431 if (sc == NULL) 432 return; 433 434 video_stream_write(&sc->sc_stream_in, payload); 435} 436 437static const char * 438video_pixel_format_str(enum video_pixel_format px) 439{ 440 switch (px) { 441 case VIDEO_FORMAT_UYVY: return "UYVY"; 442 case VIDEO_FORMAT_YUV420: return "YUV420"; 443 case VIDEO_FORMAT_YUY2: return "YUYV"; 444 case VIDEO_FORMAT_NV12: return "NV12"; 445 case VIDEO_FORMAT_RGB24: return "RGB24"; 446 case VIDEO_FORMAT_RGB555: return "RGB555"; 447 case VIDEO_FORMAT_RGB565: return "RGB565"; 448 case VIDEO_FORMAT_SBGGR8: return "SBGGR8"; 449 case VIDEO_FORMAT_MJPEG: return "MJPEG"; 450 case VIDEO_FORMAT_DV: return "DV"; 451 case VIDEO_FORMAT_MPEG: return "MPEG"; 452 default: return "Unknown"; 453 } 454} 455 456/* Takes a V4L2 id and returns a "native" video driver control id. 457 * TODO: is there a better way to do this? some kind of array? */ 458static uint16_t 459v4l2id_to_control_id(uint32_t v4l2id) 460{ 461 /* mask includes class bits and control id bits */ 462 switch (v4l2id & 0xffffff) { 463 case V4L2_CID_BRIGHTNESS: return VIDEO_CONTROL_BRIGHTNESS; 464 case V4L2_CID_CONTRAST: return VIDEO_CONTROL_CONTRAST; 465 case V4L2_CID_SATURATION: return VIDEO_CONTROL_SATURATION; 466 case V4L2_CID_HUE: return VIDEO_CONTROL_HUE; 467 case V4L2_CID_HUE_AUTO: return VIDEO_CONTROL_HUE_AUTO; 468 case V4L2_CID_SHARPNESS: return VIDEO_CONTROL_SHARPNESS; 469 case V4L2_CID_GAMMA: return VIDEO_CONTROL_GAMMA; 470 471 /* "black level" means the same as "brightness", but V4L2 472 * defines two separate controls that are not identical. 473 * V4L2_CID_BLACK_LEVEL is deprecated however in V4L2. */ 474 case V4L2_CID_BLACK_LEVEL: return VIDEO_CONTROL_BRIGHTNESS; 475 476 case V4L2_CID_AUDIO_VOLUME: return VIDEO_CONTROL_UNDEFINED; 477 case V4L2_CID_AUDIO_BALANCE: return VIDEO_CONTROL_UNDEFINED; 478 case V4L2_CID_AUDIO_BASS: return VIDEO_CONTROL_UNDEFINED; 479 case V4L2_CID_AUDIO_TREBLE: return VIDEO_CONTROL_UNDEFINED; 480 case V4L2_CID_AUDIO_MUTE: return VIDEO_CONTROL_UNDEFINED; 481 case V4L2_CID_AUDIO_LOUDNESS: return VIDEO_CONTROL_UNDEFINED; 482 483 case V4L2_CID_AUTO_WHITE_BALANCE: 484 return VIDEO_CONTROL_WHITE_BALANCE_AUTO; 485 case V4L2_CID_DO_WHITE_BALANCE: 486 return VIDEO_CONTROL_WHITE_BALANCE_ACTION; 487 case V4L2_CID_RED_BALANCE: 488 case V4L2_CID_BLUE_BALANCE: 489 /* This might not fit in with the control_id/value_id scheme */ 490 return VIDEO_CONTROL_WHITE_BALANCE_COMPONENT; 491 case V4L2_CID_WHITE_BALANCE_TEMPERATURE: 492 return VIDEO_CONTROL_WHITE_BALANCE_TEMPERATURE; 493 case V4L2_CID_EXPOSURE: 494 return VIDEO_CONTROL_EXPOSURE_TIME_ABSOLUTE; 495 case V4L2_CID_GAIN: return VIDEO_CONTROL_GAIN; 496 case V4L2_CID_AUTOGAIN: return VIDEO_CONTROL_GAIN_AUTO; 497 case V4L2_CID_HFLIP: return VIDEO_CONTROL_HFLIP; 498 case V4L2_CID_VFLIP: return VIDEO_CONTROL_VFLIP; 499 case V4L2_CID_HCENTER_DEPRECATED: 500 case V4L2_CID_VCENTER_DEPRECATED: 501 return VIDEO_CONTROL_UNDEFINED; 502 case V4L2_CID_POWER_LINE_FREQUENCY: 503 return VIDEO_CONTROL_POWER_LINE_FREQUENCY; 504 case V4L2_CID_BACKLIGHT_COMPENSATION: 505 return VIDEO_CONTROL_BACKLIGHT_COMPENSATION; 506 default: return V4L2_CTRL_ID2CID(v4l2id); 507 } 508} 509 510 511static uint32_t 512control_flags_to_v4l2flags(uint32_t flags) 513{ 514 uint32_t v4l2flags = 0; 515 516 if (flags & VIDEO_CONTROL_FLAG_DISABLED) 517 v4l2flags |= V4L2_CTRL_FLAG_INACTIVE; 518 519 if (!(flags & VIDEO_CONTROL_FLAG_WRITE)) 520 v4l2flags |= V4L2_CTRL_FLAG_READ_ONLY; 521 522 if (flags & VIDEO_CONTROL_FLAG_AUTOUPDATE) 523 v4l2flags |= V4L2_CTRL_FLAG_GRABBED; 524 525 return v4l2flags; 526} 527 528 529static enum v4l2_ctrl_type 530control_type_to_v4l2type(enum video_control_type type) { 531 switch (type) { 532 case VIDEO_CONTROL_TYPE_INT: return V4L2_CTRL_TYPE_INTEGER; 533 case VIDEO_CONTROL_TYPE_BOOL: return V4L2_CTRL_TYPE_BOOLEAN; 534 case VIDEO_CONTROL_TYPE_LIST: return V4L2_CTRL_TYPE_MENU; 535 case VIDEO_CONTROL_TYPE_ACTION: return V4L2_CTRL_TYPE_BUTTON; 536 default: return V4L2_CTRL_TYPE_INTEGER; /* err? */ 537 } 538} 539 540 541static int 542video_query_control(struct video_softc *sc, 543 struct v4l2_queryctrl *query) 544{ 545 const struct video_hw_if *hw; 546 struct video_control_desc_group desc_group; 547 struct video_control_desc desc; 548 int err; 549 550 hw = sc->hw_if; 551 if (hw->get_control_desc_group) { 552 desc.group_id = desc.control_id = 553 v4l2id_to_control_id(query->id); 554 555 desc_group.group_id = desc.group_id; 556 desc_group.length = 1; 557 desc_group.desc = &desc; 558 559 err = hw->get_control_desc_group(sc->hw_softc, &desc_group); 560 if (err != 0) 561 return err; 562 563 query->type = control_type_to_v4l2type(desc.type); 564 memcpy(query->name, desc.name, 32); 565 query->minimum = desc.min; 566 query->maximum = desc.max; 567 query->step = desc.step; 568 query->default_value = desc.def; 569 query->flags = control_flags_to_v4l2flags(desc.flags); 570 571 return 0; 572 } else { 573 return EINVAL; 574 } 575} 576 577 578/* Takes a single Video4Linux2 control and queries the driver for the 579 * current value. */ 580static int 581video_get_control(struct video_softc *sc, 582 struct v4l2_control *vcontrol) 583{ 584 const struct video_hw_if *hw; 585 struct video_control_group group; 586 struct video_control control; 587 int err; 588 589 hw = sc->hw_if; 590 if (hw->get_control_group) { 591 control.group_id = control.control_id = 592 v4l2id_to_control_id(vcontrol->id); 593 /* ?? if "control_id" is arbitrarily defined by the 594 * driver, then we need some way to store it... Maybe 595 * it doesn't matter for single value controls. */ 596 control.value = 0; 597 598 group.group_id = control.group_id; 599 group.length = 1; 600 group.control = &control; 601 602 err = hw->get_control_group(sc->hw_softc, &group); 603 if (err != 0) 604 return err; 605 606 vcontrol->value = control.value; 607 return 0; 608 } else { 609 return EINVAL; 610 } 611} 612 613static void 614video_format_to_v4l2_format(const struct video_format *src, 615 struct v4l2_format *dest) 616{ 617 /* TODO: what about win and vbi formats? */ 618 dest->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 619 dest->fmt.pix.width = src->width; 620 dest->fmt.pix.height = src->height; 621 if (VIDEO_INTERLACED(src->interlace_flags)) 622 dest->fmt.pix.field = V4L2_FIELD_INTERLACED; 623 else 624 dest->fmt.pix.field = V4L2_FIELD_NONE; 625 dest->fmt.pix.bytesperline = src->stride; 626 dest->fmt.pix.sizeimage = src->sample_size; 627 dest->fmt.pix.priv = src->priv; 628 629 switch (src->color.primaries) { 630 case VIDEO_COLOR_PRIMARIES_SMPTE_170M: 631 dest->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; 632 break; 633 /* XXX */ 634 case VIDEO_COLOR_PRIMARIES_UNSPECIFIED: 635 default: 636 dest->fmt.pix.colorspace = 0; 637 break; 638 } 639 640 switch (src->pixel_format) { 641 case VIDEO_FORMAT_UYVY: 642 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; 643 break; 644 case VIDEO_FORMAT_YUV420: 645 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; 646 break; 647 case VIDEO_FORMAT_YUY2: 648 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; 649 break; 650 case VIDEO_FORMAT_NV12: 651 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12; 652 break; 653 case VIDEO_FORMAT_RGB24: 654 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24; 655 break; 656 case VIDEO_FORMAT_RGB555: 657 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB555; 658 break; 659 case VIDEO_FORMAT_RGB565: 660 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; 661 break; 662 case VIDEO_FORMAT_SBGGR8: 663 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; 664 break; 665 case VIDEO_FORMAT_MJPEG: 666 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; 667 break; 668 case VIDEO_FORMAT_DV: 669 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_DV; 670 break; 671 case VIDEO_FORMAT_MPEG: 672 dest->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 673 break; 674 case VIDEO_FORMAT_UNDEFINED: 675 default: 676 DPRINTF(("video_get_format: unknown pixel format %d\n", 677 src->pixel_format)); 678 dest->fmt.pix.pixelformat = 0; /* V4L2 doesn't define 679 * and "undefined" 680 * format? */ 681 break; 682 } 683 684} 685 686static void 687v4l2_format_to_video_format(const struct v4l2_format *src, 688 struct video_format *dest) 689{ 690 switch (src->type) { 691 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 692 dest->width = src->fmt.pix.width; 693 dest->height = src->fmt.pix.height; 694 695 dest->stride = src->fmt.pix.bytesperline; 696 dest->sample_size = src->fmt.pix.sizeimage; 697 698 if (src->fmt.pix.field == V4L2_FIELD_INTERLACED) 699 dest->interlace_flags = VIDEO_INTERLACE_ON; 700 else 701 dest->interlace_flags = VIDEO_INTERLACE_OFF; 702 703 switch (src->fmt.pix.colorspace) { 704 case V4L2_COLORSPACE_SMPTE170M: 705 dest->color.primaries = 706 VIDEO_COLOR_PRIMARIES_SMPTE_170M; 707 break; 708 /* XXX */ 709 default: 710 dest->color.primaries = 711 VIDEO_COLOR_PRIMARIES_UNSPECIFIED; 712 break; 713 } 714 715 switch (src->fmt.pix.pixelformat) { 716 case V4L2_PIX_FMT_UYVY: 717 dest->pixel_format = VIDEO_FORMAT_UYVY; 718 break; 719 case V4L2_PIX_FMT_YUV420: 720 dest->pixel_format = VIDEO_FORMAT_YUV420; 721 break; 722 case V4L2_PIX_FMT_YUYV: 723 dest->pixel_format = VIDEO_FORMAT_YUY2; 724 break; 725 case V4L2_PIX_FMT_NV12: 726 dest->pixel_format = VIDEO_FORMAT_NV12; 727 break; 728 case V4L2_PIX_FMT_RGB24: 729 dest->pixel_format = VIDEO_FORMAT_RGB24; 730 break; 731 case V4L2_PIX_FMT_RGB555: 732 dest->pixel_format = VIDEO_FORMAT_RGB555; 733 break; 734 case V4L2_PIX_FMT_RGB565: 735 dest->pixel_format = VIDEO_FORMAT_RGB565; 736 break; 737 case V4L2_PIX_FMT_SBGGR8: 738 dest->pixel_format = VIDEO_FORMAT_SBGGR8; 739 break; 740 case V4L2_PIX_FMT_MJPEG: 741 dest->pixel_format = VIDEO_FORMAT_MJPEG; 742 break; 743 case V4L2_PIX_FMT_DV: 744 dest->pixel_format = VIDEO_FORMAT_DV; 745 break; 746 case V4L2_PIX_FMT_MPEG: 747 dest->pixel_format = VIDEO_FORMAT_MPEG; 748 break; 749 default: 750 DPRINTF(("video: unknown v4l2 pixel format %d\n", 751 src->fmt.pix.pixelformat)); 752 dest->pixel_format = VIDEO_FORMAT_UNDEFINED; 753 break; 754 } 755 break; 756 default: 757 /* TODO: other v4l2 format types */ 758 DPRINTF(("video: unsupported v4l2 format type %d\n", 759 src->type)); 760 break; 761 } 762} 763 764static int 765video_enum_format(struct video_softc *sc, struct v4l2_fmtdesc *fmtdesc) 766{ 767 const struct video_hw_if *hw; 768 struct video_format vfmt; 769 struct v4l2_format fmt; 770 int err; 771 772 hw = sc->hw_if; 773 if (hw->enum_format == NULL) 774 return ENOTTY; 775 776 err = hw->enum_format(sc->hw_softc, fmtdesc->index, &vfmt); 777 if (err != 0) 778 return err; 779 780 video_format_to_v4l2_format(&vfmt, &fmt); 781 782 fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* TODO: only one type for now */ 783 fmtdesc->flags = 0; 784 if (vfmt.pixel_format >= VIDEO_FORMAT_MJPEG) 785 fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED; 786 strlcpy(fmtdesc->description, 787 video_pixel_format_str(vfmt.pixel_format), 788 sizeof(fmtdesc->description)); 789 fmtdesc->pixelformat = fmt.fmt.pix.pixelformat; 790 791 return 0; 792} 793 794static int 795video_get_format(struct video_softc *sc, 796 struct v4l2_format *format) 797{ 798 const struct video_hw_if *hw; 799 struct video_format vfmt; 800 int err; 801 802 hw = sc->hw_if; 803 if (hw->get_format == NULL) 804 return ENOTTY; 805 806 err = hw->get_format(sc->hw_softc, &vfmt); 807 if (err != 0) 808 return err; 809 810 video_format_to_v4l2_format(&vfmt, format); 811 812 return 0; 813} 814 815static int 816video_set_format(struct video_softc *sc, struct v4l2_format *fmt) 817{ 818 const struct video_hw_if *hw; 819 struct video_format vfmt; 820 int err; 821 822 hw = sc->hw_if; 823 if (hw->set_format == NULL) 824 return ENOTTY; 825 826 v4l2_format_to_video_format(fmt, &vfmt); 827 828 err = hw->set_format(sc->hw_softc, &vfmt); 829 if (err != 0) 830 return err; 831 832 video_format_to_v4l2_format(&vfmt, fmt); 833 sc->sc_stream_in.vs_format = vfmt; 834 835 return 0; 836} 837 838 839static int 840video_try_format(struct video_softc *sc, 841 struct v4l2_format *format) 842{ 843 const struct video_hw_if *hw; 844 struct video_format vfmt; 845 int err; 846 847 hw = sc->hw_if; 848 if (hw->try_format == NULL) 849 return ENOTTY; 850 851 v4l2_format_to_video_format(format, &vfmt); 852 853 err = hw->try_format(sc->hw_softc, &vfmt); 854 if (err != 0) 855 return err; 856 857 video_format_to_v4l2_format(&vfmt, format); 858 859 return 0; 860} 861 862static void 863v4l2_standard_to_video_standard(v4l2_std_id stdid, 864 enum video_standard *vstd) 865{ 866#define VSTD(id, vid) case (id): *vstd = (vid); break; 867 switch (stdid) { 868 VSTD(V4L2_STD_NTSC_M, VIDEO_STANDARD_NTSC_M) 869 default: 870 *vstd = VIDEO_STANDARD_UNKNOWN; 871 break; 872 } 873#undef VSTD 874} 875 876static void 877video_standard_to_v4l2_standard(enum video_standard vstd, 878 struct v4l2_standard *std) 879{ 880 switch (vstd) { 881 case VIDEO_STANDARD_NTSC_M: 882 std->id = V4L2_STD_NTSC_M; 883 strlcpy(std->name, "NTSC-M", sizeof(std->name)); 884 std->frameperiod.numerator = 1001; 885 std->frameperiod.denominator = 30000; 886 std->framelines = 525; 887 break; 888 default: 889 std->id = V4L2_STD_UNKNOWN; 890 strlcpy(std->name, "Unknown", sizeof(std->name)); 891 break; 892 } 893} 894 895static int 896video_enum_standard(struct video_softc *sc, struct v4l2_standard *std) 897{ 898 const struct video_hw_if *hw = sc->hw_if; 899 enum video_standard vstd; 900 int err; 901 902 /* simple webcam drivers don't need to implement this callback */ 903 if (hw->enum_standard == NULL) { 904 if (std->index != 0) 905 return EINVAL; 906 std->id = V4L2_STD_UNKNOWN; 907 strlcpy(std->name, "webcam", sizeof(std->name)); 908 return 0; 909 } 910 911 v4l2_standard_to_video_standard(std->id, &vstd); 912 913 err = hw->enum_standard(sc->hw_softc, std->index, &vstd); 914 if (err != 0) 915 return err; 916 917 video_standard_to_v4l2_standard(vstd, std); 918 919 return 0; 920} 921 922static int 923video_get_standard(struct video_softc *sc, v4l2_std_id *stdid) 924{ 925 const struct video_hw_if *hw = sc->hw_if; 926 struct v4l2_standard std; 927 enum video_standard vstd; 928 int err; 929 930 /* simple webcam drivers don't need to implement this callback */ 931 if (hw->get_standard == NULL) { 932 *stdid = V4L2_STD_UNKNOWN; 933 return 0; 934 } 935 936 err = hw->get_standard(sc->hw_softc, &vstd); 937 if (err != 0) 938 return err; 939 940 video_standard_to_v4l2_standard(vstd, &std); 941 *stdid = std.id; 942 943 return 0; 944} 945 946static int 947video_set_standard(struct video_softc *sc, v4l2_std_id stdid) 948{ 949 const struct video_hw_if *hw = sc->hw_if; 950 enum video_standard vstd; 951 952 /* simple webcam drivers don't need to implement this callback */ 953 if (hw->set_standard == NULL) { 954 if (stdid != V4L2_STD_UNKNOWN) 955 return EINVAL; 956 return 0; 957 } 958 959 v4l2_standard_to_video_standard(stdid, &vstd); 960 961 return hw->set_standard(sc->hw_softc, vstd); 962} 963 964static void 965v4l2_input_to_video_input(const struct v4l2_input *input, 966 struct video_input *vi) 967{ 968 vi->index = input->index; 969 strlcpy(vi->name, input->name, sizeof(vi->name)); 970 switch (input->type) { 971 case V4L2_INPUT_TYPE_TUNER: 972 vi->type = VIDEO_INPUT_TYPE_TUNER; 973 break; 974 case V4L2_INPUT_TYPE_CAMERA: 975 vi->type = VIDEO_INPUT_TYPE_CAMERA; 976 break; 977 } 978 vi->audiomask = input->audioset; 979 vi->tuner_index = input->tuner; 980 vi->standards = input->std; /* ... values are the same */ 981 vi->status = 0; 982 if (input->status & V4L2_IN_ST_NO_POWER) 983 vi->status |= VIDEO_STATUS_NO_POWER; 984 if (input->status & V4L2_IN_ST_NO_SIGNAL) 985 vi->status |= VIDEO_STATUS_NO_SIGNAL; 986 if (input->status & V4L2_IN_ST_NO_COLOR) 987 vi->status |= VIDEO_STATUS_NO_COLOR; 988 if (input->status & V4L2_IN_ST_NO_H_LOCK) 989 vi->status |= VIDEO_STATUS_NO_HLOCK; 990 if (input->status & V4L2_IN_ST_MACROVISION) 991 vi->status |= VIDEO_STATUS_MACROVISION; 992} 993 994static void 995video_input_to_v4l2_input(const struct video_input *vi, 996 struct v4l2_input *input) 997{ 998 input->index = vi->index; 999 strlcpy(input->name, vi->name, sizeof(input->name)); 1000 switch (vi->type) { 1001 case VIDEO_INPUT_TYPE_TUNER: 1002 input->type = V4L2_INPUT_TYPE_TUNER; 1003 break; 1004 case VIDEO_INPUT_TYPE_CAMERA: 1005 input->type = V4L2_INPUT_TYPE_CAMERA; 1006 break; 1007 } 1008 input->audioset = vi->audiomask; 1009 input->tuner = vi->tuner_index; 1010 input->std = vi->standards; /* ... values are the same */ 1011 input->status = 0; 1012 if (vi->status & VIDEO_STATUS_NO_POWER) 1013 input->status |= V4L2_IN_ST_NO_POWER; 1014 if (vi->status & VIDEO_STATUS_NO_SIGNAL) 1015 input->status |= V4L2_IN_ST_NO_SIGNAL; 1016 if (vi->status & VIDEO_STATUS_NO_COLOR) 1017 input->status |= V4L2_IN_ST_NO_COLOR; 1018 if (vi->status & VIDEO_STATUS_NO_HLOCK) 1019 input->status |= V4L2_IN_ST_NO_H_LOCK; 1020 if (vi->status & VIDEO_STATUS_MACROVISION) 1021 input->status |= V4L2_IN_ST_MACROVISION; 1022} 1023 1024static int 1025video_enum_input(struct video_softc *sc, struct v4l2_input *input) 1026{ 1027 const struct video_hw_if *hw = sc->hw_if; 1028 struct video_input vi; 1029 int err; 1030 1031 /* simple webcam drivers don't need to implement this callback */ 1032 if (hw->enum_input == NULL) { 1033 if (input->index != 0) 1034 return EINVAL; 1035 memset(input, 0, sizeof(*input)); 1036 input->index = 0; 1037 strlcpy(input->name, "Camera", sizeof(input->name)); 1038 input->type = V4L2_INPUT_TYPE_CAMERA; 1039 return 0; 1040 } 1041 1042 v4l2_input_to_video_input(input, &vi); 1043 1044 err = hw->enum_input(sc->hw_softc, input->index, &vi); 1045 if (err != 0) 1046 return err; 1047 1048 video_input_to_v4l2_input(&vi, input); 1049 1050 return 0; 1051} 1052 1053static int 1054video_get_input(struct video_softc *sc, int *index) 1055{ 1056 const struct video_hw_if *hw = sc->hw_if; 1057 struct video_input vi; 1058 struct v4l2_input input; 1059 int err; 1060 1061 /* simple webcam drivers don't need to implement this callback */ 1062 if (hw->get_input == NULL) { 1063 *index = 0; 1064 return 0; 1065 } 1066 1067 input.index = *index; 1068 v4l2_input_to_video_input(&input, &vi); 1069 1070 err = hw->get_input(sc->hw_softc, &vi); 1071 if (err != 0) 1072 return err; 1073 1074 video_input_to_v4l2_input(&vi, &input); 1075 *index = input.index; 1076 1077 return 0; 1078} 1079 1080static int 1081video_set_input(struct video_softc *sc, int index) 1082{ 1083 const struct video_hw_if *hw = sc->hw_if; 1084 struct video_input vi; 1085 struct v4l2_input input; 1086 1087 /* simple webcam drivers don't need to implement this callback */ 1088 if (hw->set_input == NULL) { 1089 if (index != 0) 1090 return EINVAL; 1091 return 0; 1092 } 1093 1094 input.index = index; 1095 v4l2_input_to_video_input(&input, &vi); 1096 1097 return hw->set_input(sc->hw_softc, &vi); 1098} 1099 1100static void 1101v4l2_audio_to_video_audio(const struct v4l2_audio *audio, 1102 struct video_audio *va) 1103{ 1104 va->index = audio->index; 1105 strlcpy(va->name, audio->name, sizeof(va->name)); 1106 va->caps = va->mode = 0; 1107 if (audio->capability & V4L2_AUDCAP_STEREO) 1108 va->caps |= VIDEO_AUDIO_F_STEREO; 1109 if (audio->capability & V4L2_AUDCAP_AVL) 1110 va->caps |= VIDEO_AUDIO_F_AVL; 1111 if (audio->mode & V4L2_AUDMODE_AVL) 1112 va->mode |= VIDEO_AUDIO_F_AVL; 1113} 1114 1115static void 1116video_audio_to_v4l2_audio(const struct video_audio *va, 1117 struct v4l2_audio *audio) 1118{ 1119 audio->index = va->index; 1120 strlcpy(audio->name, va->name, sizeof(audio->name)); 1121 audio->capability = audio->mode = 0; 1122 if (va->caps & VIDEO_AUDIO_F_STEREO) 1123 audio->capability |= V4L2_AUDCAP_STEREO; 1124 if (va->caps & VIDEO_AUDIO_F_AVL) 1125 audio->capability |= V4L2_AUDCAP_AVL; 1126 if (va->mode & VIDEO_AUDIO_F_AVL) 1127 audio->mode |= V4L2_AUDMODE_AVL; 1128} 1129 1130static int 1131video_enum_audio(struct video_softc *sc, struct v4l2_audio *audio) 1132{ 1133 const struct video_hw_if *hw = sc->hw_if; 1134 struct video_audio va; 1135 int err; 1136 1137 if (hw->enum_audio == NULL) 1138 return ENOTTY; 1139 1140 v4l2_audio_to_video_audio(audio, &va); 1141 1142 err = hw->enum_audio(sc->hw_softc, audio->index, &va); 1143 if (err != 0) 1144 return err; 1145 1146 video_audio_to_v4l2_audio(&va, audio); 1147 1148 return 0; 1149} 1150 1151static int 1152video_get_audio(struct video_softc *sc, struct v4l2_audio *audio) 1153{ 1154 const struct video_hw_if *hw = sc->hw_if; 1155 struct video_audio va; 1156 int err; 1157 1158 if (hw->get_audio == NULL) 1159 return ENOTTY; 1160 1161 v4l2_audio_to_video_audio(audio, &va); 1162 1163 err = hw->get_audio(sc->hw_softc, &va); 1164 if (err != 0) 1165 return err; 1166 1167 video_audio_to_v4l2_audio(&va, audio); 1168 1169 return 0; 1170} 1171 1172static int 1173video_set_audio(struct video_softc *sc, struct v4l2_audio *audio) 1174{ 1175 const struct video_hw_if *hw = sc->hw_if; 1176 struct video_audio va; 1177 1178 if (hw->set_audio == NULL) 1179 return ENOTTY; 1180 1181 v4l2_audio_to_video_audio(audio, &va); 1182 1183 return hw->set_audio(sc->hw_softc, &va); 1184} 1185 1186static void 1187v4l2_tuner_to_video_tuner(const struct v4l2_tuner *tuner, 1188 struct video_tuner *vt) 1189{ 1190 vt->index = tuner->index; 1191 strlcpy(vt->name, tuner->name, sizeof(vt->name)); 1192 vt->freq_lo = tuner->rangelow; 1193 vt->freq_hi = tuner->rangehigh; 1194 vt->signal = tuner->signal; 1195 vt->afc = tuner->afc; 1196 vt->caps = 0; 1197 if (tuner->capability & V4L2_TUNER_CAP_STEREO) 1198 vt->caps |= VIDEO_TUNER_F_STEREO; 1199 if (tuner->capability & V4L2_TUNER_CAP_LANG1) 1200 vt->caps |= VIDEO_TUNER_F_LANG1; 1201 if (tuner->capability & V4L2_TUNER_CAP_LANG2) 1202 vt->caps |= VIDEO_TUNER_F_LANG2; 1203 switch (tuner->audmode) { 1204 case V4L2_TUNER_MODE_MONO: 1205 vt->mode = VIDEO_TUNER_F_MONO; 1206 break; 1207 case V4L2_TUNER_MODE_STEREO: 1208 vt->mode = VIDEO_TUNER_F_STEREO; 1209 break; 1210 case V4L2_TUNER_MODE_LANG1: 1211 vt->mode = VIDEO_TUNER_F_LANG1; 1212 break; 1213 case V4L2_TUNER_MODE_LANG2: 1214 vt->mode = VIDEO_TUNER_F_LANG2; 1215 break; 1216 case V4L2_TUNER_MODE_LANG1_LANG2: 1217 vt->mode = VIDEO_TUNER_F_LANG1 | VIDEO_TUNER_F_LANG2; 1218 break; 1219 } 1220} 1221 1222static void 1223video_tuner_to_v4l2_tuner(const struct video_tuner *vt, 1224 struct v4l2_tuner *tuner) 1225{ 1226 tuner->index = vt->index; 1227 strlcpy(tuner->name, vt->name, sizeof(tuner->name)); 1228 tuner->rangelow = vt->freq_lo; 1229 tuner->rangehigh = vt->freq_hi; 1230 tuner->signal = vt->signal; 1231 tuner->afc = vt->afc; 1232 tuner->capability = 0; 1233 if (vt->caps & VIDEO_TUNER_F_STEREO) 1234 tuner->capability |= V4L2_TUNER_CAP_STEREO; 1235 if (vt->caps & VIDEO_TUNER_F_LANG1) 1236 tuner->capability |= V4L2_TUNER_CAP_LANG1; 1237 if (vt->caps & VIDEO_TUNER_F_LANG2) 1238 tuner->capability |= V4L2_TUNER_CAP_LANG2; 1239 switch (vt->mode) { 1240 case VIDEO_TUNER_F_MONO: 1241 tuner->audmode = V4L2_TUNER_MODE_MONO; 1242 break; 1243 case VIDEO_TUNER_F_STEREO: 1244 tuner->audmode = V4L2_TUNER_MODE_STEREO; 1245 break; 1246 case VIDEO_TUNER_F_LANG1: 1247 tuner->audmode = V4L2_TUNER_MODE_LANG1; 1248 break; 1249 case VIDEO_TUNER_F_LANG2: 1250 tuner->audmode = V4L2_TUNER_MODE_LANG2; 1251 break; 1252 case VIDEO_TUNER_F_LANG1|VIDEO_TUNER_F_LANG2: 1253 tuner->audmode = V4L2_TUNER_MODE_LANG1_LANG2; 1254 break; 1255 } 1256} 1257 1258static int 1259video_get_tuner(struct video_softc *sc, struct v4l2_tuner *tuner) 1260{ 1261 const struct video_hw_if *hw = sc->hw_if; 1262 struct video_tuner vt; 1263 int err; 1264 1265 if (hw->get_tuner == NULL) 1266 return ENOTTY; 1267 1268 v4l2_tuner_to_video_tuner(tuner, &vt); 1269 1270 err = hw->get_tuner(sc->hw_softc, &vt); 1271 if (err != 0) 1272 return err; 1273 1274 video_tuner_to_v4l2_tuner(&vt, tuner); 1275 1276 return 0; 1277} 1278 1279static int 1280video_set_tuner(struct video_softc *sc, struct v4l2_tuner *tuner) 1281{ 1282 const struct video_hw_if *hw = sc->hw_if; 1283 struct video_tuner vt; 1284 1285 if (hw->set_tuner == NULL) 1286 return ENOTTY; 1287 1288 v4l2_tuner_to_video_tuner(tuner, &vt); 1289 1290 return hw->set_tuner(sc->hw_softc, &vt); 1291} 1292 1293static int 1294video_get_frequency(struct video_softc *sc, struct v4l2_frequency *freq) 1295{ 1296 const struct video_hw_if *hw = sc->hw_if; 1297 struct video_frequency vfreq; 1298 int err; 1299 1300 if (hw->get_frequency == NULL) 1301 return ENOTTY; 1302 1303 err = hw->get_frequency(sc->hw_softc, &vfreq); 1304 if (err) 1305 return err; 1306 1307 freq->tuner = vfreq.tuner_index; 1308 freq->type = V4L2_TUNER_ANALOG_TV; 1309 freq->frequency = vfreq.frequency; 1310 1311 return 0; 1312} 1313 1314static int 1315video_set_frequency(struct video_softc *sc, struct v4l2_frequency *freq) 1316{ 1317 const struct video_hw_if *hw = sc->hw_if; 1318 struct video_frequency vfreq; 1319 1320 if (hw->set_frequency == NULL) 1321 return ENOTTY; 1322 if (freq->type != V4L2_TUNER_ANALOG_TV) 1323 return EINVAL; 1324 1325 vfreq.tuner_index = freq->tuner; 1326 vfreq.frequency = freq->frequency; 1327 1328 return hw->set_frequency(sc->hw_softc, &vfreq); 1329} 1330 1331/* Takes a single Video4Linux2 control, converts it to a struct 1332 * video_control, and calls the hardware driver. */ 1333static int 1334video_set_control(struct video_softc *sc, 1335 const struct v4l2_control *vcontrol) 1336{ 1337 const struct video_hw_if *hw; 1338 struct video_control_group group; 1339 struct video_control control; 1340 1341 hw = sc->hw_if; 1342 if (hw->set_control_group) { 1343 control.group_id = control.control_id = 1344 v4l2id_to_control_id(vcontrol->id); 1345 /* ?? if "control_id" is arbitrarily defined by the 1346 * driver, then we need some way to store it... Maybe 1347 * it doesn't matter for single value controls. */ 1348 control.value = vcontrol->value; 1349 1350 group.group_id = control.group_id; 1351 group.length = 1; 1352 group.control = &control; 1353 1354 return (hw->set_control_group(sc->hw_softc, &group)); 1355 } else { 1356 return EINVAL; 1357 } 1358} 1359 1360static int 1361video_request_bufs(struct video_softc *sc, 1362 struct v4l2_requestbuffers *req) 1363{ 1364 struct video_stream *vs = &sc->sc_stream_in; 1365 struct v4l2_buffer *buf; 1366 int i, err; 1367 1368 if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1369 return EINVAL; 1370 1371 vs->vs_type = req->type; 1372 1373 switch (req->memory) { 1374 case V4L2_MEMORY_MMAP: 1375 if (req->count < VIDEO_MIN_BUFS) 1376 req->count = VIDEO_MIN_BUFS; 1377 else if (req->count > VIDEO_MAX_BUFS) 1378 req->count = VIDEO_MAX_BUFS; 1379 1380 err = video_stream_setup_bufs(vs, 1381 VIDEO_STREAM_METHOD_MMAP, 1382 req->count); 1383 if (err != 0) 1384 return err; 1385 1386 for (i = 0; i < req->count; ++i) { 1387 buf = vs->vs_buf[i]->vb_buf; 1388 buf->memory = V4L2_MEMORY_MMAP; 1389 buf->flags |= V4L2_BUF_FLAG_MAPPED; 1390 } 1391 break; 1392 case V4L2_MEMORY_USERPTR: 1393 default: 1394 return EINVAL; 1395 } 1396 1397 return 0; 1398} 1399 1400static int 1401video_query_buf(struct video_softc *sc, 1402 struct v4l2_buffer *buf) 1403{ 1404 struct video_stream *vs = &sc->sc_stream_in; 1405 1406 if (buf->type != vs->vs_type) 1407 return EINVAL; 1408 if (buf->index >= vs->vs_nbufs) 1409 return EINVAL; 1410 1411 memcpy(buf, vs->vs_buf[buf->index]->vb_buf, sizeof(*buf)); 1412 1413 return 0; 1414} 1415 1416/* Accept a buffer descriptor from userspace and return the indicated 1417 * buffer to the driver's queue. */ 1418static int 1419video_queue_buf(struct video_softc *sc, struct v4l2_buffer *userbuf) 1420{ 1421 struct video_stream *vs = &sc->sc_stream_in; 1422 struct video_buffer *vb; 1423 struct v4l2_buffer *driverbuf; 1424 1425 if (userbuf->type != vs->vs_type) { 1426 DPRINTF(("video_queue_buf: expected type=%d got type=%d\n", 1427 userbuf->type, vs->vs_type)); 1428 return EINVAL; 1429 } 1430 if (userbuf->index >= vs->vs_nbufs) { 1431 DPRINTF(("video_queue_buf: invalid index %d >= %d\n", 1432 userbuf->index, vs->vs_nbufs)); 1433 return EINVAL; 1434 } 1435 1436 switch (vs->vs_method) { 1437 case VIDEO_STREAM_METHOD_MMAP: 1438 if (userbuf->memory != V4L2_MEMORY_MMAP) { 1439 DPRINTF(("video_queue_buf: invalid memory=%d\n", 1440 userbuf->memory)); 1441 return EINVAL; 1442 } 1443 1444 mutex_enter(&vs->vs_lock); 1445 1446 vb = vs->vs_buf[userbuf->index]; 1447 driverbuf = vb->vb_buf; 1448 if (driverbuf->flags & V4L2_BUF_FLAG_QUEUED) { 1449 DPRINTF(("video_queue_buf: buf already queued; " 1450 "flags=0x%x\n", driverbuf->flags)); 1451 mutex_exit(&vs->vs_lock); 1452 return EINVAL; 1453 } 1454 video_stream_enqueue(vs, vb); 1455 memcpy(userbuf, driverbuf, sizeof(*driverbuf)); 1456 1457 mutex_exit(&vs->vs_lock); 1458 break; 1459 default: 1460 return EINVAL; 1461 } 1462 1463 return 0; 1464} 1465 1466/* Dequeue the described buffer from the driver queue, making it 1467 * available for reading via mmap. */ 1468static int 1469video_dequeue_buf(struct video_softc *sc, struct v4l2_buffer *buf) 1470{ 1471 struct video_stream *vs = &sc->sc_stream_in; 1472 struct video_buffer *vb; 1473 int err; 1474 1475 if (buf->type != vs->vs_type) { 1476 aprint_debug_dev(sc->sc_dev, 1477 "requested type %d (expected %d)\n", 1478 buf->type, vs->vs_type); 1479 return EINVAL; 1480 } 1481 1482 switch (vs->vs_method) { 1483 case VIDEO_STREAM_METHOD_MMAP: 1484 if (buf->memory != V4L2_MEMORY_MMAP) { 1485 aprint_debug_dev(sc->sc_dev, 1486 "requested memory %d (expected %d)\n", 1487 buf->memory, V4L2_MEMORY_MMAP); 1488 return EINVAL; 1489 } 1490 1491 mutex_enter(&vs->vs_lock); 1492 1493 if (vs->vs_flags & O_NONBLOCK) { 1494 vb = video_stream_dequeue(vs); 1495 if (vb == NULL) { 1496 mutex_exit(&vs->vs_lock); 1497 return EAGAIN; 1498 } 1499 } else { 1500 /* Block until we have sample */ 1501 while ((vb = video_stream_dequeue(vs)) == NULL) { 1502 if (!vs->vs_streaming) { 1503 mutex_exit(&vs->vs_lock); 1504 return EINVAL; 1505 } 1506 err = cv_wait_sig(&vs->vs_sample_cv, 1507 &vs->vs_lock); 1508 if (err != 0) { 1509 mutex_exit(&vs->vs_lock); 1510 return EINTR; 1511 } 1512 } 1513 } 1514 1515 memcpy(buf, vb->vb_buf, sizeof(*buf)); 1516 1517 mutex_exit(&vs->vs_lock); 1518 break; 1519 default: 1520 aprint_debug_dev(sc->sc_dev, "unknown vs_method %d\n", 1521 vs->vs_method); 1522 return EINVAL; 1523 } 1524 1525 return 0; 1526} 1527 1528static int 1529video_stream_on(struct video_softc *sc, enum v4l2_buf_type type) 1530{ 1531 int err; 1532 struct video_stream *vs = &sc->sc_stream_in; 1533 const struct video_hw_if *hw; 1534 1535 if (vs->vs_streaming) 1536 return 0; 1537 if (type != vs->vs_type) 1538 return EINVAL; 1539 1540 hw = sc->hw_if; 1541 if (hw == NULL) 1542 return ENXIO; 1543 1544 1545 err = hw->start_transfer(sc->hw_softc); 1546 if (err != 0) 1547 return err; 1548 1549 vs->vs_streaming = true; 1550 return 0; 1551} 1552 1553static int 1554video_stream_off(struct video_softc *sc, enum v4l2_buf_type type) 1555{ 1556 int err; 1557 struct video_stream *vs = &sc->sc_stream_in; 1558 const struct video_hw_if *hw; 1559 1560 if (!vs->vs_streaming) 1561 return 0; 1562 if (type != vs->vs_type) 1563 return EINVAL; 1564 1565 hw = sc->hw_if; 1566 if (hw == NULL) 1567 return ENXIO; 1568 1569 err = hw->stop_transfer(sc->hw_softc); 1570 if (err != 0) 1571 return err; 1572 1573 vs->vs_frameno = -1; 1574 vs->vs_sequence = 0; 1575 vs->vs_streaming = false; 1576 1577 return 0; 1578} 1579 1580int 1581videoopen(dev_t dev, int flags, int ifmt, struct lwp *l) 1582{ 1583 struct video_softc *sc; 1584 const struct video_hw_if *hw; 1585 struct video_stream *vs; 1586 int err; 1587 1588 DPRINTF(("videoopen\n")); 1589 1590 sc = device_private(device_lookup(&video_cd, VIDEOUNIT(dev))); 1591 if (sc == NULL) { 1592 DPRINTF(("videoopen: failed to get softc\n")); 1593 return ENXIO; 1594 } 1595 1596 if (sc->sc_dying) { 1597 DPRINTF(("videoopen: dying\n")); 1598 return EIO; 1599 } 1600 1601 sc->sc_stream_in.vs_flags = flags; 1602 1603 DPRINTF(("videoopen: flags=0x%x sc=%p parent=%p\n", 1604 flags, sc, sc->hw_dev)); 1605 1606 hw = sc->hw_if; 1607 if (hw == NULL) 1608 return ENXIO; 1609 1610 device_active(sc->sc_dev, DVA_SYSTEM); 1611 1612 sc->sc_opencnt++; 1613 1614 if (hw->open != NULL) { 1615 err = hw->open(sc->hw_softc, flags); 1616 if (err) 1617 return err; 1618 } 1619 1620 /* set up input stream. TODO: check flags to determine if 1621 * "read" is desired? */ 1622 vs = &sc->sc_stream_in; 1623 1624 if (hw->get_format != NULL) { 1625 err = hw->get_format(sc->hw_softc, &vs->vs_format); 1626 if (err != 0) 1627 return err; 1628 } 1629 return 0; 1630} 1631 1632 1633int 1634videoclose(dev_t dev, int flags, int ifmt, struct lwp *l) 1635{ 1636 struct video_softc *sc; 1637 const struct video_hw_if *hw; 1638 1639 sc = device_private(device_lookup(&video_cd, VIDEOUNIT(dev))); 1640 if (sc == NULL) 1641 return ENXIO; 1642 1643 DPRINTF(("videoclose: sc=%p\n", sc)); 1644 1645 hw = sc->hw_if; 1646 if (hw == NULL) 1647 return ENXIO; 1648 1649 device_active(sc->sc_dev, DVA_SYSTEM); 1650 1651 video_stream_off(sc, sc->sc_stream_in.vs_type); 1652 1653 /* ignore error */ 1654 if (hw->close != NULL) 1655 hw->close(sc->hw_softc); 1656 1657 video_stream_teardown_bufs(&sc->sc_stream_in); 1658 1659 sc->sc_open = 0; 1660 sc->sc_opencnt--; 1661 1662 return 0; 1663} 1664 1665 1666int 1667videoread(dev_t dev, struct uio *uio, int ioflag) 1668{ 1669 struct video_softc *sc; 1670 struct video_stream *vs; 1671 struct video_buffer *vb; 1672 struct scatter_io sio; 1673 int err; 1674 size_t len; 1675 off_t offset; 1676 1677 sc = device_private(device_lookup(&video_cd, VIDEOUNIT(dev))); 1678 if (sc == NULL) 1679 return ENXIO; 1680 1681 if (sc->sc_dying) 1682 return EIO; 1683 1684 vs = &sc->sc_stream_in; 1685 1686 /* userspace has chosen read() method */ 1687 if (vs->vs_method == VIDEO_STREAM_METHOD_NONE) { 1688 err = video_stream_setup_bufs(vs, 1689 VIDEO_STREAM_METHOD_READ, 1690 VIDEO_NUM_BUFS); 1691 if (err != 0) 1692 return err; 1693 1694 err = video_stream_on(sc, vs->vs_type); 1695 if (err != 0) 1696 return err; 1697 } else if (vs->vs_method != VIDEO_STREAM_METHOD_READ) { 1698 return EBUSY; 1699 } 1700 1701 mutex_enter(&vs->vs_lock); 1702 1703retry: 1704 if (SIMPLEQ_EMPTY(&vs->vs_egress)) { 1705 if (vs->vs_flags & O_NONBLOCK) { 1706 mutex_exit(&vs->vs_lock); 1707 return EAGAIN; 1708 } 1709 1710 /* Block until we have a sample */ 1711 while (SIMPLEQ_EMPTY(&vs->vs_egress)) { 1712 err = cv_wait_sig(&vs->vs_sample_cv, 1713 &vs->vs_lock); 1714 if (err != 0) { 1715 mutex_exit(&vs->vs_lock); 1716 return EINTR; 1717 } 1718 } 1719 1720 vb = SIMPLEQ_FIRST(&vs->vs_egress); 1721 } else { 1722 vb = SIMPLEQ_FIRST(&vs->vs_egress); 1723 } 1724 1725 /* Oops, empty sample buffer. */ 1726 if (vb->vb_buf->bytesused == 0) { 1727 vb = video_stream_dequeue(vs); 1728 video_stream_enqueue(vs, vb); 1729 vs->vs_bytesread = 0; 1730 goto retry; 1731 } 1732 1733 mutex_exit(&vs->vs_lock); 1734 1735 len = min(uio->uio_resid, vb->vb_buf->bytesused - vs->vs_bytesread); 1736 offset = vb->vb_buf->m.offset + vs->vs_bytesread; 1737 1738 if (scatter_io_init(&vs->vs_data, offset, len, &sio)) { 1739 err = scatter_io_uiomove(&sio, uio); 1740 if (err == EFAULT) 1741 return EFAULT; 1742 vs->vs_bytesread += (len - sio.sio_resid); 1743 } else { 1744 DPRINTF(("video: invalid read\n")); 1745 } 1746 1747 /* Move the sample to the ingress queue if everything has 1748 * been read */ 1749 if (vs->vs_bytesread >= vb->vb_buf->bytesused) { 1750 mutex_enter(&vs->vs_lock); 1751 vb = video_stream_dequeue(vs); 1752 video_stream_enqueue(vs, vb); 1753 mutex_exit(&vs->vs_lock); 1754 1755 vs->vs_bytesread = 0; 1756 } 1757 1758 return 0; 1759} 1760 1761 1762int 1763videowrite(dev_t dev, struct uio *uio, int ioflag) 1764{ 1765 return ENXIO; 1766} 1767 1768 1769static void 1770buf32tobuf(const void *data, struct v4l2_buffer *buf) 1771{ 1772 const struct v4l2_buffer32 *b32 = data; 1773 1774 buf->index = b32->index; 1775 buf->type = b32->type; 1776 buf->bytesused = b32->bytesused; 1777 buf->flags = b32->flags; 1778 buf->field = b32->field; 1779 buf->timestamp.tv_sec = b32->timestamp.tv_sec; 1780 buf->timestamp.tv_usec = b32->timestamp.tv_usec; 1781 buf->timecode = b32->timecode; 1782 buf->sequence = b32->sequence; 1783 buf->memory = b32->memory; 1784 buf->m.offset = b32->m.offset; 1785 /* XXX: Handle userptr */ 1786 buf->length = b32->length; 1787 buf->input = b32->input; 1788 buf->reserved = b32->reserved; 1789} 1790 1791static void 1792buftobuf32(void *data, const struct v4l2_buffer *buf) 1793{ 1794 struct v4l2_buffer32 *b32 = data; 1795 1796 b32->index = buf->index; 1797 b32->type = buf->type; 1798 b32->bytesused = buf->bytesused; 1799 b32->flags = buf->flags; 1800 b32->field = buf->field; 1801 b32->timestamp.tv_sec = (uint32_t)buf->timestamp.tv_sec; 1802 b32->timestamp.tv_usec = buf->timestamp.tv_usec; 1803 b32->timecode = buf->timecode; 1804 b32->sequence = buf->sequence; 1805 b32->memory = buf->memory; 1806 b32->m.offset = buf->m.offset; 1807 /* XXX: Handle userptr */ 1808 b32->length = buf->length; 1809 b32->input = buf->input; 1810 b32->reserved = buf->reserved; 1811} 1812 1813int 1814videoioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 1815{ 1816 struct video_softc *sc; 1817 const struct video_hw_if *hw; 1818 struct v4l2_capability *cap; 1819 struct v4l2_fmtdesc *fmtdesc; 1820 struct v4l2_format *fmt; 1821 struct v4l2_standard *std; 1822 struct v4l2_input *input; 1823 struct v4l2_audio *audio; 1824 struct v4l2_tuner *tuner; 1825 struct v4l2_frequency *freq; 1826 struct v4l2_control *control; 1827 struct v4l2_queryctrl *query; 1828 struct v4l2_requestbuffers *reqbufs; 1829 struct v4l2_buffer *buf, bufspace; 1830 v4l2_std_id *stdid; 1831 enum v4l2_buf_type *typep; 1832 int *ip, error; 1833 1834 sc = device_private(device_lookup(&video_cd, VIDEOUNIT(dev))); 1835 1836 if (sc->sc_dying) 1837 return EIO; 1838 1839 hw = sc->hw_if; 1840 if (hw == NULL) 1841 return ENXIO; 1842 1843 switch (cmd) { 1844 case VIDIOC_QUERYCAP: 1845 cap = data; 1846 memset(cap, 0, sizeof(*cap)); 1847 strlcpy(cap->driver, device_xname(sc->hw_dev), 1848 sizeof(cap->driver)); 1849 strlcpy(cap->card, hw->get_devname(sc->hw_softc), 1850 sizeof(cap->card)); 1851 /* FIXME: bus_info is wrongly hardcoded to USB */ 1852 strlcpy(cap->bus_info, "USB", sizeof(cap->bus_info)); 1853 cap->version = VIDEO_DRIVER_VERSION; 1854 cap->capabilities = 0; 1855 if (hw->start_transfer != NULL && hw->stop_transfer != NULL) 1856 cap->capabilities |= V4L2_CAP_VIDEO_CAPTURE | 1857 V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; 1858 if (hw->set_tuner != NULL && hw->get_tuner != NULL) 1859 cap->capabilities |= V4L2_CAP_TUNER; 1860 if (hw->set_audio != NULL && hw->get_audio != NULL && 1861 hw->enum_audio != NULL) 1862 cap->capabilities |= V4L2_CAP_AUDIO; 1863 return 0; 1864 case VIDIOC_ENUM_FMT: 1865 /* TODO: for now, just enumerate one default format */ 1866 fmtdesc = data; 1867 if (fmtdesc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1868 return EINVAL; 1869 return video_enum_format(sc, fmtdesc); 1870 case VIDIOC_G_FMT: 1871 fmt = data; 1872 return video_get_format(sc, fmt); 1873 case VIDIOC_S_FMT: 1874 fmt = data; 1875 if ((flag & FWRITE) == 0) 1876 return EPERM; 1877 return video_set_format(sc, fmt); 1878 case VIDIOC_TRY_FMT: 1879 fmt = data; 1880 return video_try_format(sc, fmt); 1881 case VIDIOC_ENUMSTD: 1882 std = data; 1883 return video_enum_standard(sc, std); 1884 case VIDIOC_G_STD: 1885 stdid = data; 1886 return video_get_standard(sc, stdid); 1887 case VIDIOC_S_STD: 1888 stdid = data; 1889 if ((flag & FWRITE) == 0) 1890 return EPERM; 1891 return video_set_standard(sc, *stdid); 1892 case VIDIOC_ENUMINPUT: 1893 input = data; 1894 return video_enum_input(sc, input); 1895 case VIDIOC_G_INPUT: 1896 ip = data; 1897 return video_get_input(sc, ip); 1898 case VIDIOC_S_INPUT: 1899 ip = data; 1900 if ((flag & FWRITE) == 0) 1901 return EPERM; 1902 return video_set_input(sc, *ip); 1903 case VIDIOC_ENUMAUDIO: 1904 audio = data; 1905 return video_enum_audio(sc, audio); 1906 case VIDIOC_G_AUDIO: 1907 audio = data; 1908 return video_get_audio(sc, audio); 1909 case VIDIOC_S_AUDIO: 1910 audio = data; 1911 if ((flag & FWRITE) == 0) 1912 return EPERM; 1913 return video_set_audio(sc, audio); 1914 case VIDIOC_G_TUNER: 1915 tuner = data; 1916 return video_get_tuner(sc, tuner); 1917 case VIDIOC_S_TUNER: 1918 tuner = data; 1919 if ((flag & FWRITE) == 0) 1920 return EPERM; 1921 return video_set_tuner(sc, tuner); 1922 case VIDIOC_G_FREQUENCY: 1923 freq = data; 1924 return video_get_frequency(sc, freq); 1925 case VIDIOC_S_FREQUENCY: 1926 freq = data; 1927 if ((flag & FWRITE) == 0) 1928 return EPERM; 1929 return video_set_frequency(sc, freq); 1930 case VIDIOC_QUERYCTRL: 1931 query = data; 1932 return (video_query_control(sc, query)); 1933 case VIDIOC_G_CTRL: 1934 control = data; 1935 return (video_get_control(sc, control)); 1936 case VIDIOC_S_CTRL: 1937 control = data; 1938 if ((flag & FWRITE) == 0) 1939 return EPERM; 1940 return (video_set_control(sc, control)); 1941 case VIDIOC_REQBUFS: 1942 reqbufs = data; 1943 return (video_request_bufs(sc, reqbufs)); 1944 case VIDIOC_QUERYBUF: 1945 buf = data; 1946 return video_query_buf(sc, buf); 1947 case VIDIOC_QUERYBUF32: 1948 buf32tobuf(data, buf = &bufspace); 1949 if ((error = video_query_buf(sc, buf)) != 0) 1950 return error; 1951 buftobuf32(data, buf); 1952 return 0; 1953 case VIDIOC_QBUF: 1954 buf = data; 1955 return video_queue_buf(sc, buf); 1956 case VIDIOC_QBUF32: 1957 buf32tobuf(data, buf = &bufspace); 1958 return video_queue_buf(sc, buf); 1959 case VIDIOC_DQBUF: 1960 buf = data; 1961 return video_dequeue_buf(sc, buf); 1962 case VIDIOC_DQBUF32: 1963 buf32tobuf(data, buf = &bufspace); 1964 if ((error = video_dequeue_buf(sc, buf)) != 0) 1965 return error; 1966 buftobuf32(data, buf); 1967 return 0; 1968 case VIDIOC_STREAMON: 1969 typep = data; 1970 return video_stream_on(sc, *typep); 1971 case VIDIOC_STREAMOFF: 1972 typep = data; 1973 return video_stream_off(sc, *typep); 1974 default: 1975 DPRINTF(("videoioctl: invalid cmd %s (%lx)\n", 1976 video_ioctl_str(cmd), cmd)); 1977 return EINVAL; 1978 } 1979} 1980 1981#ifdef VIDEO_DEBUG 1982static const char * 1983video_ioctl_str(u_long cmd) 1984{ 1985 const char *str; 1986 1987 switch (cmd) { 1988 case VIDIOC_QUERYCAP: 1989 str = "VIDIOC_QUERYCAP"; 1990 break; 1991 case VIDIOC_RESERVED: 1992 str = "VIDIOC_RESERVED"; 1993 break; 1994 case VIDIOC_ENUM_FMT: 1995 str = "VIDIOC_ENUM_FMT"; 1996 break; 1997 case VIDIOC_G_FMT: 1998 str = "VIDIOC_G_FMT"; 1999 break; 2000 case VIDIOC_S_FMT: 2001 str = "VIDIOC_S_FMT"; 2002 break; 2003/* 6 and 7 are VIDIOC_[SG]_COMP, which are unsupported */ 2004 case VIDIOC_REQBUFS: 2005 str = "VIDIOC_REQBUFS"; 2006 break; 2007 case VIDIOC_QUERYBUF: 2008 str = "VIDIOC_QUERYBUF"; 2009 break; 2010 case VIDIOC_QUERYBUF32: 2011 str = "VIDIOC_QUERYBUF32"; 2012 break; 2013 case VIDIOC_G_FBUF: 2014 str = "VIDIOC_G_FBUF"; 2015 break; 2016 case VIDIOC_S_FBUF: 2017 str = "VIDIOC_S_FBUF"; 2018 break; 2019 case VIDIOC_OVERLAY: 2020 str = "VIDIOC_OVERLAY"; 2021 break; 2022 case VIDIOC_QBUF: 2023 str = "VIDIOC_QBUF"; 2024 break; 2025 case VIDIOC_QBUF32: 2026 str = "VIDIOC_QBUF32"; 2027 break; 2028 case VIDIOC_DQBUF: 2029 str = "VIDIOC_DQBUF"; 2030 break; 2031 case VIDIOC_DQBUF32: 2032 str = "VIDIOC_DQBUF32"; 2033 break; 2034 case VIDIOC_STREAMON: 2035 str = "VIDIOC_STREAMON"; 2036 break; 2037 case VIDIOC_STREAMOFF: 2038 str = "VIDIOC_STREAMOFF"; 2039 break; 2040 case VIDIOC_G_PARM: 2041 str = "VIDIOC_G_PARAM"; 2042 break; 2043 case VIDIOC_S_PARM: 2044 str = "VIDIOC_S_PARAM"; 2045 break; 2046 case VIDIOC_G_STD: 2047 str = "VIDIOC_G_STD"; 2048 break; 2049 case VIDIOC_S_STD: 2050 str = "VIDIOC_S_STD"; 2051 break; 2052 case VIDIOC_ENUMSTD: 2053 str = "VIDIOC_ENUMSTD"; 2054 break; 2055 case VIDIOC_ENUMINPUT: 2056 str = "VIDIOC_ENUMINPUT"; 2057 break; 2058 case VIDIOC_G_CTRL: 2059 str = "VIDIOC_G_CTRL"; 2060 break; 2061 case VIDIOC_S_CTRL: 2062 str = "VIDIOC_S_CTRL"; 2063 break; 2064 case VIDIOC_G_TUNER: 2065 str = "VIDIOC_G_TUNER"; 2066 break; 2067 case VIDIOC_S_TUNER: 2068 str = "VIDIOC_S_TUNER"; 2069 break; 2070 case VIDIOC_G_AUDIO: 2071 str = "VIDIOC_G_AUDIO"; 2072 break; 2073 case VIDIOC_S_AUDIO: 2074 str = "VIDIOC_S_AUDIO"; 2075 break; 2076 case VIDIOC_QUERYCTRL: 2077 str = "VIDIOC_QUERYCTRL"; 2078 break; 2079 case VIDIOC_QUERYMENU: 2080 str = "VIDIOC_QUERYMENU"; 2081 break; 2082 case VIDIOC_G_INPUT: 2083 str = "VIDIOC_G_INPUT"; 2084 break; 2085 case VIDIOC_S_INPUT: 2086 str = "VIDIOC_S_INPUT"; 2087 break; 2088 case VIDIOC_G_OUTPUT: 2089 str = "VIDIOC_G_OUTPUT"; 2090 break; 2091 case VIDIOC_S_OUTPUT: 2092 str = "VIDIOC_S_OUTPUT"; 2093 break; 2094 case VIDIOC_ENUMOUTPUT: 2095 str = "VIDIOC_ENUMOUTPUT"; 2096 break; 2097 case VIDIOC_G_AUDOUT: 2098 str = "VIDIOC_G_AUDOUT"; 2099 break; 2100 case VIDIOC_S_AUDOUT: 2101 str = "VIDIOC_S_AUDOUT"; 2102 break; 2103 case VIDIOC_G_MODULATOR: 2104 str = "VIDIOC_G_MODULATOR"; 2105 break; 2106 case VIDIOC_S_MODULATOR: 2107 str = "VIDIOC_S_MODULATOR"; 2108 break; 2109 case VIDIOC_G_FREQUENCY: 2110 str = "VIDIOC_G_FREQUENCY"; 2111 break; 2112 case VIDIOC_S_FREQUENCY: 2113 str = "VIDIOC_S_FREQUENCY"; 2114 break; 2115 case VIDIOC_CROPCAP: 2116 str = "VIDIOC_CROPCAP"; 2117 break; 2118 case VIDIOC_G_CROP: 2119 str = "VIDIOC_G_CROP"; 2120 break; 2121 case VIDIOC_S_CROP: 2122 str = "VIDIOC_S_CROP"; 2123 break; 2124 case VIDIOC_G_JPEGCOMP: 2125 str = "VIDIOC_G_JPEGCOMP"; 2126 break; 2127 case VIDIOC_S_JPEGCOMP: 2128 str = "VIDIOC_S_JPEGCOMP"; 2129 break; 2130 case VIDIOC_QUERYSTD: 2131 str = "VIDIOC_QUERYSTD"; 2132 break; 2133 case VIDIOC_TRY_FMT: 2134 str = "VIDIOC_TRY_FMT"; 2135 break; 2136 case VIDIOC_ENUMAUDIO: 2137 str = "VIDIOC_ENUMAUDIO"; 2138 break; 2139 case VIDIOC_ENUMAUDOUT: 2140 str = "VIDIOC_ENUMAUDOUT"; 2141 break; 2142 case VIDIOC_G_PRIORITY: 2143 str = "VIDIOC_G_PRIORITY"; 2144 break; 2145 case VIDIOC_S_PRIORITY: 2146 str = "VIDIOC_S_PRIORITY"; 2147 break; 2148 default: 2149 str = "unknown"; 2150 break; 2151 } 2152 return str; 2153} 2154#endif 2155 2156 2157int 2158videopoll(dev_t dev, int events, struct lwp *l) 2159{ 2160 struct video_softc *sc; 2161 struct video_stream *vs; 2162 int err, revents = 0; 2163 2164 sc = device_private(device_lookup(&video_cd, VIDEOUNIT(dev))); 2165 vs = &sc->sc_stream_in; 2166 2167 if (sc->sc_dying) 2168 return (POLLHUP); 2169 2170 /* userspace has chosen read() method */ 2171 if (vs->vs_method == VIDEO_STREAM_METHOD_NONE) { 2172 err = video_stream_setup_bufs(vs, 2173 VIDEO_STREAM_METHOD_READ, 2174 VIDEO_NUM_BUFS); 2175 if (err != 0) 2176 return POLLERR; 2177 2178 err = video_stream_on(sc, vs->vs_type); 2179 if (err != 0) 2180 return POLLERR; 2181 } 2182 2183 mutex_enter(&vs->vs_lock); 2184 if (!SIMPLEQ_EMPTY(&sc->sc_stream_in.vs_egress)) 2185 revents |= events & (POLLIN | POLLRDNORM); 2186 else 2187 selrecord(l, &vs->vs_sel); 2188 mutex_exit(&vs->vs_lock); 2189 2190 return (revents); 2191} 2192 2193 2194paddr_t 2195videommap(dev_t dev, off_t off, int prot) 2196{ 2197 struct video_softc *sc; 2198 struct video_stream *vs; 2199 /* paddr_t pa; */ 2200 2201 sc = device_lookup_private(&video_cd, VIDEOUNIT(dev)); 2202 if (sc->sc_dying) 2203 return -1; 2204 2205 vs = &sc->sc_stream_in; 2206 2207 return scatter_buf_map(&vs->vs_data, off); 2208} 2209 2210 2211/* Allocates buffers and initizlizes some fields. The format field 2212 * must already have been initialized. */ 2213void 2214video_stream_init(struct video_stream *vs) 2215{ 2216 vs->vs_method = VIDEO_STREAM_METHOD_NONE; 2217 vs->vs_flags = 0; 2218 vs->vs_frameno = -1; 2219 vs->vs_sequence = 0; 2220 vs->vs_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2221 vs->vs_nbufs = 0; 2222 vs->vs_buf = NULL; 2223 vs->vs_streaming = false; 2224 2225 memset(&vs->vs_format, 0, sizeof(vs->vs_format)); 2226 2227 SIMPLEQ_INIT(&vs->vs_ingress); 2228 SIMPLEQ_INIT(&vs->vs_egress); 2229 2230 mutex_init(&vs->vs_lock, MUTEX_DEFAULT, IPL_NONE); 2231 cv_init(&vs->vs_sample_cv, "video"); 2232 selinit(&vs->vs_sel); 2233 2234 scatter_buf_init(&vs->vs_data); 2235} 2236 2237void 2238video_stream_fini(struct video_stream *vs) 2239{ 2240 /* Sample data in queues has already been freed */ 2241 /* while (SIMPLEQ_FIRST(&vs->vs_ingress) != NULL) 2242 SIMPLEQ_REMOVE_HEAD(&vs->vs_ingress, entries); 2243 while (SIMPLEQ_FIRST(&vs->vs_egress) != NULL) 2244 SIMPLEQ_REMOVE_HEAD(&vs->vs_egress, entries); */ 2245 2246 mutex_destroy(&vs->vs_lock); 2247 cv_destroy(&vs->vs_sample_cv); 2248 seldestroy(&vs->vs_sel); 2249 2250 scatter_buf_destroy(&vs->vs_data); 2251} 2252 2253static int 2254video_stream_setup_bufs(struct video_stream *vs, 2255 enum video_stream_method method, 2256 uint8_t nbufs) 2257{ 2258 int i, err; 2259 2260 mutex_enter(&vs->vs_lock); 2261 2262 /* Ensure that all allocated buffers are queued and not under 2263 * userspace control. */ 2264 for (i = 0; i < vs->vs_nbufs; ++i) { 2265 if (!(vs->vs_buf[i]->vb_buf->flags & V4L2_BUF_FLAG_QUEUED)) { 2266 mutex_exit(&vs->vs_lock); 2267 return EBUSY; 2268 } 2269 } 2270 2271 /* Allocate the buffers */ 2272 err = video_stream_realloc_bufs(vs, nbufs); 2273 if (err != 0) { 2274 mutex_exit(&vs->vs_lock); 2275 return err; 2276 } 2277 2278 /* Queue up buffers for read method. Other methods are queued 2279 * by VIDIOC_QBUF ioctl. */ 2280 if (method == VIDEO_STREAM_METHOD_READ) { 2281 for (i = 0; i < nbufs; ++i) 2282 if (!(vs->vs_buf[i]->vb_buf->flags & V4L2_BUF_FLAG_QUEUED)) 2283 video_stream_enqueue(vs, vs->vs_buf[i]); 2284 } 2285 2286 vs->vs_method = method; 2287 mutex_exit(&vs->vs_lock); 2288 2289 return 0; 2290} 2291 2292/* Free all buffer memory in preparation for close(). This should 2293 * free buffers regardless of errors. Use video_stream_setup_bufs if 2294 * you need to check for errors. Streaming should be off before 2295 * calling this function. */ 2296static void 2297video_stream_teardown_bufs(struct video_stream *vs) 2298{ 2299 int err; 2300 2301 mutex_enter(&vs->vs_lock); 2302 2303 if (vs->vs_streaming) { 2304 DPRINTF(("video_stream_teardown_bufs: " 2305 "tearing down bufs while streaming\n")); 2306 } 2307 2308 /* dequeue all buffers */ 2309 while (SIMPLEQ_FIRST(&vs->vs_ingress) != NULL) 2310 SIMPLEQ_REMOVE_HEAD(&vs->vs_ingress, entries); 2311 while (SIMPLEQ_FIRST(&vs->vs_egress) != NULL) 2312 SIMPLEQ_REMOVE_HEAD(&vs->vs_egress, entries); 2313 2314 err = video_stream_free_bufs(vs); 2315 if (err != 0) { 2316 DPRINTF(("video_stream_teardown_bufs: " 2317 "error releasing buffers: %d\n", 2318 err)); 2319 } 2320 vs->vs_method = VIDEO_STREAM_METHOD_NONE; 2321 2322 mutex_exit(&vs->vs_lock); 2323} 2324 2325static struct video_buffer * 2326video_buffer_alloc(void) 2327{ 2328 struct video_buffer *vb; 2329 2330 vb = kmem_alloc(sizeof(*vb), KM_SLEEP); 2331 if (vb == NULL) 2332 return NULL; 2333 2334 vb->vb_buf = kmem_alloc(sizeof(*vb->vb_buf), KM_SLEEP); 2335 if (vb->vb_buf == NULL) { 2336 kmem_free(vb, sizeof(*vb)); 2337 return NULL; 2338 } 2339 2340 return vb; 2341} 2342 2343static void 2344video_buffer_free(struct video_buffer *vb) 2345{ 2346 kmem_free(vb->vb_buf, sizeof(*vb->vb_buf)); 2347 vb->vb_buf = NULL; 2348 kmem_free(vb, sizeof(*vb)); 2349} 2350 2351/* TODO: for userptr method 2352struct video_buffer * 2353video_buf_alloc_with_ubuf(struct v4l2_buffer *buf) 2354{ 2355} 2356 2357void 2358video_buffer_free_with_ubuf(struct video_buffer *vb) 2359{ 2360} 2361*/ 2362 2363static int 2364video_stream_realloc_bufs(struct video_stream *vs, uint8_t nbufs) 2365{ 2366 int i, err; 2367 uint8_t minnbufs, oldnbufs; 2368 size_t size; 2369 off_t offset; 2370 struct video_buffer **oldbuf; 2371 struct v4l2_buffer *buf; 2372 2373 size = PAGE_ALIGN(vs->vs_format.sample_size) * nbufs; 2374 err = scatter_buf_set_size(&vs->vs_data, size); 2375 if (err != 0) 2376 return err; 2377 2378 oldnbufs = vs->vs_nbufs; 2379 oldbuf = vs->vs_buf; 2380 2381 vs->vs_nbufs = nbufs; 2382 if (nbufs > 0) { 2383 vs->vs_buf = 2384 kmem_alloc(sizeof(struct video_buffer *) * nbufs, KM_SLEEP); 2385 if (vs->vs_buf == NULL) { 2386 vs->vs_nbufs = oldnbufs; 2387 vs->vs_buf = oldbuf; 2388 2389 return ENOMEM; 2390 } 2391 } else { 2392 vs->vs_buf = NULL; 2393 } 2394 2395 minnbufs = min(vs->vs_nbufs, oldnbufs); 2396 /* copy any bufs that will be reused */ 2397 for (i = 0; i < minnbufs; ++i) 2398 vs->vs_buf[i] = oldbuf[i]; 2399 /* allocate any necessary new bufs */ 2400 for (; i < vs->vs_nbufs; ++i) 2401 vs->vs_buf[i] = video_buffer_alloc(); 2402 /* free any bufs no longer used */ 2403 for (; i < oldnbufs; ++i) { 2404 video_buffer_free(oldbuf[i]); 2405 oldbuf[i] = NULL; 2406 } 2407 2408 /* Free old buffer metadata */ 2409 if (oldbuf != NULL) 2410 kmem_free(oldbuf, sizeof(struct video_buffer *) * oldnbufs); 2411 2412 /* initialize bufs */ 2413 offset = 0; 2414 for (i = 0; i < vs->vs_nbufs; ++i) { 2415 buf = vs->vs_buf[i]->vb_buf; 2416 buf->index = i; 2417 buf->type = vs->vs_type; 2418 buf->bytesused = 0; 2419 buf->flags = 0; 2420 buf->field = 0; 2421 buf->sequence = 0; 2422 buf->memory = V4L2_MEMORY_MMAP; 2423 buf->m.offset = offset; 2424 buf->length = PAGE_ALIGN(vs->vs_format.sample_size); 2425 buf->input = 0; 2426 buf->reserved = 0; 2427 2428 offset += buf->length; 2429 } 2430 2431 return 0; 2432} 2433 2434/* Accepts a video_sample into the ingress queue. Caller must hold 2435 * the stream lock. */ 2436void 2437video_stream_enqueue(struct video_stream *vs, struct video_buffer *vb) 2438{ 2439 if (vb->vb_buf->flags & V4L2_BUF_FLAG_QUEUED) { 2440 DPRINTF(("video_stream_enqueue: sample already queued\n")); 2441 return; 2442 } 2443 2444 vb->vb_buf->flags |= V4L2_BUF_FLAG_QUEUED; 2445 vb->vb_buf->flags &= ~V4L2_BUF_FLAG_DONE; 2446 2447 vb->vb_buf->bytesused = 0; 2448 2449 SIMPLEQ_INSERT_TAIL(&vs->vs_ingress, vb, entries); 2450} 2451 2452 2453/* Removes the head of the egress queue for use by userspace. Caller 2454 * must hold the stream lock. */ 2455struct video_buffer * 2456video_stream_dequeue(struct video_stream *vs) 2457{ 2458 struct video_buffer *vb; 2459 2460 if (!SIMPLEQ_EMPTY(&vs->vs_egress)) { 2461 vb = SIMPLEQ_FIRST(&vs->vs_egress); 2462 SIMPLEQ_REMOVE_HEAD(&vs->vs_egress, entries); 2463 vb->vb_buf->flags &= ~V4L2_BUF_FLAG_QUEUED; 2464 vb->vb_buf->flags |= V4L2_BUF_FLAG_DONE; 2465 return vb; 2466 } else { 2467 return NULL; 2468 } 2469} 2470 2471 2472/* 2473 * write payload data to the appropriate video sample, possibly moving 2474 * the sample from ingress to egress queues 2475 */ 2476void 2477video_stream_write(struct video_stream *vs, 2478 const struct video_payload *payload) 2479{ 2480 struct video_buffer *vb; 2481 struct v4l2_buffer *buf; 2482 struct scatter_io sio; 2483 2484 mutex_enter(&vs->vs_lock); 2485 2486 /* change of frameno implies end of current frame */ 2487 if (vs->vs_frameno >= 0 && vs->vs_frameno != payload->frameno) 2488 video_stream_sample_done(vs); 2489 2490 vs->vs_frameno = payload->frameno; 2491 2492 if (vs->vs_drop || SIMPLEQ_EMPTY(&vs->vs_ingress)) { 2493 /* DPRINTF(("video_stream_write: dropping sample %d\n", 2494 vs->vs_sequence)); */ 2495 vs->vs_drop = true; 2496 } else if (payload->size > 0) { 2497 vb = SIMPLEQ_FIRST(&vs->vs_ingress); 2498 buf = vb->vb_buf; 2499 if (payload->size > buf->length - buf->bytesused) { 2500 DPRINTF(("video_stream_write: " 2501 "payload would overflow\n")); 2502 } else if (scatter_io_init(&vs->vs_data, 2503 buf->m.offset + buf->bytesused, 2504 payload->size, 2505 &sio)) 2506 { 2507 scatter_io_copyin(&sio, payload->data); 2508 buf->bytesused += (payload->size - sio.sio_resid); 2509 } else { 2510 DPRINTF(("video_stream_write: failed to init scatter io " 2511 "vb=%p buf=%p " 2512 "buf->m.offset=%d buf->bytesused=%u " 2513 "payload->size=%zu\n", 2514 vb, buf, 2515 buf->m.offset, buf->bytesused, payload->size)); 2516 } 2517 } 2518 2519 /* if the payload marks it, we can do sample_done() early */ 2520 if (payload->end_of_frame) 2521 video_stream_sample_done(vs); 2522 2523 mutex_exit(&vs->vs_lock); 2524} 2525 2526 2527/* Moves the head of the ingress queue to the tail of the egress 2528 * queue, or resets drop status if we were dropping this sample. 2529 * Caller should hold the stream queue lock. */ 2530void 2531video_stream_sample_done(struct video_stream *vs) 2532{ 2533 struct video_buffer *vb; 2534 2535 if (vs->vs_drop) { 2536 vs->vs_drop = false; 2537 } else if (!SIMPLEQ_EMPTY(&vs->vs_ingress)) { 2538 vb = SIMPLEQ_FIRST(&vs->vs_ingress); 2539 vb->vb_buf->sequence = vs->vs_sequence; 2540 SIMPLEQ_REMOVE_HEAD(&vs->vs_ingress, entries); 2541 2542 SIMPLEQ_INSERT_TAIL(&vs->vs_egress, vb, entries); 2543 cv_signal(&vs->vs_sample_cv); 2544 selnotify(&vs->vs_sel, 0, 0); 2545 } else { 2546 DPRINTF(("video_stream_sample_done: no sample\n")); 2547 } 2548 2549 vs->vs_frameno ^= 1; 2550 vs->vs_sequence++; 2551} 2552 2553/* Check if all buffers are queued, i.e. none are under control of 2554 * userspace. */ 2555/* 2556static bool 2557video_stream_all_queued(struct video_stream *vs) 2558{ 2559} 2560*/ 2561 2562 2563static void 2564scatter_buf_init(struct scatter_buf *sb) 2565{ 2566 sb->sb_pool = pool_cache_init(PAGE_SIZE, 0, 0, 0, 2567 "video", NULL, IPL_VIDEO, 2568 NULL, NULL, NULL); 2569 sb->sb_size = 0; 2570 sb->sb_npages = 0; 2571 sb->sb_page_ary = NULL; 2572} 2573 2574static void 2575scatter_buf_destroy(struct scatter_buf *sb) 2576{ 2577 /* Do we need to return everything to the pool first? */ 2578 scatter_buf_set_size(sb, 0); 2579 pool_cache_destroy(sb->sb_pool); 2580 sb->sb_pool = 0; 2581 sb->sb_npages = 0; 2582 sb->sb_page_ary = NULL; 2583} 2584 2585/* Increase or decrease the size of the buffer */ 2586static int 2587scatter_buf_set_size(struct scatter_buf *sb, size_t sz) 2588{ 2589 int i; 2590 size_t npages, minpages, oldnpages; 2591 uint8_t **old_ary; 2592 2593 npages = (sz >> PAGE_SHIFT) + ((sz & PAGE_MASK) > 0); 2594 2595 if (sb->sb_npages == npages) { 2596 return 0; 2597 } 2598 2599 oldnpages = sb->sb_npages; 2600 old_ary = sb->sb_page_ary; 2601 2602 sb->sb_npages = npages; 2603 if (npages > 0) { 2604 sb->sb_page_ary = 2605 kmem_alloc(sizeof(uint8_t *) * npages, KM_SLEEP); 2606 if (sb->sb_page_ary == NULL) { 2607 sb->sb_npages = oldnpages; 2608 sb->sb_page_ary = old_ary; 2609 return ENOMEM; 2610 } 2611 } else { 2612 sb->sb_page_ary = NULL; 2613 } 2614 2615 minpages = min(npages, oldnpages); 2616 /* copy any pages that will be reused */ 2617 for (i = 0; i < minpages; ++i) 2618 sb->sb_page_ary[i] = old_ary[i]; 2619 /* allocate any new pages */ 2620 for (; i < npages; ++i) { 2621 sb->sb_page_ary[i] = pool_cache_get(sb->sb_pool, 0); 2622 /* TODO: does pool_cache_get return NULL on 2623 * ENOMEM? If so, we need to release or note 2624 * the pages with did allocate 2625 * successfully. */ 2626 if (sb->sb_page_ary[i] == NULL) { 2627 DPRINTF(("video: pool_cache_get ENOMEM\n")); 2628 return ENOMEM; 2629 } 2630 } 2631 /* return any pages no longer needed */ 2632 for (; i < oldnpages; ++i) 2633 pool_cache_put(sb->sb_pool, old_ary[i]); 2634 2635 if (old_ary != NULL) 2636 kmem_free(old_ary, sizeof(uint8_t *) * oldnpages); 2637 2638 sb->sb_size = sb->sb_npages << PAGE_SHIFT; 2639 2640 return 0; 2641} 2642 2643 2644static paddr_t 2645scatter_buf_map(struct scatter_buf *sb, off_t off) 2646{ 2647 size_t pg; 2648 paddr_t pa; 2649 2650 pg = off >> PAGE_SHIFT; 2651 2652 if (pg >= sb->sb_npages) 2653 return -1; 2654 else if (!pmap_extract(pmap_kernel(), (vaddr_t)sb->sb_page_ary[pg], &pa)) 2655 return -1; 2656 2657 return atop(pa); 2658} 2659 2660/* Initialize data for an io operation on a scatter buffer. Returns 2661 * true if the transfer is valid, or false if out of range. */ 2662static bool 2663scatter_io_init(struct scatter_buf *sb, 2664 off_t off, size_t len, 2665 struct scatter_io *sio) 2666{ 2667 if ((off + len) > sb->sb_size) { 2668 DPRINTF(("video: scatter_io_init failed: off=%" PRId64 2669 " len=%zu sb->sb_size=%zu\n", 2670 off, len, sb->sb_size)); 2671 return false; 2672 } 2673 2674 sio->sio_buf = sb; 2675 sio->sio_offset = off; 2676 sio->sio_resid = len; 2677 2678 return true; 2679} 2680 2681/* Store the pointer and size of the next contiguous segment. Returns 2682 * true if the segment is valid, or false if all has been transfered. 2683 * Does not check for overflow. */ 2684static bool 2685scatter_io_next(struct scatter_io *sio, void **p, size_t *sz) 2686{ 2687 size_t pg, pgo; 2688 2689 if (sio->sio_resid == 0) 2690 return false; 2691 2692 pg = sio->sio_offset >> PAGE_SHIFT; 2693 pgo = sio->sio_offset & PAGE_MASK; 2694 2695 *sz = min(PAGE_SIZE - pgo, sio->sio_resid); 2696 *p = sio->sio_buf->sb_page_ary[pg] + pgo; 2697 2698 sio->sio_offset += *sz; 2699 sio->sio_resid -= *sz; 2700 2701 return true; 2702} 2703 2704/* Semi-undo of a failed segment copy. Updates the scatter_io 2705 * struct to the previous values prior to a failed segment copy. */ 2706static void 2707scatter_io_undo(struct scatter_io *sio, size_t sz) 2708{ 2709 sio->sio_offset -= sz; 2710 sio->sio_resid += sz; 2711} 2712 2713/* Copy data from src into the scatter_buf as described by io. */ 2714static void 2715scatter_io_copyin(struct scatter_io *sio, const void *p) 2716{ 2717 void *dst; 2718 const uint8_t *src = p; 2719 size_t sz; 2720 2721 while(scatter_io_next(sio, &dst, &sz)) { 2722 memcpy(dst, src, sz); 2723 src += sz; 2724 } 2725} 2726 2727/* --not used; commented to avoid compiler warnings-- 2728static void 2729scatter_io_copyout(struct scatter_io *sio, void *p) 2730{ 2731 void *src; 2732 uint8_t *dst = p; 2733 size_t sz; 2734 2735 while(scatter_io_next(sio, &src, &sz)) { 2736 memcpy(dst, src, sz); 2737 dst += sz; 2738 } 2739} 2740*/ 2741 2742/* Performat a series of uiomove calls on a scatter buf. Returns 2743 * EFAULT if uiomove EFAULTs on the first segment. Otherwise, returns 2744 * an incomplete transfer but with no error. */ 2745static int 2746scatter_io_uiomove(struct scatter_io *sio, struct uio *uio) 2747{ 2748 void *p; 2749 size_t sz; 2750 bool first = true; 2751 int err; 2752 2753 while(scatter_io_next(sio, &p, &sz)) { 2754 err = uiomove(p, sz, uio); 2755 if (err == EFAULT) { 2756 scatter_io_undo(sio, sz); 2757 if (first) 2758 return EFAULT; 2759 else 2760 return 0; 2761 } 2762 first = false; 2763 } 2764 2765 return 0; 2766} 2767 2768#endif /* NVIDEO > 0 */ 2769