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>
This commit is contained in:
Alexander Leidinger 2010-01-15 14:58:19 +00:00
parent 1b2ef7353d
commit 0f6800b944

View File

@ -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: