Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163953973
D58368.id182336.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
52 KB
Referenced Files
None
Subscribers
None
D58368.id182336.diff
View Options
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3506,7 +3506,7 @@
# USB video drivers
#
dev/usb/video/udl.c optional udl
-dev/usb/video/uvideo.c optional uvideo
+dev/usb/video/uvideo.c optional uvideo video
#
# USB END
#
diff --git a/sys/dev/usb/video/uvideo.c b/sys/dev/usb/video/uvideo.c
--- a/sys/dev/usb/video/uvideo.c
+++ b/sys/dev/usb/video/uvideo.c
@@ -23,7 +23,6 @@
* USB Video Class (UVC) driver.
*
* Implements standard UVC 1.0/1.1/1.5 devices only.
- * Creates /dev/videoN character devices with V4L2 ioctl interface.
*/
#include <sys/param.h>
@@ -36,17 +35,11 @@
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
-#include <sys/poll.h>
#include <sys/proc.h>
-#include <sys/event.h>
-#include <sys/selinfo.h>
#include <sys/limits.h>
#include <sys/sysctl.h>
#include <sys/uio.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
@@ -54,6 +47,7 @@
#include "usbdevs.h"
#include <dev/usb/video/uvideo.h>
+#include <dev/video/video_if.h>
#define USB_DEBUG_VAR uvideo_debug
#include <dev/usb/usb_debug.h>
@@ -75,11 +69,6 @@
#define UE_GET_SIZE(x) ((x) & 0x7FF)
#define UE_GET_TRANS(x) (((x) >> 11) & 0x03)
-/* IO_NDELAY from sys/vnode.h - avoid pulling in vnode_if.h dependency */
-#ifndef IO_NDELAY
-#define IO_NDELAY 0x0004
-#endif
-
/* Forward declarations */
struct uvideo_softc;
@@ -146,50 +135,52 @@
static void uvideo_vs_free_frame(struct uvideo_softc *);
static usb_error_t uvideo_vs_open(struct uvideo_softc *);
static void uvideo_vs_close(struct uvideo_softc *);
-static usb_error_t uvideo_vs_init(struct uvideo_softc *);
static void uvideo_vs_decode_stream_header(struct uvideo_softc *,
uint8_t *, int);
static void uvideo_vs_decode_stream_header_isight(
struct uvideo_softc *, uint8_t *, int);
static void uvideo_isoc_decode(struct uvideo_softc *,
struct usb_page_cache *, int, int);
-static uint8_t *uvideo_mmap_getbuf(struct uvideo_softc *);
-static void uvideo_mmap_queue(struct uvideo_softc *, int, int);
-static void uvideo_read_frame(struct uvideo_softc *, uint8_t *, int);
-
-static d_open_t uvideo_cdev_open;
-static d_close_t uvideo_cdev_close;
-static d_read_t uvideo_cdev_read;
-static d_ioctl_t uvideo_cdev_ioctl;
-static d_poll_t uvideo_cdev_poll;
-static d_kqfilter_t uvideo_cdev_kqfilter;
-static d_mmap_t uvideo_cdev_mmap;
-
-static int uvideo_querycap(struct uvideo_softc *, struct v4l2_capability *);
-static int uvideo_enum_fmt(struct uvideo_softc *, struct v4l2_fmtdesc *);
-static int uvideo_enum_fsizes(struct uvideo_softc *,
- struct v4l2_frmsizeenum *);
-static int uvideo_enum_fivals(struct uvideo_softc *,
- struct v4l2_frmivalenum *);
-static int uvideo_s_fmt(struct uvideo_softc *, struct v4l2_format *);
-static int uvideo_g_fmt(struct uvideo_softc *, struct v4l2_format *);
-static int uvideo_s_parm(struct uvideo_softc *, struct v4l2_streamparm *);
-static int uvideo_g_parm(struct uvideo_softc *, struct v4l2_streamparm *);
-static int uvideo_enum_input(struct uvideo_softc *, struct v4l2_input *);
-static int uvideo_s_input(struct uvideo_softc *, int);
-static int uvideo_g_input(struct uvideo_softc *, int *);
-static int uvideo_reqbufs(struct uvideo_softc *,
- struct v4l2_requestbuffers *);
-static int uvideo_querybuf(struct uvideo_softc *, struct v4l2_buffer *);
-static int uvideo_qbuf(struct uvideo_softc *, struct v4l2_buffer *);
-static int uvideo_dqbuf(struct uvideo_softc *, struct v4l2_buffer *);
-static int uvideo_streamon(struct uvideo_softc *, int);
-static int uvideo_streamoff(struct uvideo_softc *, int);
-static int uvideo_try_fmt(struct uvideo_softc *, struct v4l2_format *);
-static int uvideo_queryctrl(struct uvideo_softc *,
- struct v4l2_queryctrl *);
-static int uvideo_g_ctrl(struct uvideo_softc *, struct v4l2_control *);
-static int uvideo_s_ctrl(struct uvideo_softc *, struct v4l2_control *);
+static void uvideo_frame_done(struct uvideo_softc *);
+
+static int uvideo_hw_querycap(void *, struct video_caps *);
+static int uvideo_hw_enum_format(void *, uint32_t, struct video_format *);
+static int uvideo_hw_get_format(void *, struct video_format *);
+static int uvideo_hw_try_format(void *, struct video_format *);
+static int uvideo_hw_set_format(void *, const struct video_format *);
+static int uvideo_hw_enum_framesizes(void *, struct video_frmsizeenum *);
+static int uvideo_hw_enum_frameintervals(void *,
+ struct video_frmivalenum *);
+static int uvideo_hw_get_parm(void *, struct video_fract *);
+static int uvideo_hw_set_parm(void *, struct video_fract *);
+static int uvideo_hw_enum_input(void *, uint32_t, struct video_input *);
+static int uvideo_hw_get_input(void *, uint32_t *);
+static int uvideo_hw_set_input(void *, uint32_t);
+static int uvideo_hw_query_control(void *, struct video_control_desc *);
+static int uvideo_hw_get_control(void *, struct video_control *);
+static int uvideo_hw_set_control(void *, const struct video_control *);
+static int uvideo_hw_start_stream(void *);
+static void uvideo_hw_stop_stream(void *);
+
+static const struct video_hw_ops uvideo_hw_ops = {
+ .querycap = uvideo_hw_querycap,
+ .enum_format = uvideo_hw_enum_format,
+ .get_format = uvideo_hw_get_format,
+ .try_format = uvideo_hw_try_format,
+ .set_format = uvideo_hw_set_format,
+ .enum_framesizes = uvideo_hw_enum_framesizes,
+ .enum_frameintervals = uvideo_hw_enum_frameintervals,
+ .get_parm = uvideo_hw_get_parm,
+ .set_parm = uvideo_hw_set_parm,
+ .enum_input = uvideo_hw_enum_input,
+ .get_input = uvideo_hw_get_input,
+ .set_input = uvideo_hw_set_input,
+ .query_control = uvideo_hw_query_control,
+ .get_control = uvideo_hw_get_control,
+ .set_control = uvideo_hw_set_control,
+ .start_stream = uvideo_hw_start_stream,
+ .stop_stream = uvideo_hw_stop_stream,
+};
/*
* Transfer configuration indices.
@@ -211,15 +202,13 @@
device_t sc_dev;
struct usb_device *sc_udev;
struct mtx sc_mtx;
- struct cdev *sc_cdev;
- int sc_unit;
+
+ struct video_device *sc_vd;
+ uint32_t sc_sequence;
uint8_t sc_iface_index;
uint8_t sc_nifaces;
int sc_dying;
- int sc_open;
- uint32_t sc_priority;
- struct proc *sc_owner;
struct usb_xfer *sc_xfer[UVIDEO_N_XFER];
int sc_streaming;
@@ -231,15 +220,6 @@
struct uvideo_frame_buffer sc_frame_buffer;
- struct uvideo_mmap sc_mmap[UVIDEO_MAX_BUFFERS];
- struct uvideo_mmap *sc_mmap_cur;
- uint8_t *sc_mmap_buffer;
- size_t sc_mmap_buffer_size;
- int sc_mmap_buffer_idx;
- q_mmap sc_mmap_q;
- int sc_mmap_count;
- int sc_mmap_flag;
-
uint8_t *sc_tmpbuf;
int sc_tmpbuf_size;
@@ -268,17 +248,6 @@
struct uvideo_vs_iface *sc_vs_cur;
struct uvideo_vs_iface sc_vs_coll[UVIDEO_MAX_VS_NUM];
- int sc_fsize;
- uint8_t *sc_fbuffer;
- size_t sc_fbufferlen;
- int sc_vidmode;
-#define VIDMODE_NONE 0
-#define VIDMODE_MMAP 1
-#define VIDMODE_READ 2
- int sc_frames_ready;
-
- struct selinfo sc_selinfo;
-
const struct uvideo_quirk *sc_quirk;
void (*sc_decode_stream_header)(
@@ -656,6 +625,7 @@
DRIVER_MODULE(uvideo, uhub, uvideo_driver, NULL, NULL);
MODULE_DEPEND(uvideo, usb, 1, 1, 1);
+MODULE_DEPEND(uvideo, video, 1, 1, 1);
MODULE_VERSION(uvideo, 1);
USB_PNP_HOST_INFO(uvideo_devs);
@@ -721,26 +691,6 @@
},
};
-/*
- * Character device switch
- */
-static struct cdevsw uvideo_cdevsw = {
- .d_version = D_VERSION,
- .d_open = uvideo_cdev_open,
- .d_close = uvideo_cdev_close,
- .d_read = uvideo_cdev_read,
- .d_ioctl = uvideo_cdev_ioctl,
- .d_poll = uvideo_cdev_poll,
- .d_kqfilter = uvideo_cdev_kqfilter,
- .d_mmap = uvideo_cdev_mmap,
- .d_name = "video",
-};
-
-/*
- * Unit number allocator
- */
-/* Unit number allocation is handled by scanning for free /dev/videoN names */
-
/* ---------------------------------------------------------------- */
/* Probe / Attach / Detach */
/* ---------------------------------------------------------------- */
@@ -782,7 +732,6 @@
struct usb_config_descriptor *cdesc;
struct usb_descriptor *desc;
struct usb_interface_assoc_descriptor *iad;
- struct make_dev_args args;
usb_error_t error;
int first_iface, nifaces;
int i;
@@ -793,7 +742,6 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "uvideo", NULL, MTX_DEF);
- knlist_init_mtx(&sc->sc_selinfo.si_note, &sc->sc_mtx);
/* Look up quirks for this device */
sc->sc_quirk = uvideo_lookup_quirk(uaa);
@@ -907,33 +855,12 @@
}
}
- /* Init mmap queue */
- STAILQ_INIT(&sc->sc_mmap_q);
- sc->sc_mmap_count = 0;
-
- /* Allocate unit number and create character device */
- make_dev_args_init(&args);
- args.mda_devsw = &uvideo_cdevsw;
- args.mda_uid = UID_ROOT;
- args.mda_gid = GID_VIDEO;
- args.mda_mode = 0660;
- args.mda_si_drv1 = sc;
- args.mda_flags = MAKEDEV_CHECKNAME;
-
- sc->sc_unit = -1;
- for (i = 0; i < 256; i++) {
- if (make_dev_s(&args, &sc->sc_cdev, "video%d", i) == 0) {
- sc->sc_unit = i;
- break;
- }
- }
- if (sc->sc_unit < 0) {
- device_printf(dev, "failed to create /dev/video device\n");
+ i = video_register(dev, &uvideo_hw_ops, sc, &sc->sc_vd);
+ if (i != 0) {
+ device_printf(dev, "failed to register video device\n");
goto detach;
}
- device_printf(dev, "UVC camera on /dev/video%d\n", sc->sc_unit);
-
return (0);
detach:
@@ -948,7 +875,9 @@
sc->sc_dying = 1;
- /* Stop any active streaming */
+ if (sc->sc_vd != NULL)
+ video_unregister(sc->sc_vd);
+
if (sc->sc_streaming) {
mtx_lock(&sc->sc_mtx);
sc->sc_streaming = 0;
@@ -956,22 +885,11 @@
uvideo_vs_close(sc);
}
- /* Destroy character device */
- if (sc->sc_cdev != NULL) {
- destroy_dev(sc->sc_cdev);
- sc->sc_cdev = NULL;
- }
-
- /* Unit number is implicitly freed when the cdev is destroyed */
-
- /* Free frame buffers */
uvideo_vs_free_frame(sc);
/* Unsetup USB transfers */
usbd_transfer_unsetup(sc->sc_xfer, UVIDEO_N_XFER);
- seldrain(&sc->sc_selinfo);
- knlist_destroy(&sc->sc_selinfo.si_note);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -2229,12 +2147,6 @@
fb->buf_size = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
- if (sc->sc_max_fbuf_size < fb->buf_size && sc->sc_mmap_flag == 0) {
- device_printf(sc->sc_dev,
- "software video buffer too small!\n");
- return (USB_ERR_NOMEM);
- }
-
fb->buf = malloc(fb->buf_size, M_USBDEV, M_WAITOK | M_ZERO);
if (fb->buf == NULL) {
device_printf(sc->sc_dev,
@@ -2264,18 +2176,6 @@
free(fb->buf, M_USBDEV);
fb->buf = NULL;
}
-
- if (sc->sc_mmap_buffer != NULL) {
- contigfree(sc->sc_mmap_buffer, sc->sc_mmap_buffer_size,
- M_USBDEV);
- sc->sc_mmap_buffer = NULL;
- sc->sc_mmap_buffer_size = 0;
- }
-
- while (!STAILQ_EMPTY(&sc->sc_mmap_q))
- STAILQ_REMOVE_HEAD(&sc->sc_mmap_q, q_frames);
-
- sc->sc_mmap_count = 0;
}
static usb_error_t
@@ -2376,22 +2276,6 @@
}
}
-static usb_error_t
-uvideo_vs_init(struct uvideo_softc *sc)
-{
- usb_error_t error;
-
- error = uvideo_vs_open(sc);
- if (error != USB_ERR_NORMAL_COMPLETION)
- return (USB_ERR_INVAL);
-
- error = uvideo_vs_alloc_frame(sc);
- if (error != USB_ERR_NORMAL_COMPLETION)
- return (USB_ERR_INVAL);
-
- return (USB_ERR_NORMAL_COMPLETION);
-}
-
/* ---------------------------------------------------------------- */
/* Transfer Callbacks */
/* ---------------------------------------------------------------- */
@@ -2408,7 +2292,6 @@
struct uvideo_frame_buffer *fb = &sc->sc_frame_buffer;
uint8_t shdr[2];
uint8_t flags;
- uint8_t *buf;
int hdrlen, payload_len;
if (len < UVIDEO_SH_MIN_LEN)
@@ -2442,16 +2325,6 @@
fb->error = 1;
}
- /* Get destination buffer */
- if (sc->sc_mmap_flag) {
- if (!fb->mmap_q_full) {
- buf = uvideo_mmap_getbuf(sc);
- if (buf == NULL)
- fb->mmap_q_full = 1;
- }
- } else
- buf = fb->buf;
-
/* Copy payload directly from USB DMA into frame buffer */
payload_len = len - hdrlen;
if (payload_len > fb->buf_size - fb->offset) {
@@ -2459,9 +2332,9 @@
payload_len = fb->buf_size - fb->offset;
fb->error = 1;
}
- if (!fb->mmap_q_full && payload_len > 0) {
+ if (payload_len > 0) {
usbd_copy_out(pc, offset + hdrlen,
- buf + fb->offset, payload_len);
+ fb->buf + fb->offset, payload_len);
fb->offset += payload_len;
}
@@ -2474,13 +2347,14 @@
fb->error = 1;
}
- if (sc->sc_mmap_flag) {
- if (!fb->mmap_q_full)
- uvideo_mmap_queue(sc, fb->offset, fb->error);
- } else if (fb->error) {
- DPRINTFN(1, "error frame, skipped\n");
+ if (!fb->error) {
+ uvideo_frame_done(sc);
} else {
- uvideo_read_frame(sc, fb->buf, fb->offset);
+ struct video_buf *vb;
+
+ vb = video_buf_acquire(sc->sc_vd);
+ if (vb != NULL)
+ video_buf_error(vb);
}
fb->sample = 0;
@@ -2571,7 +2445,6 @@
struct uvideo_frame_buffer *fb = &sc->sc_frame_buffer;
struct usb_video_stream_header *sh;
int sample_len;
- uint8_t *buf;
if (frame_size < UVIDEO_SH_MIN_LEN)
return;
@@ -2605,15 +2478,6 @@
fb->error = 1;
}
- if (sc->sc_mmap_flag) {
- if (!fb->mmap_q_full) {
- buf = uvideo_mmap_getbuf(sc);
- if (buf == NULL)
- fb->mmap_q_full = 1;
- }
- } else
- buf = sc->sc_frame_buffer.buf;
-
/* Save sample data */
sample_len = frame_size - sh->bLength;
if (sample_len > fb->buf_size - fb->offset) {
@@ -2621,8 +2485,8 @@
sample_len = fb->buf_size - fb->offset;
fb->error = 1;
}
- if (!fb->mmap_q_full && sample_len > 0) {
- bcopy(frame + sh->bLength, buf + fb->offset, sample_len);
+ if (sample_len > 0) {
+ bcopy(frame + sh->bLength, fb->buf + fb->offset, sample_len);
fb->offset += sample_len;
}
@@ -2636,13 +2500,14 @@
fb->error = 1;
}
- if (sc->sc_mmap_flag) {
- if (!fb->mmap_q_full)
- uvideo_mmap_queue(sc, fb->offset, fb->error);
- } else if (fb->error) {
- DPRINTFN(1, "error frame, skipped\n");
+ if (!fb->error) {
+ uvideo_frame_done(sc);
} else {
- uvideo_read_frame(sc, fb->buf, fb->offset);
+ struct video_buf *vb;
+
+ vb = video_buf_acquire(sc->sc_vd);
+ if (vb != NULL)
+ video_buf_error(vb);
}
fb->sample = 0;
@@ -2652,25 +2517,12 @@
}
}
-/*
- * The iSight first generation device uses a non-standard streaming
- * protocol. The stream header is sent once per image and looks like:
- *
- * uByte header length
- * uByte flags
- * uByte magic1[4] always "11223344"
- * uByte magic2[8] always "deadbeefdeadface"
- * uByte unknown[16]
- *
- * Sometimes the stream header is prefixed by an unknown byte.
- */
static void
uvideo_vs_decode_stream_header_isight(struct uvideo_softc *sc,
uint8_t *frame, int frame_size)
{
struct uvideo_frame_buffer *fb = &sc->sc_frame_buffer;
int sample_len, header = 0;
- uint8_t *buf;
uint8_t magic[] = { 0x11, 0x22, 0x33, 0x44, 0xde, 0xad, 0xbe,
0xef, 0xde, 0xad, 0xfa, 0xce };
@@ -2685,559 +2537,217 @@
}
if (header) {
- if (sc->sc_mmap_flag) {
- if (!fb->mmap_q_full)
- uvideo_mmap_queue(sc, fb->offset, 0);
- } else {
- uvideo_read_frame(sc, fb->buf, fb->offset);
- }
+ if (fb->offset > 0)
+ uvideo_frame_done(sc);
fb->offset = 0;
- fb->mmap_q_full = 0;
} else {
- if (sc->sc_mmap_flag) {
- if (!fb->mmap_q_full) {
- buf = uvideo_mmap_getbuf(sc);
- if (buf == NULL)
- fb->mmap_q_full = 1;
- }
- } else
- buf = sc->sc_frame_buffer.buf;
-
- /* Save sample */
sample_len = frame_size;
- if (!fb->mmap_q_full &&
- (fb->offset + sample_len) < fb->buf_size) {
- bcopy(frame, buf + fb->offset, sample_len);
+ if ((fb->offset + sample_len) < fb->buf_size) {
+ bcopy(frame, fb->buf + fb->offset, sample_len);
fb->offset += sample_len;
}
}
}
-static uint8_t *
-uvideo_mmap_getbuf(struct uvideo_softc *sc)
-{
- int i, idx;
-
- /*
- * Multiple frames per transfer / multiple transfers per frame.
- */
- if (sc->sc_mmap_cur != NULL)
- return (sc->sc_mmap_cur->buf);
-
- if (sc->sc_mmap_count == 0 || sc->sc_mmap_buffer == NULL)
- return (NULL);
-
- idx = sc->sc_mmap_buffer_idx;
-
- /* Find a buffer which is queued and ready */
- for (i = 0; i < sc->sc_mmap_count; i++) {
- if (sc->sc_mmap[sc->sc_mmap_buffer_idx].v4l2_buf.flags &
- V4L2_BUF_FLAG_QUEUED) {
- idx = sc->sc_mmap_buffer_idx;
- if (++sc->sc_mmap_buffer_idx == sc->sc_mmap_count)
- sc->sc_mmap_buffer_idx = 0;
- break;
- }
- if (++sc->sc_mmap_buffer_idx == sc->sc_mmap_count)
- sc->sc_mmap_buffer_idx = 0;
- }
-
- if (i == sc->sc_mmap_count) {
- DPRINTFN(1, "mmap queue is full!\n");
- return (NULL);
- }
-
- sc->sc_mmap_cur = &sc->sc_mmap[idx];
- return (sc->sc_mmap_cur->buf);
-}
-
static void
-uvideo_mmap_queue(struct uvideo_softc *sc, int len, int err)
+uvideo_frame_done(struct uvideo_softc *sc)
{
+ struct video_buf *vb;
- if (sc->sc_mmap_cur == NULL)
+ vb = video_buf_acquire(sc->sc_vd);
+ if (vb == NULL)
return;
- sc->sc_mmap_cur->v4l2_buf.bytesused = len;
-
- getmicrouptime(&sc->sc_mmap_cur->v4l2_buf.timestamp);
- sc->sc_mmap_cur->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TIMESTAMP_MASK;
- sc->sc_mmap_cur->v4l2_buf.flags |= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- sc->sc_mmap_cur->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
- sc->sc_mmap_cur->v4l2_buf.flags |= V4L2_BUF_FLAG_TSTAMP_SRC_EOF;
- sc->sc_mmap_cur->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TIMECODE;
-
- sc->sc_mmap_cur->v4l2_buf.flags &= ~V4L2_BUF_FLAG_ERROR;
- if (err)
- sc->sc_mmap_cur->v4l2_buf.flags |= V4L2_BUF_FLAG_ERROR;
-
- sc->sc_mmap_cur->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
- sc->sc_mmap_cur->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
- STAILQ_INSERT_TAIL(&sc->sc_mmap_q, sc->sc_mmap_cur, q_frames);
- sc->sc_mmap_cur = NULL;
-
- DPRINTFN(2, "frame queued\n");
-
- wakeup(sc);
- selwakeup(&sc->sc_selinfo);
- KNOTE_LOCKED(&sc->sc_selinfo.si_note, 0);
+ video_buf_write(vb, 0, sc->sc_frame_buffer.buf,
+ sc->sc_frame_buffer.offset);
+ video_buf_done(vb, sc->sc_frame_buffer.offset, sc->sc_sequence++);
}
-static void
-uvideo_read_frame(struct uvideo_softc *sc, uint8_t *buf, int len)
-{
-
- /*
- * In read mode, copy the frame into the upper-layer buffer
- * so the USB callback can start assembling the next frame
- * without racing with the cdev read.
- */
- if (sc->sc_fbuffer == NULL || len > sc->sc_fbufferlen)
- return;
-
- bcopy(buf, sc->sc_fbuffer, len);
- sc->sc_fsize = len;
- sc->sc_frames_ready++;
-
- wakeup(sc);
- selwakeup(&sc->sc_selinfo);
- KNOTE_LOCKED(&sc->sc_selinfo.si_note, 0);
-}
-
-/* ---------------------------------------------------------------- */
-/* Character Device Operations */
-/* ---------------------------------------------------------------- */
-
static int
-uvideo_cdev_open(struct cdev *dev, int flags, int fmt, struct thread *td)
+uvideo_hw_querycap(void *arg, struct video_caps *caps)
{
- struct uvideo_softc *sc = dev->si_drv1;
-
- if (sc == NULL || sc->sc_dying)
- return (ENXIO);
-
- if (sc->sc_vs_cur == NULL)
- return (EIO);
+ struct uvideo_softc *sc = arg;
- mtx_lock(&sc->sc_mtx);
- if (sc->sc_open == 0) {
- /* First open: initialize state */
- sc->sc_owner = td->td_proc;
- sc->sc_mmap_flag = 0;
- sc->sc_negotiated_flag = 0;
- sc->sc_vidmode = VIDMODE_NONE;
- sc->sc_frames_ready = 0;
- sc->sc_priority = 1; /* V4L2_PRIORITY_DEFAULT */
- }
- sc->sc_open++;
- mtx_unlock(&sc->sc_mtx);
+ bzero(caps, sizeof(*caps));
+ strlcpy(caps->driver, "uvideo", sizeof(caps->driver));
+ strlcpy(caps->card, usb_get_product(sc->sc_udev),
+ sizeof(caps->card));
+ snprintf(caps->bus_info, sizeof(caps->bus_info), "usb-%s",
+ device_get_nameunit(sc->sc_dev));
+ caps->version = (5 << 16) | (0 << 8) | 0; /* 5.0.0 */
+ caps->capabilities = VIDEO_CAP_CAPTURE |
+ VIDEO_CAP_READWRITE | VIDEO_CAP_STREAMING;
return (0);
}
static int
-uvideo_cdev_close(struct cdev *dev, int flags, int fmt, struct thread *td)
+uvideo_hw_enum_format(void *arg, uint32_t index, struct video_format *fmt)
{
- struct uvideo_softc *sc = dev->si_drv1;
+ struct uvideo_softc *sc = arg;
+ struct uvideo_format_group *fmtgrp;
+ struct usb_video_frame_desc *frame;
- if (sc == NULL)
- return (0);
+ if (index >= (uint32_t)sc->sc_fmtgrp_num)
+ return (EINVAL);
- mtx_lock(&sc->sc_mtx);
- sc->sc_open--;
- if (sc->sc_open > 0) {
- mtx_unlock(&sc->sc_mtx);
- return (0);
- }
- mtx_unlock(&sc->sc_mtx);
+ fmtgrp = &sc->sc_fmtgrp[index];
+ frame = fmtgrp->frame_cur;
- /* Last close: stop streaming if active */
- if (sc->sc_streaming) {
- mtx_lock(&sc->sc_mtx);
- sc->sc_streaming = 0;
- mtx_unlock(&sc->sc_mtx);
- uvideo_vs_close(sc);
- uvideo_vs_free_frame(sc);
+ bzero(fmt, sizeof(*fmt));
+ fmt->pixelformat = fmtgrp->pixelformat;
+ if (frame != NULL) {
+ fmt->width = UGETW(UVIDEO_FRAME_FIELD(frame, wWidth));
+ fmt->height = UGETW(UVIDEO_FRAME_FIELD(frame, wHeight));
}
+ fmt->sizeimage = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
+ fmt->field = V4L2_FIELD_NONE;
- if (sc->sc_fbuffer != NULL) {
- free(sc->sc_fbuffer, M_USBDEV);
- sc->sc_fbuffer = NULL;
- sc->sc_fbufferlen = 0;
+ if (fmtgrp->has_colorformat) {
+ fmt->colorspace = fmtgrp->colorspace;
+ fmt->xfer_func = fmtgrp->xfer_func;
+ fmt->ycbcr_enc = fmtgrp->ycbcr_enc;
}
- sc->sc_open = 0;
- sc->sc_owner = NULL;
- sc->sc_vidmode = VIDMODE_NONE;
+ switch (fmtgrp->format->bDescriptorSubtype) {
+ case UDESCSUB_VS_FORMAT_MJPEG:
+ fmt->flags = V4L2_FMT_FLAG_COMPRESSED;
+ strlcpy(fmt->description, "Motion-JPEG",
+ sizeof(fmt->description));
+ break;
+ case UDESCSUB_VS_FORMAT_H264:
+ case UDESCSUB_VS_FORMAT_H264_SIMULCAST:
+ fmt->flags = V4L2_FMT_FLAG_COMPRESSED;
+ strlcpy(fmt->description, "H.264",
+ sizeof(fmt->description));
+ break;
+ case UDESCSUB_VS_FORMAT_FRAME_BASED:
+ if (fmtgrp->format->u.fb.bVariableSize)
+ fmt->flags = V4L2_FMT_FLAG_COMPRESSED;
+ break;
+ default:
+ strlcpy(fmt->description, "YUV",
+ sizeof(fmt->description));
+ break;
+ }
return (0);
}
static int
-uvideo_cdev_read(struct cdev *dev, struct uio *uio, int ioflag)
+uvideo_hw_get_format(void *arg, struct video_format *fmt)
{
- struct uvideo_softc *sc = dev->si_drv1;
- usb_error_t error;
- int ret;
-
- if (sc == NULL || sc->sc_dying)
- return (ENXIO);
+ struct uvideo_softc *sc = arg;
+ struct usb_video_frame_desc *frame;
- if (sc->sc_vs_cur == NULL)
+ if (sc->sc_fmtgrp_cur == NULL)
return (EIO);
- /* Start streaming in read mode if not already running */
- if (sc->sc_vidmode == VIDMODE_NONE) {
- sc->sc_mmap_flag = 0;
- sc->sc_vidmode = VIDMODE_READ;
-
- error = uvideo_vs_init(sc);
- if (error != USB_ERR_NORMAL_COMPLETION) {
- sc->sc_vidmode = VIDMODE_NONE;
- return (EIO);
- }
-
- /* Allocate a separate read buffer for frame delivery */
- sc->sc_fbufferlen = sc->sc_max_fbuf_size;
- if (sc->sc_fbufferlen == 0)
- sc->sc_fbufferlen =
- UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
- if (sc->sc_fbuffer == NULL) {
- sc->sc_fbuffer = malloc(sc->sc_fbufferlen, M_USBDEV,
- M_WAITOK | M_ZERO);
- if (sc->sc_fbuffer == NULL) {
- sc->sc_vidmode = VIDMODE_NONE;
- return (ENOMEM);
- }
- }
+ frame = sc->sc_fmtgrp_cur->frame_cur;
- mtx_lock(&sc->sc_mtx);
- sc->sc_streaming = 1;
- if (sc->sc_vs_cur->bulk_endpoint)
- usbd_transfer_start(sc->sc_xfer[0]);
- else {
- int i;
- for (i = 0; i < UVIDEO_IXFERS; i++)
- usbd_transfer_start(sc->sc_xfer[i]);
- }
- mtx_unlock(&sc->sc_mtx);
+ bzero(fmt, sizeof(*fmt));
+ fmt->pixelformat = sc->sc_fmtgrp_cur->pixelformat;
+ fmt->field = V4L2_FIELD_NONE;
+ if (frame != NULL) {
+ fmt->width = UGETW(UVIDEO_FRAME_FIELD(frame, wWidth));
+ fmt->height = UGETW(UVIDEO_FRAME_FIELD(frame, wHeight));
}
+ fmt->sizeimage = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
- if (sc->sc_vidmode != VIDMODE_READ)
- return (EBUSY);
-
- /* Wait for a frame */
- while (sc->sc_frames_ready == 0) {
- if (ioflag & IO_NDELAY)
- return (EWOULDBLOCK);
- ret = tsleep(sc, PCATCH, "uvread", hz * 10);
- if (ret != 0)
- return (ret);
- if (sc->sc_dying)
- return (ENXIO);
+ if (sc->sc_fmtgrp_cur->has_colorformat) {
+ fmt->colorspace = sc->sc_fmtgrp_cur->colorspace;
+ fmt->xfer_func = sc->sc_fmtgrp_cur->xfer_func;
+ fmt->ycbcr_enc = sc->sc_fmtgrp_cur->ycbcr_enc;
}
- sc->sc_frames_ready--;
-
- if (sc->sc_fsize == 0)
- return (0);
-
- return (uiomove(sc->sc_fbuffer, MIN(uio->uio_resid, sc->sc_fsize),
- uio));
-}
-
-static int
-uvideo_cdev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
- struct thread *td)
-{
- struct uvideo_softc *sc = dev->si_drv1;
-
- if (sc == NULL || sc->sc_dying)
- return (ENXIO);
-
- DPRINTFN(2, "ioctl cmd=0x%08lx\n", cmd);
-
- switch (cmd) {
- case VIDIOC_QUERYCAP:
- return (uvideo_querycap(sc, (struct v4l2_capability *)data));
- case VIDIOC_ENUM_FMT:
- return (uvideo_enum_fmt(sc, (struct v4l2_fmtdesc *)data));
- case VIDIOC_ENUM_FRAMESIZES:
- return (uvideo_enum_fsizes(sc,
- (struct v4l2_frmsizeenum *)data));
- case VIDIOC_ENUM_FRAMEINTERVALS:
- return (uvideo_enum_fivals(sc,
- (struct v4l2_frmivalenum *)data));
- case VIDIOC_S_FMT:
- return (uvideo_s_fmt(sc, (struct v4l2_format *)data));
- case VIDIOC_G_FMT:
- return (uvideo_g_fmt(sc, (struct v4l2_format *)data));
- case VIDIOC_TRY_FMT:
- return (uvideo_try_fmt(sc, (struct v4l2_format *)data));
- case VIDIOC_S_PARM:
- return (uvideo_s_parm(sc, (struct v4l2_streamparm *)data));
- case VIDIOC_G_PARM:
- return (uvideo_g_parm(sc, (struct v4l2_streamparm *)data));
- case VIDIOC_ENUMINPUT:
- return (uvideo_enum_input(sc, (struct v4l2_input *)data));
- case VIDIOC_S_INPUT:
- return (uvideo_s_input(sc, *(int *)data));
- case VIDIOC_G_INPUT:
- return (uvideo_g_input(sc, (int *)data));
- case VIDIOC_REQBUFS:
- return (uvideo_reqbufs(sc,
- (struct v4l2_requestbuffers *)data));
- case VIDIOC_QUERYBUF:
- return (uvideo_querybuf(sc, (struct v4l2_buffer *)data));
- case VIDIOC_QBUF:
- return (uvideo_qbuf(sc, (struct v4l2_buffer *)data));
- case VIDIOC_DQBUF:
- return (uvideo_dqbuf(sc, (struct v4l2_buffer *)data));
- case VIDIOC_STREAMON:
- return (uvideo_streamon(sc, *(int *)data));
- case VIDIOC_STREAMOFF:
- return (uvideo_streamoff(sc, *(int *)data));
- case VIDIOC_QUERYCTRL:
- return (uvideo_queryctrl(sc,
- (struct v4l2_queryctrl *)data));
- case VIDIOC_G_CTRL:
- return (uvideo_g_ctrl(sc, (struct v4l2_control *)data));
- case VIDIOC_S_CTRL:
- return (uvideo_s_ctrl(sc, (struct v4l2_control *)data));
- case VIDIOC_G_PRIORITY:
- *(uint32_t *)data = sc->sc_priority;
- return (0);
- case VIDIOC_S_PRIORITY:
- sc->sc_priority = *(uint32_t *)data;
- return (0);
- default:
- return (ENOTTY);
- }
+ return (0);
}
static int
-uvideo_cdev_poll(struct cdev *dev, int events, struct thread *td)
+uvideo_hw_try_format(void *arg, struct video_format *fmt)
{
- struct uvideo_softc *sc = dev->si_drv1;
- int revents = 0;
-
- if (sc == NULL || sc->sc_dying)
- return (POLLHUP);
+ struct uvideo_softc *sc = arg;
+ struct uvideo_res r;
+ int found, i;
- if (events & (POLLIN | POLLRDNORM)) {
- if (sc->sc_mmap_flag) {
- if (!STAILQ_EMPTY(&sc->sc_mmap_q))
- revents |= events & (POLLIN | POLLRDNORM);
- } else {
- if (sc->sc_frames_ready > 0)
- revents |= events & (POLLIN | POLLRDNORM);
+ for (found = 0, i = 0; i < sc->sc_fmtgrp_num; i++) {
+ if (fmt->pixelformat == sc->sc_fmtgrp[i].pixelformat) {
+ found = 1;
+ break;
}
- if (revents == 0)
- selrecord(td, &sc->sc_selinfo);
}
-
- return (revents);
-}
-
-static void
-uvideo_kqfilter_detach(struct knote *kn)
-{
- struct uvideo_softc *sc = kn->kn_hook;
-
- knlist_remove(&sc->sc_selinfo.si_note, kn, 0);
-}
-
-static int
-uvideo_kqfilter_read(struct knote *kn, long hint __unused)
-{
- struct uvideo_softc *sc = kn->kn_hook;
-
- if (sc->sc_mmap_flag)
- return (!STAILQ_EMPTY(&sc->sc_mmap_q));
- return (sc->sc_frames_ready > 0);
-}
-
-static struct filterops uvideo_filtops_read = {
- .f_isfd = 1,
- .f_detach = uvideo_kqfilter_detach,
- .f_event = uvideo_kqfilter_read,
-};
-
-static int
-uvideo_cdev_kqfilter(struct cdev *dev, struct knote *kn)
-{
- struct uvideo_softc *sc = dev->si_drv1;
-
- if (sc == NULL || sc->sc_dying)
- return (ENXIO);
-
- switch (kn->kn_filter) {
- case EVFILT_READ:
- kn->kn_fop = &uvideo_filtops_read;
- kn->kn_hook = sc;
- knlist_add(&sc->sc_selinfo.si_note, kn, 0);
- return (0);
- default:
- return (EINVAL);
- }
-}
-
-static int
-uvideo_cdev_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
- int nprot, vm_memattr_t *memattr)
-{
- struct uvideo_softc *sc = dev->si_drv1;
-
- if (sc == NULL || sc->sc_dying)
- return (ENXIO);
-
- if (offset >= sc->sc_mmap_buffer_size)
+ if (found == 0)
return (EINVAL);
- if (sc->sc_mmap_buffer == NULL)
+ if (sc->sc_fmtgrp[i].frame_num == 0)
return (EINVAL);
- if (!sc->sc_mmap_flag)
- sc->sc_mmap_flag = 1;
-
- *paddr = vtophys(sc->sc_mmap_buffer + offset);
+ uvideo_find_res(sc, i, fmt->width, fmt->height, &r);
- return (0);
-}
-
-/* ---------------------------------------------------------------- */
-/* V4L2 Ioctl Handlers */
-/* ---------------------------------------------------------------- */
-
-static int
-uvideo_querycap(struct uvideo_softc *sc, struct v4l2_capability *caps)
-{
+ fmt->width = r.width;
+ fmt->height = r.height;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->sizeimage = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
- bzero(caps, sizeof(*caps));
- strlcpy(caps->driver, "uvideo", sizeof(caps->driver));
- strlcpy(caps->card, usb_get_product(sc->sc_udev),
- sizeof(caps->card));
- snprintf(caps->bus_info, sizeof(caps->bus_info), "usb-%s",
- device_get_nameunit(sc->sc_dev));
-
- caps->version = (5 << 16) | (0 << 8) | 0; /* 5.0.0 */
- caps->device_caps = V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_STREAMING | V4L2_CAP_READWRITE |
- V4L2_CAP_EXT_PIX_FORMAT;
- caps->capabilities = caps->device_caps | V4L2_CAP_DEVICE_CAPS;
+ if (sc->sc_fmtgrp[i].has_colorformat) {
+ fmt->colorspace = sc->sc_fmtgrp[i].colorspace;
+ fmt->xfer_func = sc->sc_fmtgrp[i].xfer_func;
+ fmt->ycbcr_enc = sc->sc_fmtgrp[i].ycbcr_enc;
+ }
return (0);
}
-/*
- * Map pixel format to canonical V4L2 description string.
- * v4l2-compliance checks these names against an internal table.
- */
-static const struct {
- uint32_t pixfmt;
- const char *name;
- uint32_t flags;
-} uvideo_fmt_names[] = {
- { V4L2_PIX_FMT_MJPEG, "Motion-JPEG", V4L2_FMT_FLAG_COMPRESSED },
- { V4L2_PIX_FMT_YUYV, "YUYV 4:2:2", 0 },
- { V4L2_PIX_FMT_UYVY, "UYVY 4:2:2", 0 },
- { V4L2_PIX_FMT_NV12, "Y/UV 4:2:0", 0 },
- { V4L2_PIX_FMT_NV21, "Y/VU 4:2:0", 0 },
- { V4L2_PIX_FMT_YVU420, "Planar YVU 4:2:0", 0 },
- { V4L2_PIX_FMT_YUV420, "Planar YUV 4:2:0", 0 },
- { V4L2_PIX_FMT_M420, "M420 YUV 4:2:0", 0 },
- { V4L2_PIX_FMT_GREY, "8-bit Greyscale", 0 },
- { V4L2_PIX_FMT_Y10, "10-bit Greyscale", 0 },
- { V4L2_PIX_FMT_Y12, "12-bit Greyscale", 0 },
- { V4L2_PIX_FMT_Y16, "16-bit Greyscale", 0 },
- { V4L2_PIX_FMT_RGB565, "16-bit RGB 5-6-5", 0 },
- { V4L2_PIX_FMT_BGR24, "24-bit BGR 8-8-8", 0 },
- { V4L2_PIX_FMT_XBGR32, "32-bit BGRX 8-8-8-8", 0 },
- { V4L2_PIX_FMT_H264, "H.264", V4L2_FMT_FLAG_COMPRESSED },
- { V4L2_PIX_FMT_HEVC, "HEVC", V4L2_FMT_FLAG_COMPRESSED },
- { V4L2_PIX_FMT_SBGGR8, "8-bit Bayer BGBG/GRGR", 0 },
- { V4L2_PIX_FMT_SGBRG8, "8-bit Bayer GBGB/RGRG", 0 },
- { V4L2_PIX_FMT_SGRBG8, "8-bit Bayer GRGR/BGBG", 0 },
- { V4L2_PIX_FMT_SRGGB8, "8-bit Bayer RGRG/GBGB", 0 },
- { V4L2_PIX_FMT_SBGGR16, "16-bit Bayer BGBG/GRGR", 0 },
- { V4L2_PIX_FMT_SGBRG16, "16-bit Bayer GBGB/RGRG", 0 },
- { V4L2_PIX_FMT_SGRBG16, "16-bit Bayer GRGR/BGBG", 0 },
- { V4L2_PIX_FMT_SRGGB16, "16-bit Bayer RGRG/GBGB", 0 },
- { V4L2_PIX_FMT_SRGGB10P, "10-bit Bayer RGRG/GBGB Packed", 0 },
- { V4L2_PIX_FMT_Z16, "16-bit Depth", 0 },
- { 0, NULL, 0 }
-};
-
static int
-uvideo_enum_fmt(struct uvideo_softc *sc, struct v4l2_fmtdesc *fmtdesc)
+uvideo_hw_set_format(void *arg, const struct video_format *fmt)
{
- uint32_t idx, type, pixfmt, flags;
- const char *name;
- int i;
-
- type = fmtdesc->type;
- idx = fmtdesc->index;
+ struct uvideo_softc *sc = arg;
+ struct uvideo_format_group *fmtgrp_save;
+ struct usb_video_frame_desc *frame_save;
+ struct uvideo_res r;
+ int found, i;
+ usb_error_t error;
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ for (found = 0, i = 0; i < sc->sc_fmtgrp_num; i++) {
+ if (fmt->pixelformat == sc->sc_fmtgrp[i].pixelformat) {
+ found = 1;
+ break;
+ }
+ }
+ if (found == 0)
return (EINVAL);
- if (idx >= (uint32_t)sc->sc_fmtgrp_num)
+ if (sc->sc_fmtgrp[i].frame_num == 0)
return (EINVAL);
- pixfmt = sc->sc_fmtgrp[idx].pixelformat;
- flags = 0;
- name = "Unknown Format";
+ uvideo_find_res(sc, i, fmt->width, fmt->height, &r);
- /* Look up canonical name and flags */
- for (i = 0; uvideo_fmt_names[i].name != NULL; i++) {
- if (uvideo_fmt_names[i].pixfmt == pixfmt) {
- name = uvideo_fmt_names[i].name;
- flags = uvideo_fmt_names[i].flags;
- break;
- }
- }
+ fmtgrp_save = sc->sc_fmtgrp_cur;
+ frame_save = sc->sc_fmtgrp_cur->frame_cur;
- /* Override flags for special descriptor subtypes */
- switch (sc->sc_fmtgrp[idx].format->bDescriptorSubtype) {
- case UDESCSUB_VS_FORMAT_MJPEG:
- pixfmt = V4L2_PIX_FMT_MJPEG;
- flags = V4L2_FMT_FLAG_COMPRESSED;
- name = "Motion-JPEG";
- break;
- case UDESCSUB_VS_FORMAT_H264:
- case UDESCSUB_VS_FORMAT_H264_SIMULCAST:
- pixfmt = V4L2_PIX_FMT_H264;
- flags = V4L2_FMT_FLAG_COMPRESSED;
- name = "H.264";
- break;
- case UDESCSUB_VS_FORMAT_FRAME_BASED:
- if (sc->sc_fmtgrp[idx].format->u.fb.bVariableSize)
- flags = V4L2_FMT_FLAG_COMPRESSED;
- break;
- }
+ sc->sc_fmtgrp_cur = &sc->sc_fmtgrp[i];
+ sc->sc_fmtgrp[i].frame_cur = sc->sc_fmtgrp[i].frame[r.fidx];
- bzero(fmtdesc, sizeof(*fmtdesc));
- fmtdesc->index = idx;
- fmtdesc->type = type;
- fmtdesc->flags = flags;
- fmtdesc->pixelformat = pixfmt;
- strlcpy(fmtdesc->description, name, sizeof(fmtdesc->description));
+ error = uvideo_vs_negotiation(sc, 1);
+ if (error != USB_ERR_NORMAL_COMPLETION) {
+ sc->sc_fmtgrp_cur = fmtgrp_save;
+ sc->sc_fmtgrp_cur->frame_cur = frame_save;
+ return (EINVAL);
+ }
+ sc->sc_negotiated_flag = 1;
return (0);
}
static int
-uvideo_enum_fsizes(struct uvideo_softc *sc, struct v4l2_frmsizeenum *fsizes)
+uvideo_hw_enum_framesizes(void *arg, struct video_frmsizeenum *fse)
{
+ struct uvideo_softc *sc = arg;
int idx, found = 0;
- uint32_t index, pixel_format;
struct usb_video_frame_desc *frame;
- index = fsizes->index;
- pixel_format = fsizes->pixel_format;
-
for (idx = 0; idx < sc->sc_fmtgrp_num; idx++) {
- if (sc->sc_fmtgrp[idx].pixelformat == pixel_format) {
+ if (sc->sc_fmtgrp[idx].pixelformat == fse->pixelformat) {
found = 1;
break;
}
@@ -3245,36 +2755,28 @@
if (found == 0)
return (EINVAL);
- if (index >= (uint32_t)sc->sc_fmtgrp[idx].frame_num)
+ if (fse->index >= (uint32_t)sc->sc_fmtgrp[idx].frame_num)
return (EINVAL);
- bzero(fsizes, sizeof(*fsizes));
- fsizes->index = index;
- fsizes->pixel_format = pixel_format;
- fsizes->type = V4L2_FRMSIZE_TYPE_DISCRETE;
- frame = sc->sc_fmtgrp[idx].frame[index];
- fsizes->discrete.width = UGETW(UVIDEO_FRAME_FIELD(frame, wWidth));
- fsizes->discrete.height = UGETW(UVIDEO_FRAME_FIELD(frame, wHeight));
+ frame = sc->sc_fmtgrp[idx].frame[fse->index];
+ fse->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fse->discrete.width = UGETW(UVIDEO_FRAME_FIELD(frame, wWidth));
+ fse->discrete.height = UGETW(UVIDEO_FRAME_FIELD(frame, wHeight));
return (0);
}
static int
-uvideo_enum_fivals(struct uvideo_softc *sc, struct v4l2_frmivalenum *fivals)
+uvideo_hw_enum_frameintervals(void *arg, struct video_frmivalenum *fie)
{
+ struct uvideo_softc *sc = arg;
int idx;
struct uvideo_format_group *fmtgrp = NULL;
struct usb_video_frame_desc *frame = NULL;
uint8_t *p;
- uint32_t fi_index, fi_pixfmt, fi_width, fi_height;
-
- fi_index = fivals->index;
- fi_pixfmt = fivals->pixel_format;
- fi_width = fivals->width;
- fi_height = fivals->height;
for (idx = 0; idx < sc->sc_fmtgrp_num; idx++) {
- if (sc->sc_fmtgrp[idx].pixelformat == fi_pixfmt) {
+ if (sc->sc_fmtgrp[idx].pixelformat == fie->pixelformat) {
fmtgrp = &sc->sc_fmtgrp[idx];
break;
}
@@ -3284,9 +2786,9 @@
for (idx = 0; idx < fmtgrp->frame_num; idx++) {
if (UGETW(UVIDEO_FRAME_FIELD(fmtgrp->frame[idx], wWidth))
- == fi_width &&
+ == fie->width &&
UGETW(UVIDEO_FRAME_FIELD(fmtgrp->frame[idx], wHeight))
- == fi_height) {
+ == fie->height) {
frame = fmtgrp->frame[idx];
break;
}
@@ -3296,144 +2798,56 @@
p = (uint8_t *)frame + UVIDEO_FRAME_MIN_LEN(frame);
- bzero(fivals, sizeof(*fivals));
- fivals->index = fi_index;
- fivals->pixel_format = fi_pixfmt;
- fivals->width = fi_width;
- fivals->height = fi_height;
-
if (UVIDEO_FRAME_NUM_INTERVALS(frame) == 0) {
- if (fi_index != 0)
+ if (fie->index != 0)
return (EINVAL);
- fivals->type = V4L2_FRMIVAL_TYPE_STEPWISE;
- fivals->stepwise.min.numerator = UGETDW(p);
- fivals->stepwise.min.denominator = 10000000;
+ fie->type = V4L2_FRMIVAL_TYPE_STEPWISE;
+ fie->stepwise.min.numerator = UGETDW(p);
+ fie->stepwise.min.denominator = 10000000;
p += sizeof(uDWord);
- fivals->stepwise.max.numerator = UGETDW(p);
- fivals->stepwise.max.denominator = 10000000;
+ fie->stepwise.max.numerator = UGETDW(p);
+ fie->stepwise.max.denominator = 10000000;
p += sizeof(uDWord);
- fivals->stepwise.step.numerator = UGETDW(p);
- fivals->stepwise.step.denominator = 10000000;
+ fie->stepwise.step.numerator = UGETDW(p);
+ fie->stepwise.step.denominator = 10000000;
} else {
- if (fi_index >= (uint32_t)UVIDEO_FRAME_NUM_INTERVALS(frame))
+ if (fie->index >= (uint32_t)UVIDEO_FRAME_NUM_INTERVALS(frame))
return (EINVAL);
- p += sizeof(uDWord) * fi_index;
+ p += sizeof(uDWord) * fie->index;
if (p > frame->bLength + (uint8_t *)frame) {
device_printf(sc->sc_dev,
"frame desc too short?\n");
return (EINVAL);
}
- fivals->type = V4L2_FRMIVAL_TYPE_DISCRETE;
- fivals->discrete.numerator = UGETDW(p);
- fivals->discrete.denominator = 10000000;
+ fie->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fie->discrete.numerator = UGETDW(p);
+ fie->discrete.denominator = 10000000;
}
return (0);
}
static int
-uvideo_s_fmt(struct uvideo_softc *sc, struct v4l2_format *fmt)
+uvideo_hw_get_parm(void *arg, struct video_fract *fract)
{
- struct uvideo_format_group *fmtgrp_save;
- struct usb_video_frame_desc *frame_save;
- struct uvideo_res r;
- int found, i;
- usb_error_t error;
-
- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return (EINVAL);
-
- DPRINTFN(1, "s_fmt: requested %dx%d\n",
- fmt->fmt.pix.width, fmt->fmt.pix.height);
-
- /* Search requested pixel format */
- for (found = 0, i = 0; i < sc->sc_fmtgrp_num; i++) {
- if (fmt->fmt.pix.pixelformat == sc->sc_fmtgrp[i].pixelformat) {
- found = 1;
- break;
- }
- }
- if (found == 0)
- return (EINVAL);
-
- if (sc->sc_fmtgrp[i].frame_num == 0) {
- device_printf(sc->sc_dev, "no frame descriptors!\n");
- return (EINVAL);
- }
-
- uvideo_find_res(sc, i, fmt->fmt.pix.width, fmt->fmt.pix.height, &r);
-
- /* Save current format in case negotiation fails */
- fmtgrp_save = sc->sc_fmtgrp_cur;
- frame_save = sc->sc_fmtgrp_cur->frame_cur;
-
- sc->sc_fmtgrp_cur = &sc->sc_fmtgrp[i];
- sc->sc_fmtgrp[i].frame_cur = sc->sc_fmtgrp[i].frame[r.fidx];
-
- error = uvideo_vs_negotiation(sc, 1);
- if (error != USB_ERR_NORMAL_COMPLETION) {
- sc->sc_fmtgrp_cur = fmtgrp_save;
- sc->sc_fmtgrp_cur->frame_cur = frame_save;
- return (EINVAL);
- }
- sc->sc_negotiated_flag = 1;
-
- fmt->fmt.pix.width = r.width;
- fmt->fmt.pix.height = r.height;
- fmt->fmt.pix.sizeimage =
- UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
+ struct uvideo_softc *sc = arg;
- DPRINTFN(1, "s_fmt: offered %dx%d\n", r.width, r.height);
+ fract->numerator = UGETDW(sc->sc_desc_probe.dwFrameInterval);
+ fract->denominator = 10000000;
return (0);
}
static int
-uvideo_g_fmt(struct uvideo_softc *sc, struct v4l2_format *fmt)
-{
- struct usb_video_frame_desc *frame;
- uint32_t type;
-
- type = fmt->type;
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return (EINVAL);
-
- bzero(fmt, sizeof(*fmt));
- fmt->type = type;
- fmt->fmt.pix.pixelformat = sc->sc_fmtgrp_cur->pixelformat;
- fmt->fmt.pix.field = V4L2_FIELD_NONE;
-
- frame = sc->sc_fmtgrp_cur->frame_cur;
- fmt->fmt.pix.width = UGETW(UVIDEO_FRAME_FIELD(frame, wWidth));
- fmt->fmt.pix.height = UGETW(UVIDEO_FRAME_FIELD(frame, wHeight));
- fmt->fmt.pix.sizeimage =
- UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
-
- if (sc->sc_fmtgrp_cur->has_colorformat) {
- fmt->fmt.pix.colorspace = sc->sc_fmtgrp_cur->colorspace;
- fmt->fmt.pix.xfer_func = sc->sc_fmtgrp_cur->xfer_func;
- fmt->fmt.pix.ycbcr_enc = sc->sc_fmtgrp_cur->ycbcr_enc;
- }
-
-
- return (0);
-}
-
-static int
-uvideo_s_parm(struct uvideo_softc *sc, struct v4l2_streamparm *parm)
+uvideo_hw_set_parm(void *arg, struct video_fract *fract)
{
+ struct uvideo_softc *sc = arg;
usb_error_t error;
- if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- if (parm->parm.capture.timeperframe.numerator == 0 ||
- parm->parm.capture.timeperframe.denominator == 0)
- sc->sc_frame_rate = 0;
- else
- sc->sc_frame_rate =
- parm->parm.capture.timeperframe.denominator /
- parm->parm.capture.timeperframe.numerator;
- } else
- return (EINVAL);
+ if (fract->numerator == 0 || fract->denominator == 0)
+ sc->sc_frame_rate = 0;
+ else
+ sc->sc_frame_rate = fract->denominator / fract->numerator;
/* Renegotiate if needed */
if (sc->sc_negotiated_flag) {
@@ -3442,277 +2856,55 @@
return (EINVAL);
}
- /* Return current parameters (zeroes reserved fields) */
- return (uvideo_g_parm(sc, parm));
-}
-
-static int
-uvideo_g_parm(struct uvideo_softc *sc, struct v4l2_streamparm *parm)
-{
- uint32_t type;
-
- type = parm->type;
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return (EINVAL);
-
- bzero(parm, sizeof(*parm));
- parm->type = type;
- parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
- parm->parm.capture.capturemode = 0;
- parm->parm.capture.readbuffers = UVIDEO_MAX_BUFFERS;
- parm->parm.capture.timeperframe.numerator =
- UGETDW(sc->sc_desc_probe.dwFrameInterval);
- parm->parm.capture.timeperframe.denominator = 10000000;
+ fract->numerator = UGETDW(sc->sc_desc_probe.dwFrameInterval);
+ fract->denominator = 10000000;
return (0);
}
static int
-uvideo_enum_input(struct uvideo_softc *sc, struct v4l2_input *input)
+uvideo_hw_enum_input(void *arg, uint32_t index, struct video_input *inp)
{
- uint32_t idx;
- idx = input->index;
- if (idx != 0)
+ if (index != 0)
return (EINVAL);
- bzero(input, sizeof(*input));
- input->index = idx;
- strlcpy(input->name, "Camera Terminal", sizeof(input->name));
- input->type = V4L2_INPUT_TYPE_CAMERA;
- input->status = 0; /* no error */
- input->std = 0; /* no standard TV norms */
-
- return (0);
-}
-
-static int
-uvideo_s_input(struct uvideo_softc *sc, int input)
-{
-
- if (input != 0)
- return (EINVAL);
+ bzero(inp, sizeof(*inp));
+ inp->index = 0;
+ strlcpy(inp->name, "Camera Terminal", sizeof(inp->name));
+ inp->type = VIDEO_INPUT_TYPE_CAMERA;
return (0);
}
static int
-uvideo_g_input(struct uvideo_softc *sc, int *input)
+uvideo_hw_get_input(void *arg, uint32_t *index)
{
- *input = 0;
+ *index = 0;
return (0);
}
static int
-uvideo_reqbufs(struct uvideo_softc *sc, struct v4l2_requestbuffers *rb)
+uvideo_hw_set_input(void *arg, uint32_t index)
{
- int i, buf_size, buf_size_total;
- DPRINTFN(1, "reqbufs: count=%d\n", rb->count);
-
- if (rb->count == 0)
- return (EINVAL);
-
- if (sc->sc_mmap_count > 0 || sc->sc_mmap_buffer != NULL) {
- DPRINTFN(1, "mmap buffers already allocated\n");
+ if (index != 0)
return (EINVAL);
- }
-
- if (rb->count > UVIDEO_MAX_BUFFERS)
- sc->sc_mmap_count = UVIDEO_MAX_BUFFERS;
- else
- sc->sc_mmap_count = rb->count;
-
- buf_size = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
- buf_size_total = sc->sc_mmap_count * buf_size;
- buf_size_total = round_page(buf_size_total);
-
- sc->sc_mmap_buffer = contigmalloc(buf_size_total, M_USBDEV,
- M_WAITOK | M_ZERO, 0, ~0UL, PAGE_SIZE, 0);
- if (sc->sc_mmap_buffer == NULL) {
- device_printf(sc->sc_dev, "can't allocate mmap buffer!\n");
- sc->sc_mmap_count = 0;
- return (ENOMEM);
- }
- sc->sc_mmap_buffer_size = buf_size_total;
-
- DPRINTFN(1, "allocated %d bytes mmap buffer\n", buf_size_total);
-
- for (i = 0; i < sc->sc_mmap_count; i++) {
- sc->sc_mmap[i].buf = sc->sc_mmap_buffer + (i * buf_size);
-
- sc->sc_mmap[i].v4l2_buf.index = i;
- sc->sc_mmap[i].v4l2_buf.m.offset = i * buf_size;
- sc->sc_mmap[i].v4l2_buf.length = buf_size;
- sc->sc_mmap[i].v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- sc->sc_mmap[i].v4l2_buf.sequence = 0;
- sc->sc_mmap[i].v4l2_buf.field = V4L2_FIELD_NONE;
- sc->sc_mmap[i].v4l2_buf.memory = V4L2_MEMORY_MMAP;
- sc->sc_mmap[i].v4l2_buf.flags = V4L2_BUF_FLAG_MAPPED;
- }
-
- sc->sc_mmap_buffer_idx = 0;
- sc->sc_mmap_cur = NULL;
-
- rb->count = sc->sc_mmap_count;
- rb->capabilities = V4L2_BUF_CAP_SUPPORTS_MMAP;
-
return (0);
}
static int
-uvideo_querybuf(struct uvideo_softc *sc, struct v4l2_buffer *qb)
-{
-
- if (qb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- qb->memory != V4L2_MEMORY_MMAP ||
- qb->index >= sc->sc_mmap_count)
- return (EINVAL);
-
- bcopy(&sc->sc_mmap[qb->index].v4l2_buf, qb,
- sizeof(struct v4l2_buffer));
-
- return (0);
-}
-
-static int
-uvideo_qbuf(struct uvideo_softc *sc, struct v4l2_buffer *qb)
-{
-
- if (qb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- qb->memory != V4L2_MEMORY_MMAP ||
- qb->index >= sc->sc_mmap_count)
- return (EINVAL);
-
- sc->sc_mmap[qb->index].v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
- sc->sc_mmap[qb->index].v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
-
- DPRINTFN(2, "buffer %d ready for queueing\n", qb->index);
-
- return (0);
-}
-
-static int
-uvideo_dqbuf(struct uvideo_softc *sc, struct v4l2_buffer *dqb)
-{
- struct uvideo_mmap *mmap;
- int error;
-
- if (dqb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- dqb->memory != V4L2_MEMORY_MMAP)
- return (EINVAL);
-
- if (STAILQ_EMPTY(&sc->sc_mmap_q)) {
- error = tsleep(sc, PCATCH, "uvdqbuf", hz * 10);
- if (error)
- return (EINVAL);
- }
-
- mmap = STAILQ_FIRST(&sc->sc_mmap_q);
- if (mmap == NULL)
- return (EINVAL);
-
- bcopy(&mmap->v4l2_buf, dqb, sizeof(struct v4l2_buffer));
-
- mmap->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
- mmap->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
-
- DPRINTFN(2, "frame dequeued from index %d\n",
- mmap->v4l2_buf.index);
- STAILQ_REMOVE_HEAD(&sc->sc_mmap_q, q_frames);
-
- return (0);
-}
-
-static int
-uvideo_streamon(struct uvideo_softc *sc, int type)
-{
- usb_error_t error;
-
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return (EINVAL);
-
- if (sc->sc_streaming)
- return (0);
-
- sc->sc_vidmode = VIDMODE_MMAP;
-
- error = uvideo_vs_init(sc);
- if (error != USB_ERR_NORMAL_COMPLETION)
- return (EINVAL);
-
- mtx_lock(&sc->sc_mtx);
- sc->sc_streaming = 1;
- if (sc->sc_vs_cur->bulk_endpoint)
- usbd_transfer_start(sc->sc_xfer[0]);
- else {
- int i;
- for (i = 0; i < UVIDEO_IXFERS; i++)
- usbd_transfer_start(sc->sc_xfer[i]);
- }
- mtx_unlock(&sc->sc_mtx);
-
- return (0);
-}
-
-static int
-uvideo_streamoff(struct uvideo_softc *sc, int type)
-{
-
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return (EINVAL);
-
- if (!sc->sc_streaming)
- return (0);
-
- mtx_lock(&sc->sc_mtx);
- sc->sc_streaming = 0;
- mtx_unlock(&sc->sc_mtx);
-
- uvideo_vs_close(sc);
- uvideo_vs_free_frame(sc);
-
- return (0);
-}
-
-static int
-uvideo_try_fmt(struct uvideo_softc *sc, struct v4l2_format *fmt)
-{
- struct uvideo_res r;
- int found, i;
-
- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return (EINVAL);
-
- for (found = 0, i = 0; i < sc->sc_fmtgrp_num; i++) {
- if (fmt->fmt.pix.pixelformat == sc->sc_fmtgrp[i].pixelformat) {
- found = 1;
- break;
- }
- }
- if (found == 0)
- return (EINVAL);
-
- uvideo_find_res(sc, i, fmt->fmt.pix.width, fmt->fmt.pix.height, &r);
-
- fmt->fmt.pix.width = r.width;
- fmt->fmt.pix.height = r.height;
- fmt->fmt.pix.sizeimage = sc->sc_frame_buffer.buf_size;
-
- return (0);
-}
-
-static int
-uvideo_queryctrl(struct uvideo_softc *sc, struct v4l2_queryctrl *qctrl)
+uvideo_hw_query_control(void *arg, struct video_control_desc *qc)
{
+ struct uvideo_softc *sc = arg;
int i, ret = 0;
usb_error_t error;
uint8_t *ctrl_data;
uint16_t ctrl_len;
uint8_t unit_id;
- i = uvideo_find_ctrl(sc, qctrl->id);
+ i = uvideo_find_ctrl(sc, qc->id);
if (i == EINVAL)
return (i);
@@ -3722,18 +2914,15 @@
unit_id = sc->sc_desc_vc_pu_cur->bUnitID;
ctrl_len = uvideo_ctrls[i].ctrl_len;
- if (ctrl_len < 1 || ctrl_len > 4) {
- device_printf(sc->sc_dev,
- "invalid control length: %d\n", ctrl_len);
+ if (ctrl_len < 1 || ctrl_len > 4)
return (EINVAL);
- }
ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK | M_ZERO);
if (ctrl_data == NULL)
return (ENOMEM);
- qctrl->type = uvideo_ctrls[i].type;
- strlcpy(qctrl->name, uvideo_ctrls[i].name, sizeof(qctrl->name));
+ qc->type = uvideo_ctrls[i].type;
+ strlcpy(qc->name, uvideo_ctrls[i].name, sizeof(qc->name));
/* get minimum */
error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_MIN,
@@ -3745,15 +2934,15 @@
}
switch (ctrl_len) {
case 1:
- qctrl->minimum = uvideo_ctrls[i].sig ?
+ qc->minimum = uvideo_ctrls[i].sig ?
*(int8_t *)ctrl_data : *ctrl_data;
break;
case 2:
- qctrl->minimum = uvideo_ctrls[i].sig ?
+ qc->minimum = uvideo_ctrls[i].sig ?
(int16_t)UGETW(ctrl_data) : UGETW(ctrl_data);
break;
case 4:
- qctrl->minimum = uvideo_ctrls[i].sig ?
+ qc->minimum = uvideo_ctrls[i].sig ?
(int32_t)UGETDW(ctrl_data) : UGETDW(ctrl_data);
break;
}
@@ -3768,15 +2957,15 @@
}
switch (ctrl_len) {
case 1:
- qctrl->maximum = uvideo_ctrls[i].sig ?
+ qc->maximum = uvideo_ctrls[i].sig ?
*(int8_t *)ctrl_data : *ctrl_data;
break;
case 2:
- qctrl->maximum = uvideo_ctrls[i].sig ?
+ qc->maximum = uvideo_ctrls[i].sig ?
(int16_t)UGETW(ctrl_data) : UGETW(ctrl_data);
break;
case 4:
- qctrl->maximum = uvideo_ctrls[i].sig ?
+ qc->maximum = uvideo_ctrls[i].sig ?
(int32_t)UGETDW(ctrl_data) : UGETDW(ctrl_data);
break;
}
@@ -3791,15 +2980,15 @@
}
switch (ctrl_len) {
case 1:
- qctrl->step = uvideo_ctrls[i].sig ?
+ qc->step = uvideo_ctrls[i].sig ?
*(int8_t *)ctrl_data : *ctrl_data;
break;
case 2:
- qctrl->step = uvideo_ctrls[i].sig ?
+ qc->step = uvideo_ctrls[i].sig ?
(int16_t)UGETW(ctrl_data) : UGETW(ctrl_data);
break;
case 4:
- qctrl->step = uvideo_ctrls[i].sig ?
+ qc->step = uvideo_ctrls[i].sig ?
(int32_t)UGETDW(ctrl_data) : UGETDW(ctrl_data);
break;
}
@@ -3814,20 +3003,20 @@
}
switch (ctrl_len) {
case 1:
- qctrl->default_value = uvideo_ctrls[i].sig ?
+ qc->default_value = uvideo_ctrls[i].sig ?
*(int8_t *)ctrl_data : *ctrl_data;
break;
case 2:
- qctrl->default_value = uvideo_ctrls[i].sig ?
+ qc->default_value = uvideo_ctrls[i].sig ?
(int16_t)UGETW(ctrl_data) : UGETW(ctrl_data);
break;
case 4:
- qctrl->default_value = uvideo_ctrls[i].sig ?
+ qc->default_value = uvideo_ctrls[i].sig ?
(int32_t)UGETDW(ctrl_data) : UGETDW(ctrl_data);
break;
}
- qctrl->flags = 0;
+ qc->flags = 0;
out:
free(ctrl_data, M_USBDEV);
@@ -3835,15 +3024,16 @@
}
static int
-uvideo_g_ctrl(struct uvideo_softc *sc, struct v4l2_control *gctrl)
+uvideo_hw_get_control(void *arg, struct video_control *ctrl)
{
+ struct uvideo_softc *sc = arg;
int i, ret = 0;
usb_error_t error;
uint8_t *ctrl_data;
uint16_t ctrl_len;
uint8_t unit_id;
- i = uvideo_find_ctrl(sc, gctrl->id);
+ i = uvideo_find_ctrl(sc, ctrl->id);
if (i == EINVAL)
return (i);
@@ -3869,15 +3059,15 @@
}
switch (ctrl_len) {
case 1:
- gctrl->value = uvideo_ctrls[i].sig ?
+ ctrl->value = uvideo_ctrls[i].sig ?
*(int8_t *)ctrl_data : *ctrl_data;
break;
case 2:
- gctrl->value = uvideo_ctrls[i].sig ?
+ ctrl->value = uvideo_ctrls[i].sig ?
(int16_t)UGETW(ctrl_data) : UGETW(ctrl_data);
break;
case 4:
- gctrl->value = uvideo_ctrls[i].sig ?
+ ctrl->value = uvideo_ctrls[i].sig ?
(int32_t)UGETDW(ctrl_data) : UGETDW(ctrl_data);
break;
}
@@ -3888,15 +3078,16 @@
}
static int
-uvideo_s_ctrl(struct uvideo_softc *sc, struct v4l2_control *sctrl)
+uvideo_hw_set_control(void *arg, const struct video_control *ctrl)
{
+ struct uvideo_softc *sc = arg;
int i, ret = 0;
usb_error_t error;
uint8_t *ctrl_data;
uint16_t ctrl_len;
uint8_t unit_id;
- i = uvideo_find_ctrl(sc, sctrl->id);
+ i = uvideo_find_ctrl(sc, ctrl->id);
if (i == EINVAL)
return (i);
@@ -3916,15 +3107,15 @@
switch (ctrl_len) {
case 1:
if (uvideo_ctrls[i].sig)
- *(int8_t *)ctrl_data = sctrl->value;
+ *(int8_t *)ctrl_data = ctrl->value;
else
- *ctrl_data = sctrl->value;
+ *ctrl_data = ctrl->value;
break;
case 2:
- USETW(ctrl_data, sctrl->value);
+ USETW(ctrl_data, ctrl->value);
break;
case 4:
- USETDW(ctrl_data, sctrl->value);
+ USETDW(ctrl_data, ctrl->value);
break;
}
@@ -3937,3 +3128,51 @@
free(ctrl_data, M_USBDEV);
return (ret);
}
+
+static int
+uvideo_hw_start_stream(void *arg)
+{
+ struct uvideo_softc *sc = arg;
+ usb_error_t error;
+
+ if (sc->sc_vs_cur == NULL)
+ return (EIO);
+
+ sc->sc_sequence = 0;
+
+ error = uvideo_vs_open(sc);
+ if (error != USB_ERR_NORMAL_COMPLETION)
+ return (EIO);
+
+ error = uvideo_vs_alloc_frame(sc);
+ if (error != USB_ERR_NORMAL_COMPLETION) {
+ uvideo_vs_close(sc);
+ return (EIO);
+ }
+
+ mtx_lock(&sc->sc_mtx);
+ sc->sc_streaming = 1;
+ if (sc->sc_vs_cur->bulk_endpoint)
+ usbd_transfer_start(sc->sc_xfer[0]);
+ else {
+ int i;
+ for (i = 0; i < UVIDEO_IXFERS; i++)
+ usbd_transfer_start(sc->sc_xfer[i]);
+ }
+ mtx_unlock(&sc->sc_mtx);
+
+ return (0);
+}
+
+static void
+uvideo_hw_stop_stream(void *arg)
+{
+ struct uvideo_softc *sc = arg;
+
+ mtx_lock(&sc->sc_mtx);
+ sc->sc_streaming = 0;
+ mtx_unlock(&sc->sc_mtx);
+
+ uvideo_vs_close(sc);
+ uvideo_vs_free_frame(sc);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jul 28, 10:50 AM (1 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35648219
Default Alt Text
D58368.id182336.diff (52 KB)
Attached To
Mode
D58368: uvideo: convert to video(4) framework
Attached
Detach File
Event Timeline
Log In to Comment