svn commit: r202364 - head/sys/compat/linux

Alexander Leidinger netchild at FreeBSD.org
Fri Jan 15 14:58:20 UTC 2010


Author: netchild
Date: Fri Jan 15 14:58:19 2010
New Revision: 202364
URL: http://svn.freebsd.org/changeset/base/202364

Log:
  This is v4l support for the linuxulator. This allows to access FreeBSD
  native devices which support the v4l API from processes running within
  the linuxulator, e.g. skype or flash can access the multimedia/pwcbsd driver.
  
  Not tested is firmware upload, framebuffer stuff and video tuner stuff
  due to lack of hardware.
  The clipping part (VIDIOCSWIN) needs a little bit of further work (partly
  in progress, but can not be tested due to lack of a suitable device).
  
  The submitter tested this sucessfully with Skype and flash apps on amd64 and
  i386 with the multimedia/pwcbsd driver.
  
  Submitted by:	J.R. Oldroyd <fbsd at opal.com>

Modified:
  head/sys/compat/linux/linux_ioctl.c

Modified: head/sys/compat/linux/linux_ioctl.c
==============================================================================
--- head/sys/compat/linux/linux_ioctl.c	Fri Jan 15 14:47:26 2010	(r202363)
+++ head/sys/compat/linux/linux_ioctl.c	Fri Jan 15 14:58:19 2010	(r202364)
@@ -2624,7 +2624,6 @@ bsd_to_linux_v4l_tuner(struct video_tune
 	return (0);
 }
 
-#if 0
 static int
 linux_to_bsd_v4l_clip(struct l_video_clip *lvc, struct video_clip *vc)
 {
@@ -2635,7 +2634,6 @@ linux_to_bsd_v4l_clip(struct l_video_cli
 	vc->next = PTRIN(lvc->next);	/* possible pointer size conversion */
 	return (0);
 }
-#endif
 
 static int
 linux_to_bsd_v4l_window(struct l_video_window *lvw, struct video_window *vw)
@@ -2696,29 +2694,21 @@ linux_to_bsd_v4l_code(struct l_video_cod
 	return (0);
 }
 
-#if 0
 static int
-linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw)
+linux_v4l_clip_copy(void *lvc, struct video_clip **ppvc)
 {
+	int error;
 	struct video_clip vclip;
 	struct l_video_clip l_vclip;
-	struct video_clip **ppvc;
-	struct l_video_clip *plvc;
-	int error;
 
-	ppvc = &(vw->clips);
-	for (plvc = (struct l_video_clip *) PTRIN(lvw->clips);
-	    plvc != NULL;
-	    plvc = (struct l_video_clip *) PTRIN(plvc->next)) {
-		error = copyin((void *) plvc, &l_vclip, sizeof(l_vclip));
-		if (error) return (error);
-		linux_to_bsd_v4l_clip(&l_vclip, &vclip);
-		/* XXX: If there can be no concurrency: s/M_NOWAIT/M_WAITOK/ */
-		if ((*ppvc = malloc(sizeof(**ppvc), M_LINUX, M_NOWAIT)) == NULL)
-			return (ENOMEM);    /* XXX: linux has no ENOMEM here */
-		memcpy(&vclip, *ppvc, sizeof(vclip));
-		ppvc = &((*ppvc)->next);
-	}
+	error = copyin(lvc, &l_vclip, sizeof(l_vclip));
+	if (error) return (error);
+	linux_to_bsd_v4l_clip(&l_vclip, &vclip);
+	/* XXX: If there can be no concurrency: s/M_NOWAIT/M_WAITOK/ */
+	if ((*ppvc = malloc(sizeof(**ppvc), M_LINUX, M_NOWAIT)) == NULL)
+		return (ENOMEM);    /* XXX: linux has no ENOMEM here */
+	memcpy(&vclip, *ppvc, sizeof(vclip));
+	(*ppvc)->next = NULL;
 	return (0);
 }
 
@@ -2734,7 +2724,71 @@ linux_v4l_cliplist_free(struct video_win
 	}
 	return (0);
 }
-#endif
+
+static int
+linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw)
+{
+	int error;
+	int clipcount;
+	void *plvc;
+	struct video_clip **ppvc;
+
+	/*
+	 * XXX: The cliplist is used to pass in a list of clipping
+	 *	rectangles or, if clipcount == VIDEO_CLIP_BITMAP, a
+	 *	clipping bitmap.  Some Linux apps, however, appear to
+	 *	leave cliplist and clips uninitialized.  In any case,
+	 *	the cliplist is not used by pwc(4), at the time of
+	 *	writing, FreeBSD's only V4L driver.  When a driver
+	 *	that uses the cliplist is developed, this code may
+	 *	need re-examiniation.
+	 */
+	error = 0;
+	clipcount = vw->clipcount;
+	if (clipcount == VIDEO_CLIP_BITMAP) {
+		/*
+		 * In this case, the pointer (clips) is overloaded
+		 * to be a "void *" to a bitmap, therefore there
+		 * is no struct video_clip to copy now.
+		 */
+	} else if (clipcount > 0 && clipcount <= 16384) {
+		/*
+		 * Clips points to list of clip rectangles, so
+		 * copy the list.
+		 *
+		 * XXX: Upper limit of 16384 was used here to try to
+		 *	avoid cases when clipcount and clips pointer
+		 *	are uninitialized and therefore have high random
+		 *	values, as is the case in the Linux Skype
+		 *	application.  The value 16384 was chosen as that
+		 *	is what is used in the Linux stradis(4) MPEG
+		 *	decoder driver, the only place we found an
+		 *	example of cliplist use.
+		 */
+		plvc = PTRIN(lvw->clips);
+		ppvc = &(vw->clips);
+		while (clipcount-- > 0) {
+			if (plvc == 0)
+				error = EFAULT;
+			if (!error)
+				error = linux_v4l_clip_copy(plvc, ppvc);
+			if (error) {
+				linux_v4l_cliplist_free(vw);
+				break;
+			}
+			ppvc = &((*ppvc)->next);
+		        plvc = PTRIN(((struct l_video_clip *) plvc)->next);
+		}
+	} else {
+		/*
+		 * clipcount == 0 or negative (but not VIDEO_CLIP_BITMAP)
+		 * Force cliplist to null.
+		 */
+		vw->clipcount = 0;
+		vw->clips = NULL;
+	}
+	return (error);
+}
 
 static int
 linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
@@ -2805,21 +2859,14 @@ linux_ioctl_v4l(struct thread *td, struc
 			return (error);
 		}
 		linux_to_bsd_v4l_window(&l_vwin, &vwin);
-#if 0
-		/*
-		 * XXX: some Linux apps call SWIN but do not store valid
-		 *	values in clipcount or in the clips pointer.  Until
-		 *	we have someone calling to support this, the code
-		 *	to handle the list of video_clip structures is removed.
-		 */
 		error = linux_v4l_cliplist_copy(&l_vwin, &vwin);
-#endif
-		if (!error)
-			error = fo_ioctl(fp, VIDIOCSWIN, &vwin, td->td_ucred, td);
+		if (error) {
+			fdrop(fp, td);
+			return (error);
+		}
+		error = fo_ioctl(fp, VIDIOCSWIN, &vwin, td->td_ucred, td);
 		fdrop(fp, td);
-#if 0
 		linux_v4l_cliplist_free(&vwin);
-#endif
 		return (error);
 
 	case LINUX_VIDIOCGFBUF:


More information about the svn-src-head mailing list