summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authornetchild <netchild@FreeBSD.org>2010-01-15 14:58:19 +0000
committernetchild <netchild@FreeBSD.org>2010-01-15 14:58:19 +0000
commit9c3e54b694875c4ef4aea79ee6ebcb09fe1ef4fd (patch)
tree40bb33bbafa2e8d7f2beccc9c189b99722f1615e /sys/compat
parentd8e1c135e63b56479795e9754c33bd13b8028283 (diff)
downloadFreeBSD-src-9c3e54b694875c4ef4aea79ee6ebcb09fe1ef4fd.zip
FreeBSD-src-9c3e54b694875c4ef4aea79ee6ebcb09fe1ef4fd.tar.gz
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@opal.com>
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/linux/linux_ioctl.c113
1 files changed, 80 insertions, 33 deletions
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index 89b50e4..e6f6581 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -2624,7 +2624,6 @@ bsd_to_linux_v4l_tuner(struct video_tuner *vt, struct l_video_tuner *lvt)
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_clip *lvc, struct video_clip *vc)
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_code *lvc, struct video_code *vc)
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_window *vw)
}
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, struct linux_ioctl_args *args)
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:
OpenPOWER on IntegriCloud