# $Id: README,v 1.3 2007/02/09 08:48:43 luigi Exp $

This archive contains some headers and source files to help porting
linux drivers to FreeBSD (6.x and above).

The idea is that you should be able to take linux sources, write a
suitable Makefile.kld following the example at the end of this file,
and then build a working driver for FreeBSD.

In particular, our initial focus was on usb webcam drivers,
and so this emulation layer contains enough to create a character
driver using the services of the USB stack.

----------------------------------------------------------------------
	C U R R E N T    S T A T U S    (08 Feb 2007)

The code is working with three linux drivers so far (gspca, spca, ov511)
and we are slowly working on adding functions to build more drivers.
The various headers are being cleaned up removing useless stuff and
moving some definitions in more appropriate places.

Locking needs to be revised.

We can build an unmodified (apart from fixes for compiler warnings)
'gspca' linux driver into a loadable kld module, and display
the output on screen using e.g. the 'pwcview' program,
which is included for convenience in this package.

What remains to do is some cleanup of the locking, and add support
for BULK and other transfer types as the need arises.

------------------------------------------------------------------
	E M U L A T I O N    S T R A T E G Y

This project is made of several components, not all of them
needed in all drivers, nor all implemented so far. These are:

 1. Header files
    One thing that all linux drivers need is a suitable set of headers
    to provide all the definitions that are available in the original
    header files. Some of them are just empty placeholders,
    some are partial replicas of the corresponding linux headers,
    and some more are almost completely rewritten to remap linux
    structs and constants to FreeBSD types.
	The headers are under linux_compat/ in this archive,

 2. Generic kernel functions.
    There are some library functions that basically all kernel modules
    need. Some are already available on FreeBSD as libkern, others
    (e.g. printk and kmalloc etc.) are remapped using macros, some more
    are implemented by C functions.

 3. Specific kernel functions.
    These functions emulate the API of some kernel subsystems, e.g.
    mbufs, sockets, usb... They are implemented as the need arises,
    and the way to do it differs depending on the circumstances.

Emulation of kernel functions is trivial when there is a one-to-one
mapping to FreeBSD calls. Otherwise, e.g. when data structures differ,
it may be necessary to put small wrappers around the FreeBSD calls,
doing the necessary massaging of data - copying, remapping values, etc.

Finally, some cases are even harder because the equivalence is not
on single functions but on sets of them - in which case we need to
record the sequence of calls done by the linux driver, and when we
have enough information to perform the equivalent FreeBSD functions,
issue a number of FreeBSD calls to perform the task, possibly storing
the results and returning them to the linux driver a few at a time.
We had to follow this approach when emulating the functions of the
USB stack. The details are described in linux/usb.h and in the
source file (at the moment, linux_compat.c)

----------------------------------------------------------------------
		C O D E     L A Y O U T

The system is structured as follows.
Note that paths need to be revisited to make this installable as a port.
Also the content of some of the headers may be moved from one to
another in order to match better the original linux layout.

    linux_compat/
	contains the whole subtree (headers, sources, .mk files)

    linux_compat/linux/ linux_compat/asm
	adapted linux headers with enough definitions to
	compile stuff under FreeBSD

    linux_compat/linux_compat.c
	implementation of the linux function called by drivers.
	This may be expanded into multiple files for the various
	subsystem (memory, usb, pci, ...) as needed.
	In principle (and this is almost completely true even now),
	these files should be compilable as a library so they should
	have no dependency (also in terms of cpp magic) on the
	actual driver they are used for.

    linux_compat/ldev_stub.c, linux_compat/ldev_stub.h
	A template for a FreeBSD device driver that calls
	the wrappers for the linux functions.
	This should be recompiled each time, as there are some
	parts whose output depends on the preprocessor symbols,
	e.g. DRIVER_NAME and DEV_NAME.

    linux_compat/bsd.linux_kmod.mk
	bmake include file to be added at the end of the
	driver-specific Makefile.kld to add the required
	.PATH, CFLAGS and SRCS (see example at the end of this file).

----------------------------------------------------------------------
			U S A G E

In order to port a linux driver on FreeBSD, you should follow
these steps:

+ [this may change when this code becomes a FreeBSD port]
  extract this archive  in a work/ directory. With the exception of this
  README, everything ends up under linux_compat/ (note, you can
  use a different, system-wide place provided you set up the
  paths in Makefile.kld accordingly).

+ extract the driver you want to port into the same work/ directory.
  Depending on the structure of the driver it may extract just a few
  files, or a large number of subdirectories.

+ write a Makefile.kld using the template supplied at the end, with
  adaptation for the driver you want to build (at a minimum, add
  the list of sources and a driver name).

+ run "make -f Makefile.kld" to try and build the driver.
  If you are lucky, everything works and you end up with a .kld file.
  Most likely, you will encounter one or more of the following problems:

  - compiler error due to the strict checks we make (-Werror ...).
    You can usually remove them by adding missing prototypes,
    removing extra ones, and fixing the qualifiers (const etc) on
    arguments.

  - clashes between the FreeBSD and the Linux symbols (e.g. msleep() has
    different meaning on the two; the FreeBSD system headers define a
    "version" as a global symbol (string) while some Linux drivers appear
    to use it as a local variable; and so on.
    The fix of these errors depends on a case-by-case

  - missing function in the linux emulation library. We are only implementing
    what our sample drivers need, so it is likely that some parts are missing.
    Your best option is to look at some suitable linux distribution
    (e.g. http://www.gelato.unsw.edu.au/lxr/ ) to find out
    how to implement what is missing.
	The first step is to provide the prototype in some of the header
    files, and then a stub routine (returning an error) in some of the
    .c file, and then try to fill up the details.

  - error loading the module, typically because the kernel loader could
    not resolve some of the symbols. Fix is the same as above.

  - finally, even if everything loads, in order to achieve the desired
    functionality you are likely to need to implement in full some of
    the emulation functions for which we only provide stubs.

That's all... this is developer stuff!
 
------------------------------------------------------------------
		H I S T O R Y

2007.02.08
	Intercept the mmap-related ioctl and make them fail
	early, because we do not support mmap yet. This prevents
	ekiga from crashing.
	Move around the content of the header files trying
	to reduce the entanglement.
	
2007.02.04
	Made a FreeBSD port for the basic emulation code,
	devel/linux-kmod-compat, and two children ports for the
	gspca and ov511 drivers (multimedia/linux-gspca-kmod,
	multimedia/linux-ov511-kmod)

2007.01.30
	Video output is working! It took quite a bit of work to figure
	out a strange problem - isoc transfer interrupts were generated
	at a much lower rate than they should (e.g. every 140-150ms
	instead of 8-10ms). Turned out that the reason was that
	the sample driver i used has only 2 pending ISOC transfers,
	and on FreeBSD 6 at least they are not enough to keep the
	pipe streaming, presumably causing timeouts and recovery.
	Bumping the number of ISOC transfers to 3 fixes things.

	At this point 'gspca' and 'spca' are working almost fully,
	but only with open/read/ioctl/close, and using the ISOC pipe.
	select/poll/mmap are not implemented yet, nor are other
	(BULK, IRQ...) transfers. Locking needs to be revisited, too.

2007.01.28
	Full configuration is available to the linux emulation code.
	ISOC transfers are up and running, including tsleep/wakeup.
	We call the tasklet inline (should be done dropping the lock),
	but decoding reports an error with pwcview - not sure why,
	maybe a mismatch between formats.
	Still missing copy_to_user(), so no data would be passed to
	userland anyways. Also no select/poll support is available yet.

2007.01.27
	1. added hooks to the _open routine.
	2. added debugging code to parse the usb configuration.
	This needs to be extended to build the full descriptors
	required by the linux emulation code.

2007.01.26
	1. Implement the data structures required by the linux drivers
	as part of the softc. Provide the necessary linkage between
	these and the FreeBSD data structures. This enables the linux
	_probe routine (equivalent to the FreeBSD _attach) to complete.
	2. implement usb_control_message and usb_set_interface
	3. link the cdevsw functions to the softc so we can call them
	from the FreeBSD driver.
	4. misc cleanup to remove some useless includes and data structures.

2007.01.24
	Linked the _probe() routine to the usb_device table provided
	by the linux driver, so that device matching works.
	Implemented an initial wrapper for the linux attach routine
	(which is called probe). However, it does not yet provide a
	suitable emulation of the usb layer so it is simply instructed
	to fail.

2007.01.23
	Implemented stubs for all hooks needed by the gspca driver.
	You can now build and load it.
	
2007.01.22
	start of project
-------------------------------------------------------------------

----- example Makefile.kld (taken from gspca) -----

# Makefile.kld to build a driver with linux emulation.
# $Id: README,v 1.3 2007/02/09 08:48:43 luigi Exp $
#
# Here you should set the following:
#	.PATH:	driver-specific paths
#	SRCS=	list of (driver) source files that we want to compile.
#	KMOD=	driver name (one word, will be used also elsewhere).
#	CFLAGS=	any driver-specific flags you might need. Often
#		-Ixyz listing all directories with include files.
#
#	Any other driver-specific variables.

.PATH: ${.CURDIR} ${.CURDIR}/decoder 

# sources for the linux driver
SRCS= gspca_core.c gspcadecoder.c

KMOD=gspca

CFLAGS+= -ISunplus -ISunplus-jpeg -ISonix -IConexant
CFLAGS+= -IVimicro -Idecoder
CFLAGS+= -DUSB_DEBUG

#DEBUG_FLAGS=-g

#--- Here are the driver-specific variables

VERSION    = 01.00.12

###
# The following flags enable experimental features.
# By default, these are enabled for development versions of the driver, and
# disabled for release versions.

# Optional: Enable driver debugging
CFLAGS   += -DGSPCA_ENABLE_DEBUG

# Optional: Enable direct register read/write for PAC207 development
#CFLAGS   += -DGSPCA_ENABLE_REGISTERPLAY

###
# The following flags enable features that aren't yet implemented, and
# therefore are disabled by default.

# Optional: Enable compression
CFLAGS   += -DGSPCA_ENABLE_COMPRESSION

###
# Rest of Makefile follows here. You probably won't need to touch this.

# Setup defines
CFLAGS   += -DCONFIG_USB_GSPCA_MODULE=1 -D__KERNEL__
#CFLAGS   += -DCONFIG_USB_GSPCA_MODULE=1 -DMODULE -D__KERNEL__
CFLAGS   += -DVID_HARDWARE_GSPCA=0xFF -DGSPCA_VERSION=\"$(VERSION)\"

.include <linux_compat/bsd.linux_kmod.mk>

# -------- end of file ----------
