Module Name:    src
Committed By:   riastradh
Date:           Thu Mar  3 06:22:53 UTC 2022

Modified Files:
        src/sys/dev/usb: uvideo.c

Log Message:
uvideo(4): Attach one video(4) per independent stream.


To generate a diff of this commit:
cvs rdiff -u -r1.67 -r1.68 src/sys/dev/usb/uvideo.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/uvideo.c
diff -u src/sys/dev/usb/uvideo.c:1.67 src/sys/dev/usb/uvideo.c:1.68
--- src/sys/dev/usb/uvideo.c:1.67	Thu Mar  3 06:22:40 2022
+++ src/sys/dev/usb/uvideo.c	Thu Mar  3 06:22:53 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvideo.c,v 1.67 2022/03/03 06:22:40 riastradh Exp $	*/
+/*	$NetBSD: uvideo.c,v 1.68 2022/03/03 06:22:53 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2008 Patrick Mahoney
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.67 2022/03/03 06:22:40 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.68 2022/03/03 06:22:53 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -210,6 +210,7 @@ struct uvideo_bulk_xfer {
 };
 
 struct uvideo_stream {
+	device_t		vs_videodev;
 	struct uvideo_softc	*vs_parent;
 	struct usbd_interface	*vs_iface;
 	uint8_t			vs_ifaceno;
@@ -236,6 +237,8 @@ struct uvideo_stream {
 	uint32_t		vs_max_payload_size;
 	uint32_t		vs_frame_interval;
 	SLIST_ENTRY(uvideo_stream) entries;
+
+	uvideo_state		vs_state;
 };
 SLIST_HEAD(uvideo_stream_list, uvideo_stream);
 
@@ -246,16 +249,11 @@ struct uvideo_softc {
         int     		sc_ifaceno;	/* interface number */
 	char			*sc_devname;
 
-	device_t		sc_videodev;
-
 	int			sc_dying;
-	uvideo_state		sc_state;
 
 	uint8_t			sc_nunits;
 	struct uvideo_unit	**sc_unit;
 
-	struct uvideo_stream	*sc_stream_in;
-
 	struct uvideo_stream_list sc_stream_list;
 
 	char			sc_businfo[32];
@@ -501,7 +499,6 @@ uvideo_attach(device_t parent, device_t 
 	sc->sc_iface = uiaa->uiaa_iface;
 	sc->sc_ifaceno = uiaa->uiaa_ifaceno;
 	sc->sc_dying = 0;
-	sc->sc_state = UVIDEO_STATE_CLOSED;
 	SLIST_INIT(&sc->sc_stream_list);
 	snprintf(sc->sc_businfo, sizeof(sc->sc_businfo), "usb:%08x",
 	    sc->sc_udev->ud_cookie.cookie);
@@ -574,8 +571,6 @@ uvideo_attach(device_t parent, device_t 
 					 usbd_errstr(err), err));
 				goto bad;
 			}
-			/* TODO: for now, set (each) stream to stream_in. */
-			sc->sc_stream_in = vs;
 			break;
 		case UISUBCLASS_VIDEOCOLLECTION:
 			err = uvideo_init_collection(sc, ifdesc, &iter);
@@ -606,9 +601,11 @@ uvideo_attach(device_t parent, device_t 
 	if (!pmf_device_register(self, NULL, NULL))
 		aprint_error_dev(self, "couldn't establish power handler\n");
 
-	sc->sc_videodev = video_attach_mi(&uvideo_hw_if, sc->sc_dev);
-	DPRINTF(("uvideo_attach: attached video driver at %p\n",
-		 sc->sc_videodev));
+	SLIST_FOREACH(vs, &sc->sc_stream_list, entries) {
+		/* XXX initialization of vs_videodev is racy */
+		vs->vs_videodev = video_attach_mi_softc(&uvideo_hw_if,
+		    sc->sc_dev, vs);
+	}
 
 	return;
 
@@ -642,21 +639,29 @@ static void
 uvideo_childdet(device_t self, device_t child)
 {
 	struct uvideo_softc *sc = device_private(self);
+	struct uvideo_stream *vs;
 
-	KASSERT(sc->sc_videodev == child);
-	sc->sc_videodev = NULL;
+	SLIST_FOREACH(vs, &sc->sc_stream_list, entries) {
+		if (child == vs->vs_videodev) {
+			vs->vs_videodev = NULL;
+			break;
+		}
+	}
+	KASSERTMSG(vs != NULL, "unknown child of %s detached: %s @ %p",
+	    device_xname(self), device_xname(child), child);
 }
 
 
 static int
 uvideo_detach(device_t self, int flags)
 {
-	struct uvideo_softc *sc;
+	struct uvideo_softc *sc = device_private(self);
 	struct uvideo_stream *vs;
-	int rv;
+	int error;
 
-	sc = device_private(self);
-	rv = 0;
+	error = config_detach_children(self, flags);
+	if (error)
+		return error;
 
 	sc->sc_dying = 1;
 
@@ -681,14 +686,11 @@ uvideo_detach(device_t self, int flags)
 	DPRINTFN(15, ("uvideo: detaching from %s\n",
 		device_xname(sc->sc_dev)));
 
-	if (sc->sc_videodev != NULL)
-		rv = config_detach(sc->sc_videodev, flags);
-
 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
 
 	usbd_devinfo_free(sc->sc_devname);
 
-	return rv;
+	return 0;
 }
 
 /* Search the stream list for a stream matching the interface number.
@@ -1039,6 +1041,7 @@ uvideo_stream_init(struct uvideo_stream 
 	vs->vs_default_format = NULL;
 	vs->vs_current_format.priv = -1;
 	vs->vs_xfer_type = 0;
+	vs->vs_state = UVIDEO_STATE_CLOSED;
 
 	err = usbd_device2interface_handle(sc->sc_udev, vs->vs_ifaceno,
 	    &vs->vs_iface);
@@ -1783,7 +1786,7 @@ uvideo_stream_recv_process(struct uvideo
 	payload.frameno = hdr->bmHeaderInfo & UV_FRAME_ID;
 	payload.end_of_frame = hdr->bmHeaderInfo & UV_END_OF_FRAME;
 
-	video_submit_payload(vs->vs_parent->sc_videodev, &payload);
+	video_submit_payload(vs->vs_videodev, &payload);
 
 	return USBD_NORMAL_COMPLETION;
 }
@@ -1881,13 +1884,10 @@ uvideo_stream_recv_bulk_transfer(void *a
 static int
 uvideo_open(void *addr, int flags)
 {
-	struct uvideo_softc *sc;
-	struct uvideo_stream *vs;
+	struct uvideo_stream *vs = addr;
+	struct uvideo_softc *sc = vs->vs_parent;
 	struct video_format fmt;
 
-	sc = addr;
-	vs = sc->sc_stream_in;
-
 	DPRINTF(("uvideo_open: sc=%p\n", sc));
 	if (sc->sc_dying)
 		return EIO;
@@ -1901,36 +1901,36 @@ uvideo_open(void *addr, int flags)
 static void
 uvideo_close(void *addr)
 {
-	struct uvideo_softc *sc;
-
-	sc = addr;
+	struct uvideo_stream *vs = addr;
 
 	uvideo_stop_transfer(addr);
 
-	if (sc->sc_state != UVIDEO_STATE_CLOSED) {
-		sc->sc_state = UVIDEO_STATE_CLOSED;
+	if (vs->vs_state != UVIDEO_STATE_CLOSED) {
+		vs->vs_state = UVIDEO_STATE_CLOSED;
 	}
 }
 
 static const char *
 uvideo_get_devname(void *addr)
 {
-	struct uvideo_softc *sc = addr;
-	return sc->sc_devname;
+	struct uvideo_stream *vs = addr;
+
+	return vs->vs_parent->sc_devname;
 }
 
 static const char *
 uvideo_get_businfo(void *addr)
 {
-	struct uvideo_softc *sc = addr;
-	return sc->sc_businfo;
+	struct uvideo_stream *vs = addr;
+
+	return vs->vs_parent->sc_businfo;
 }
 
 static int
 uvideo_enum_format(void *addr, uint32_t index, struct video_format *format)
 {
-	struct uvideo_softc *sc = addr;
-	struct uvideo_stream *vs = sc->sc_stream_in;
+	struct uvideo_stream *vs = addr;
+	struct uvideo_softc *sc = vs->vs_parent;
 	struct uvideo_format *video_format;
 	int off;
 
@@ -1956,8 +1956,8 @@ uvideo_enum_format(void *addr, uint32_t 
 static int
 uvideo_get_format(void *addr, struct video_format *format)
 {
-	struct uvideo_softc *sc = addr;
-	struct uvideo_stream *vs = sc->sc_stream_in;
+	struct uvideo_stream *vs = addr;
+	struct uvideo_softc *sc = vs->vs_parent;
 
 	if (sc->sc_dying)
 		return EIO;
@@ -1973,20 +1973,16 @@ uvideo_get_format(void *addr, struct vid
 static int
 uvideo_set_format(void *addr, struct video_format *format)
 {
-	struct uvideo_softc *sc;
-	struct uvideo_stream *vs;
+	struct uvideo_stream *vs = addr;
+	struct uvideo_softc *sc = vs->vs_parent;
 	struct uvideo_format *uvfmt;
 	uvideo_probe_and_commit_data_t probe, maxprobe;
 	usbd_status err;
 
-	sc = addr;
-
 	DPRINTF(("uvideo_set_format: sc=%p\n", sc));
 	if (sc->sc_dying)
 		return EIO;
 
-	vs = sc->sc_stream_in;
-
 	uvfmt =	uvideo_stream_guess_format(vs, format->pixel_format,
 					   format->width, format->height);
 	if (uvfmt == NULL) {
@@ -2090,8 +2086,7 @@ uvideo_set_format(void *addr, struct vid
 static int
 uvideo_try_format(void *addr, struct video_format *format)
 {
-	struct uvideo_softc *sc = addr;
-	struct uvideo_stream *vs = sc->sc_stream_in;
+	struct uvideo_stream *vs = addr;
 	struct uvideo_format *uvfmt;
 
 	uvfmt =	uvideo_stream_guess_format(vs, format->pixel_format,
@@ -2106,8 +2101,7 @@ uvideo_try_format(void *addr, struct vid
 static int
 uvideo_get_framerate(void *addr, struct video_fract *fract)
 {
-	struct uvideo_softc *sc = addr;
-	struct uvideo_stream *vs = sc->sc_stream_in;
+	struct uvideo_stream *vs = addr;
 
 	switch (vs->vs_frame_interval) {
 	case 41666:	/* 240 */
@@ -2149,12 +2143,9 @@ uvideo_set_framerate(void *addr, struct 
 static int
 uvideo_start_transfer(void *addr)
 {
-	struct uvideo_softc *sc = addr;
-	struct uvideo_stream *vs;
+	struct uvideo_stream *vs = addr;
 	int s, err;
 
-	/* FIXME: this function should be stream specific */
-	vs = SLIST_FIRST(&sc->sc_stream_list);
 	s = splusb();
 	err = uvideo_stream_start_xfer(vs);
 	splx(s);
@@ -2165,13 +2156,11 @@ uvideo_start_transfer(void *addr)
 static int
 uvideo_stop_transfer(void *addr)
 {
-	struct uvideo_softc *sc;
+	struct uvideo_stream *vs = addr;
 	int err, s;
 
-	sc = addr;
-
 	s = splusb();
-	err = uvideo_stream_stop_xfer(sc->sc_stream_in);
+	err = uvideo_stream_stop_xfer(vs);
 	splx(s);
 
 	return err;
@@ -2181,15 +2170,14 @@ uvideo_stop_transfer(void *addr)
 static int
 uvideo_get_control_group(void *addr, struct video_control_group *group)
 {
-	struct uvideo_softc *sc;
+	struct uvideo_stream *vs = addr;
+	struct uvideo_softc *sc = vs->vs_parent;
 	usb_device_request_t req;
 	usbd_status err;
 	uint8_t control_id, ent_id, data[16];
 	uint16_t len;
 	int s;
 
-	sc = addr;
-
 	/* request setup */
 	switch (group->group_id) {
 	case VIDEO_CONTROL_PANTILT_RELATIVE:
@@ -2243,15 +2231,14 @@ uvideo_get_control_group(void *addr, str
 static int
 uvideo_set_control_group(void *addr, const struct video_control_group *group)
 {
-	struct uvideo_softc *sc;
+	struct uvideo_stream *vs = addr;
+	struct uvideo_softc *sc = vs->vs_parent;
 	usb_device_request_t req;
 	usbd_status err;
 	uint8_t control_id, ent_id, data[16]; /* long enough for all controls */
 	uint16_t len;
 	int s;
 
-	sc = addr;
-
 	switch (group->group_id) {
 	case VIDEO_CONTROL_PANTILT_RELATIVE:
 		if (group->length != 4)

Reply via email to