linux_compat000755 000423 000000 00000000000 10673552325 013747 5ustar00luigiwheel000000 000000 linux_compat/Makefile000644 000423 000000 00000000614 10560652511 015460 0ustar00luigiwheel000000 000000 # # This is only the makefile for the 'pwcview' program, which is part of # the pwcbsd driver, available at http://raaf.atspace.org/ and distributed # under GPLv2. # # The version here has some minor modifications to select the palette, # and display two or four windows. CFLAGS= -Wall CFLAGS+= `/usr/local/bin/sdl-config --cflags --libs` -ljpeg CFLAGS+= -I. all: clean: rm pwcview pwcview.o linux_compat/README000644 000423 000000 00000027015 10563032553 014705 0ustar00luigiwheel000000 000000 # $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 # -------- end of file ---------- linux_compat/README.drivers000644 000423 000000 00000002462 10560340242 016353 0ustar00luigiwheel000000 000000 # # $Id: README.drivers,v 1.1 2007/02/01 10:27:46 luigi Exp $ # Information/url and drivers ported or to port. In most cases poll/select and mmap don't work because the infrastructure is not ready yet. gspca: http://mxhaard.free.fr/spca50x/Download/gspcav1-20070110.tar.gz Works on several cameras i tried: 0x093a 0x2468 Trust WB-1200p (Mini Webcam) 352x288 0x041e 0x403b Creative Vista VF0010 352x288 0x046d 0x092c Creative S561-based 352x288 0x046d 0x08da Logitech quickcam messenger 640x480 (black) 0x046d 0x092f Logitech quickcam express 352x288 (white) beware, the two quickcams above look the same apart from the color but the black one is 640x480. recognised but not working (no video) 0x0733 0x0401 Intel 'Create and Share' Model No. CS330. 640x480 qc: from the linux source tree Tested with: 0x05a9 0xa511 Creative Webcam CT6840 (Part no. 1168403000) 352x288 Not ported yet: --- uvcvideo: http://mxhaard.free.fr/spca50x/Investigation/uvc/uvcvideo-r75.tar.gz compiles but some stub functions are missing. qce-ga: http://www.mirrorservice.org/sites/download.sourceforge.net/pub/sourceforge/q/qc/qce-ga/qc-usb-0.6.6.tar.gz --- OTHER CAMERAS --- 0x0c45 0x624f Trust WB5500 1.3mpix usbd2 ? 0x046d 0x0870 Dexxa webcam, perhaps works on qce-ga ? 0xeb1a 0x2820 Lidl 1.3mpix (Empia driver ?) linux_compat/bsd.linux_kmod.mk000644 000423 000000 00000002672 10560652511 017277 0ustar00luigiwheel000000 000000 # bsd.linux_kmod.mk to build a driver with linux emulation. # $Id: bsd.linux_kmod.mk,v 1.5 2007/02/02 15:14:17 luigi Exp $ # # .include file for compiling linux drivers on FreeBSD. The caller should # set the following # # .PATH: driver-specific paths with extra sources # 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 you will need # -I... for subdirectories with extra headers. # Any other driver-specific variables. # # DEV_NAME= device name for the driver (defaults to \"video\" ) # KMODDIR= install location (defaults to /dev/modules) # # and then .include # Here we add the necessary hooks to the linux emulation layer. You # should not change anything below this line. # Path to the linux compat library. Should not be changed. KLINPATH?= ${.CURDIR}/linux_compat .PATH: ${KLINPATH} # location of extra sources # The extra sources we link with the linux driver SRCS+=bus_if.h device_if.h opt_usb.h SRCS+= ldev_stub.c linux_compat.c DEV_NAME?=\"video\" # default name for /dev entry KMODDIR?=/boot/modules # default install location CFLAGS+= -D__KERNEL__ # compile kernel part of the linux headers CFLAGS+= -I${KLINPATH} # where to look for headers # pass the driver name and device name to the driver CFLAGS+= -DDRIVER_NAME=${KMOD} -DDEV_NAME=${DEV_NAME} .include linux_compat/ldev_stub.c000644 000423 000000 00000037152 10563047135 016165 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id: ldev_stub.c,v 1.27 2007/02/09 10:35:09 luigi Exp $ * * This file implement the necessary functions to implement a * device driver as a loadable FreeBSD module, and on the other * side provides sufficient hooks to Linux device drivers to be linked * and operate as expected. * * compile with the following macros * * -DDEV_NAME="video" device name (with quotes) * -DDRIVER_NAME=foo driver name (without_quotes) * make sure ldev_devs is the array of ldev_info with vendor/prod identifiers * to be used for matching the device. */ #include #include SYSCTL_NODEn(_debug, OID_AUTO, DRIVER_NAME, CTLFLAG_RW, 0, "ldev controls"); /* * Fetch the unit number from the device. With devfs we cannot rely on * minor device numbers, but the minor() function does the job for us. */ #define LDEVUNIT(dev) (minor(dev)) /* * Forward declarations for the driver hooks, and the cdevs structure * containing them. This is passed as an argument to make_dev */ static d_open_t ldev_open; static d_close_t ldev_close; static d_read_t ldev_read; static d_ioctl_t ldev_ioctl; static d_mmap_t ldev_mmap; static d_poll_t ldev_poll; static struct cdevsw ldev_cdevsw = { .d_version = D_VERSION, .d_flags = D_NEEDGIANT, .d_open = ldev_open, .d_close = ldev_close, .d_read = ldev_read, .d_ioctl = ldev_ioctl, .d_poll = ldev_poll, .d_mmap = ldev_mmap, .d_name = __stringify(DRIVER_NAME), }; /* * Declare the _match, _attach, _detach methods; * define XXX_methods() and fill with the above, * define XXX_devclass, XXX_driver and link with the methods. * Among other things, write sizeof(ldev_softc) in the driver_t * associated to this driver, so that the allocation of the softc * can be done automatically. */ USB_DECLARE_DRIVER(ldev); /* * MODINFO_NAME(info) generates a unique name dependend on the driver's * name DRIVER_NAME. We use it to store device specific information from * the linux driver, stored directly or collected form a linker dataset * at the beginning of modevent_handler(). * We need the variable to be globally visible because other source * files must access it, and the macro allows us to avoid name clashes * when the driver is statically linked in the kernel. * Locally, we use a static variable to avoid obfuscating the source. */ struct linux_dev_info MODINFO_NAME(info); static struct linux_dev_info *linux_dev_info = &MODINFO_NAME(info); /* * device lookup routine. * In a standard driver we would just have the following code: static struct ldev_info ldev_devs[] = { { { vend1, prod1}, other_data }, // one or more entries { { 0, 0} }, // terminator just in case }; #define ldev_lookup(v, p, sc) \ ((const struct ldev_info *)usb_lookup(ldev_devs, v, sc)) * In the linux driver, the table is sliglthy different so we * need to write our own loop, which is implemented in the * library and passed a pointer to the table. */ /* * Rather than dereferencing the usbd_*_handle fields, * use the usbd_get_... functions. * If you really cannot, you need to include these two files: #include #include */ /* * some debugging functions to print the status of a device */ static void ldev_print_iface(usbd_interface_handle iface) { usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usbd_interface2device_handle(iface, &dev); printf("%s: iface %p device %p altindex %d\n", __FUNCTION__, iface, dev, usbd_get_interface_altindex(iface)); printf("\tnum %d alt %d ep %d class %d int %d prot %d iInt %d\n", id->bInterfaceNumber, id->bAlternateSetting, id->bNumEndpoints, id->bInterfaceClass, id->bInterfaceSubClass, id->bInterfaceProtocol, id->iInterface); } static void ldev_print_device(usbd_device_handle udev) { usb_device_descriptor_t *udd = usbd_get_device_descriptor(udev); // usb_config_descriptor_t *ucd = udev->cdesc; int nc = udd->bNumConfigurations; printf("%s: dev %p configs %d\n", __FUNCTION__, udev, nc); } static void ldev_print_info(struct usb_attach_arg *uaa) { int ni; printf("%s: 0x%04x: 0x%04x port %d config %d iface %d nifaces %d\n", __FUNCTION__, uaa->vendor, uaa->product, uaa->port, uaa->configno, uaa->ifaceno, uaa->nifaces); ldev_print_device(uaa->device); printf("\tdevice %p ifaces %p\n", uaa->device, uaa->ifaces); for (ni = 0; ni < uaa->nifaces; ni++) { printf("\tthis if %p [%d] %p\n", uaa->iface, ni, uaa->ifaces[ni]); } if (uaa->ifaceno >= 0 && uaa->iface != NULL) ldev_print_iface(uaa->iface); } static int ldev_match(device_t dev) { // struct ldev_softc *sc = device_get_softc(dev); struct usb_attach_arg *uaa = device_get_ivars(dev); usb_interface_descriptor_t *id; if (0) ldev_print_info(uaa); if (ldev_lookup(dev, linux_dev_info->device_table) == NULL) return UMATCH_NONE; /* * Driver loaded when device was already plugged in, * we have to claim all interfaces or get none... */ if (uaa->usegeneric) return UMATCH_VENDOR_PRODUCT; /* We don't want all interfaces */ if (uaa->iface == NULL) return UMATCH_NONE; id = usbd_get_interface_descriptor(uaa->iface); if (id == NULL) { printf("ldev: failed to get interface descriptor\n"); return UMATCH_NONE; } if (id->bInterfaceNumber != 0) return UMATCH_NONE; return UMATCH_VENDOR_PRODUCT; } static int ldev_attach(device_t dev) { struct ldev_softc *sc = device_get_softc(dev); struct usb_attach_arg *uaa = device_get_ivars(dev); char devinfo[1024]; const char *tmpstr; const struct usb_device_id *info; int unit = device_get_unit(dev); const struct usb_driver *dp; /* set up udev early so the lookup/attach routine can do more */ sc->udev = uaa->device; sc->sc_iface = uaa->iface; sc->sc_dev = dev; printf("%s: sc at %p, l_u_d at %p\n", __FUNCTION__, sc, &sc->l_u_d); info = ldev_lookup(dev, linux_dev_info->device_table); if (info == NULL) { device_printf(dev, "attach error vendor/product mismatch (vendor=0x%x product=0x%x)\n", uaa->vendor,uaa->product); return ENXIO; } if(uaa->iface == NULL) { device_printf(dev, "attach: iface is NULL\n"); return ENXIO; } /* prepare the linux emulation layer */ if (fill_linux_descriptors(dev, &sc->l_u_d)) { device_printf(dev, "attach: failed to allocate linux desc\n"); return ENOMEM; } /* prepare to call the linux routine */ dp = linux_dev_info->usb_driver_desc; if (dp == NULL || dp->probe == NULL) { device_printf(dev, "linux attach missing, sorry\n"); return ENXIO; } if (dp->probe(&sc->l_u_d.intf, info) != 0) { device_printf(dev, "linux attach failed, sorry\n"); return ENXIO; } usbd_devinfo(uaa->device, 0, devinfo); device_set_desc_copy(dev, devinfo); device_printf(dev, "%s\n", devinfo); mtx_init(&sc->ptrlock,device_get_name(sc->sc_dev),NULL,MTX_DEF); resource_string_value(__stringify(DRIVER_NAME), unit, "devname", &tmpstr); sc->sc_dev_t = make_dev(&ldev_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0666, "%s%d", DEV_NAME, unit); /* call the attach routine (where ???) */ usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->udev,USBDEV(sc->sc_dev)); return 0; /* success */ } static int ldev_detach(device_t dev) { struct ldev_softc *sc = device_get_softc(dev); sc->error_status = EPIPE; /* record detaching */ /* wait for userland to really close */ while (sc->vopen) { if(sc->state & LDEV_ASLEEP) wakeup(sc); if(sc->state & LDEV_POLL) { sc->state &= ~LDEV_POLL; selwakeuppri(&sc->rsel,PZERO); } device_printf(sc->sc_dev, "Disconnected while device is in use!\n"); usb_detach_wait(USBDEV(sc->sc_dev)); } /* free resources etc. */ if (sc->l_u_d.mem) /* memory allocated for linux emulation */ free(sc->l_u_d.mem, M_USBDEV); if(sc->sc_dev_t != NULL) destroy_dev(sc->sc_dev_t); mtx_destroy(&sc->ptrlock); /* free memory ? */ usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->udev,USBDEV(sc->sc_dev)); return 0; } static int ldev_open(struct cdev *dev, int flag, int mode, usb_proc_ptr p) { int err = 0; int unit = LDEVUNIT(dev); struct ldev_softc *sc = devclass_get_softc(ldev_devclass, unit); if (sc == NULL) return ENXIO; if (sc->error_status == EPIPE) /* detach in progress */ return sc->error_status; /* if vopen is 0, set to 1 and return success */ if (atomic_cmpset_int(&sc->vopen, 0, 1) == 0) /* already open */ return EBUSY; err = -sc->l_u_d.fops->open((struct inode *)sc, &sc->l_u_d.file); if (err) goto bad; /* FILL HERE: fire the device */ return 0; bad: /* free memory */ sc->vopen = 0; return err; } /* Watch out for races between close and detach */ static int ldev_close(struct cdev *dev, int flag, int mode, usb_proc_ptr p) { int unit = LDEVUNIT(dev); struct ldev_softc *sc = devclass_get_softc(ldev_devclass, unit); int err; if (sc == NULL) return ENXIO; err = -sc->l_u_d.fops->release((struct inode *)sc, &sc->l_u_d.file); sc->vopen = 0; usb_detach_wakeup(USBDEV(sc->sc_dev)); /* if a detach is pending */ return err; } static int ldev_read(struct cdev *dev, struct uio *uio, int flag) { int unit = LDEVUNIT(dev); struct ldev_softc *sc = devclass_get_softc(ldev_devclass, unit); int count = uio->uio_resid; int err; if (sc->error_status) return sc->error_status; /* * call the linux handler, using 'buf' as an alias to the * struct uio, which in the end is passed to copy_to_user. * Note, the linux routine returns the number of bytes read. */ err = sc->l_u_d.fops->read(&sc->l_u_d.file, (char *)uio, count, NULL); #if 0 if(1 /* sc->image_read_pos == 0 */) { while ((err = wait_data(sc)) == EBUSY) { if(flag & O_NONBLOCK) return EWOULDBLOCK; sc->state |= LDEV_ASLEEP; err = tsleep(sc, PZERO | PCATCH, "ldevrd", 0); sc->state &= ~LDEV_ASLEEP; if(sc->error_status) return sc->error_status; else if(err) return err; } if(err) return err; } err = uiomove(sc->data_src, count, uio); #endif return 0; /* no errors for the time being... */ } /* * This should not be here, but on the other hand we are only * doing webcams now... we want to know the ioctls used for them * in order to filter out some. */ #include #include static int ldev_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p) { int unit = LDEVUNIT(dev); struct ldev_softc *sc = devclass_get_softc(ldev_devclass, unit); int err; if (sc->error_status) return sc->error_status; printf("%s: called\n", __FUNCTION__); /* call the device-specific ioctl handler */ /* * filter out some non-implemented commands */ switch (cmd) { case VIDIOCGMBUF: case VIDIOCMCAPTURE: case VIDIOCSYNC: /* mmap not implemented yet, so fail */ return EINVAL; } err = -sc->l_u_d.fops->ioctl((struct inode *)sc, &sc->l_u_d.file, cmd, (unsigned long)addr); return err; } /* XXX this is still incomplete */ static int ldev_poll(struct cdev *dev, int events, usb_proc_ptr p) { int unit = LDEVUNIT(dev); struct ldev_softc *sc = devclass_get_softc(ldev_devclass, unit); int revents = 0; printf("%s: called\n", __FUNCTION__); if(sc->error_status) return sc->error_status; if (events & (POLLIN | POLLRDNORM)) { mtx_lock(&sc->ptrlock); if(sc->full_frames == NULL) { sc->state |= LDEV_POLL; selrecord(p,&sc->rsel); } else { revents |= events & (POLLIN | POLLRDNORM); } mtx_unlock(&sc->ptrlock); } if (events & (POLLOUT | POLLWRNORM)) { /* write is not allowed, so no point blocking on it */ revents |= events & (POLLOUT | POLLWRNORM); } return revents; } static int ldev_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot) { #ifdef USE_MMAP int unit = LDEVUNIT(dev); struct ldev_softc *sc = devclass_get_softc(ldev_devclass, unit); if (sc == NULL) return ENXIO; if (sc->error_status) return sc->error_status; if(nprot & PROT_EXEC || sc->image_data == NULL || offset < 0 || offset >= sc->pwc_mbufs * round_page(sc->len_per_image)) return -1; *paddr = vtophys(((char*)sc->image_data) + offset); return 0; #else return ENXIO; #endif } static int modevent_handler(module_t mod, int what, void *arg) { struct linux_dev_info *i = linux_dev_info; linux_devinfo_init(i); switch (what) { case MOD_LOAD: if (i->init_f) i->init_f(); break; case MOD_UNLOAD: if (i->exit_f) i->exit_f(); break; case MOD_QUIESCE: /* called before module_unload */ return 0; } return 0; } /* * we need to call tsleep, which in the linux emulation is a #define, * so we call it from a wrapper. * XXX todo: make wc have a reference to */ int wait_event_body(void *wc, int flags) { int err; if (flags & O_NONBLOCK) return EWOULDBLOCK; // sc->state |= PWC_ASLEEP; if (0) DBG("calling tsleep on %p\n", wc); err = tsleep(wc, PZERO | PCATCH, "lmod", 0); //sc->state &= ~PWC_ASLEEP; return err; } #define __A(x, a, b, c, d, e) DRIVER_MODULE(x , a, b,c,d,e) __A(DRIVER_NAME, uhub, ldev_driver, ldev_devclass, modevent_handler, 0); // DRIVER_MODULE(DRIVER_NAME, uhub, ldev_driver, ldev_devclass, modevent_handler, 0); linux_compat/ldev_stub.h000644 000423 000000 00000011730 10776737726 016206 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id: ldev_stub.h,v 1.20 2008/04/08 18:56:22 luigi Exp $ * * This is a header file to implement the necessary functions for a * device driver as a loadable FreeBSD module, and on the other * side provides sufficient hooks to Linux device drivers to be linked * and operate as expected. * * compile with the following macros * * -DDEV_NAME="video" device name (with quotes) * -DDRIVER_NAME=foo driver name (without quotes) * make sure ldev_devs is the array of ldev_info with vendor/prod identifiers * to be used for matching the device. */ #ifndef _LDEV_STUB_H #define _LDEV_STUB_H #include #include #include #include #include #include #include // #include #include #include #include /* uiomove */ /* probably needed later when implementing malloc */ // #include // #include // #include // #include // #include #include #include #include #include #include /* DBG macro and more */ #include /* linux types */ #include /* linker set and module_init */ #include #include #include #include /* struct file_operations */ #include /* this is targeted to usb... */ #define LDEV_ASLEEP 1 #define LDEV_INIT 2 #define LDEV_POLL 4 /* * We store here the various descriptors that linux expects, * and a pointer back to the FreeBSD usb device for use in the * emulation layer. * On top, there are the corresponding FreeBSD descriptors */ #define MAX_IF_ALTSETTINGS 16 struct linux_usb_descriptors { const struct file_operations *fops; usbd_interface_handle iface; usbd_device_handle udev; usbd_pipe_handle bsd_pipe; /* pipe used for streaming */ void *mem; /* malloced space for linux usb descriptors */ /* linux fields */ struct usb_interface intf; struct usb_device p_dev; /* parent device ? */ struct file file; }; /* * given a linux_usb_device pointer (l_dev), returns the corresponding * usbd_device_handle or usbd_interface_handle - assumes that l_dev is part * of a properly initialized struct linux_usb_descriptors * * The first macro returns the struct pointer, later to be mapped * to usbd_device_handler or usbd_interface_handle */ #define ludev_to_l_u_d(l_dev) \ ((struct linux_usb_descriptors *)container_of(l_dev, \ struct linux_usb_descriptors, p_dev)) #define ludev_to_udev(l_dev) (ludev_to_l_u_d(l_dev)->udev) #define ludev_to_iface(l_dev) (ludev_to_l_u_d(l_dev)->iface) /* * Device descriptor. Store here various information acquired through * during the attach phase, so that they are later available in the * cdevsw handlers. */ struct ldev_softc { device_t sc_dev; /* FreeBSD device */ struct cdev *sc_dev_t; struct selinfo rsel; usbd_device_handle udev; /* usb device for this interface */ usbd_interface_handle sc_iface; /* our interface */ int error_status; int vopen; int state; struct mtx ptrlock; /* for manipulating the buffer pointers */ /* * next is for the linux emulation structs, which must be * persistent. */ struct linux_usb_descriptors l_u_d; void *data_src; void *full_frames; /* poll placeholder */ /* other private data */ }; void usbd_dump_pipe(usbd_pipe_handle pipe); /* debug */ #endif /* _LDEV_STUB_H */ linux_compat/linux_compat.c000644 000423 000000 00000103470 10776737726 016717 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id: linux_compat.c,v 1.71 2008/04/08 18:56:22 luigi Exp $ * * This file implement an adaptation layer to compile linux usb device * drivers as loadable kernel modules on FreeBSD. * The headers provide macros and definitions, whereas this file maps the * internal linux API into equivalent (more or less) FreeBSD calls. * * compile with the following macros * * -DDEV_NAME="video" device name * -DDRIVER_NAME="foo" driver name * make sure ldev_devs is the array of ldev_info with vendor/prod identifiers * to be used for matching the device. */ #include #include #include #include #include /* vmalloc_to_page */ #include /* schedule */ #include /* video device.video device.. */ /* * note- here we use the linux-like 'struct usb device' * not the freebsd one */ #include /* jiffies support */ /* * msleep(ms) is different on FreeBSD. In the linux headers we remap * it to linux_msleep() through a macro, and implement the function here * after undefining the macro. */ #ifdef msleep #undef msleep #endif void linux_msleep(int ms) { #if __FreeBSD_version > 700100 _sleep("linux-msleep", NULL, 0 /* PRI */, #else /* call the FreeBSD msleep */ msleep("linux-msleep", NULL, 0 /* PRI */, #endif "linmsleep", 1+((ms)*hz)/1000); } /* * Here are routines called by the FreeBSD * template driver. */ static const char * eptype(int t) { static const char *names[] = { "CONTROL", "ISOC", "BULK", "INTR" }; return names[t & 3]; } /* * Parse the configuration. If passed a non-null LD, also allocate * and fill the struct needed for linux (for interface ifno. * This is done in two passes: in the first pass count items, then allocate * a single block of memory, then fill memory as required. * Printing is enabled on first pass if ld = NULL. * We only allocate for interface ifno, even if printing occurs * for all of them. */ static void parse_full_config(usb_config_descriptor_t *cdesc, int ifno, struct linux_usb_descriptors *ld) { int pass, lim = (ld ? 2 : 1); /* how many passes */ int nintf = 0; /* total number of interfaces */ /* for our interface: number of alternate configs (nalt), * number of endpoints for each config (neps) and total * number of endpoints (nep). */ int ifbitmap = 0; /* bitmap of interfaces we found */ int nalt = 0, neps[16], nep = 0, cur_alt = -1; /* * these two are used in the second pass to update the * relevant linux emulation descriptors */ struct usb_host_endpoint *next_ep = NULL; struct usb_host_interface *next_alt = NULL; if (cdesc == NULL) return; bzero(neps, sizeof(neps)); for (pass = 0; pass < lim; pass++) { char *p = (char *)cdesc; char *end = p + UGETW(cdesc->wTotalLength); usb_interface_descriptor_t *id = (usb_interface_descriptor_t *)p; usb_device_descriptor_t *dd; usb_config_descriptor_t *cd; usb_string_descriptor_t *sd; usb_endpoint_descriptor_t *ed; int ifnum; int do_print = 0 && (lim == 1); /* XXX set 0 to 1 to print */ for (; p + id->bLength <= end; p += id->bLength) { /* XXX check sizes */ id = (usb_interface_descriptor_t *)p; switch(id->bDescriptorType) { default: if (do_print) /* print only */ printf("unknown desc 0x%x len %d ", id->bDescriptorType, id->bLength); break; case UDESC_DEVICE: dd = (usb_device_descriptor_t *)p; if (do_print) printf("DEVICE, nconf %d proto %d maxpkt 0x%x", dd->bNumConfigurations, dd->bDeviceProtocol, dd->bMaxPacketSize); break; case UDESC_CONFIG: cd = (usb_config_descriptor_t *)p; if (do_print) printf("CONFIG, int %d confval %d conf %d", cd->bNumInterface, cd->bConfigurationValue, cd->iConfiguration); break; case UDESC_STRING: sd = (usb_string_descriptor_t *)p; if (do_print) printf("STRING, len %d", sd->bLength); break; case UDESC_INTERFACE: id = (usb_interface_descriptor_t *)p; ifnum = id->bInterfaceNumber; if (pass == 0 && (ifbitmap & (1<bAlternateSetting; if (pass == 1) { /* set */ /* second pass, set the endpoints */ next_alt->desc = *(struct usb_interface_descriptor *)p; next_alt->endpoint = next_ep; if (0) printf("alt %d has %d enpoints (%d)\n", cur_alt, neps[cur_alt], next_alt->desc.bNumEndpoints); next_alt++; } nalt++; } if (do_print) { printf("INTF, num %d alt %d n_ep %d", id->bInterfaceNumber, id->bAlternateSetting, id->bNumEndpoints); } break; case UDESC_ENDPOINT: ed = (usb_endpoint_descriptor_t *)p; if (pass == 0 && cur_alt != -1) { nep++; neps[cur_alt]++; } if (pass == 1) { /* fill the endpoint with *ed */ next_ep->desc = *(struct usb_endpoint_descriptor *)p; next_ep++; } if (do_print) { printf("ENDP, addr 0x%x %s pkt 0x%x int %d", ed->bEndpointAddress, eptype(ed->bmAttributes), UGETW(ed->wMaxPacketSize), ed->bInterval); } break; } if (do_print) printf("\n"); } if (do_print) printf("-- total %d interfaces, if %d: %d alt %d endp\n", nintf, ifno, nalt, nep); if (pass == 0 && ld != NULL) { /* allocate memory. The first part is for nalt interface * settings, the second part is for the total number of * endpoints. neps[i] has the total for each altsetting. */ int sz = nalt * sizeof(struct usb_host_interface) + nep * sizeof(struct usb_host_endpoint); ld->mem = malloc(sz, M_USBDEV, M_WAITOK | M_ZERO); printf("--- allocate %d bytes gives %p\n", sz, ld->mem); if (ld->mem == NULL) return; /* set ptrs to next free host_if and endpoint descriptors */ next_alt = ld->intf.altsetting = ld->mem; next_ep = (struct usb_host_endpoint *)(next_alt + nalt); /* cur_altsetting is updated later */ ld->intf.cur_altsetting = ld->mem; nalt = 0; } } } /* * Fill the linux_devinfo with information taken from the linker set. * XXX the linker set name must become an argument so this function * can be compiled as a library. */ void linux_devinfo_init(struct linux_dev_info *i) { struct bsd_module_init_t **p; if (i->initialized) return; /* initialize the struct from the linker set */ SET_FOREACH(p, ldev_info) { switch ((*p)->type) { default: break; case BSD_MOD_LOAD_HANDLER: i->init_f = (*p)->value; break; case BSD_MOD_UNLOAD_HANDLER: i->exit_f = (*p)->value; break; case BSD_MOD_DEVICE_TABLE: i->device_table = (*p)->value; break; } } i->initialized = 1; } /* * Lookup a device in the table, return NULL on failure, * the entry on success. */ const struct usb_device_id * ldev_lookup(device_t dev, struct usb_device_id *p) { int i; struct usb_attach_arg *uaa = device_get_ivars(dev); parse_full_config(usbd_get_config_descriptor(uaa->device), uaa->ifaceno, NULL); if (p == NULL) { printf("sorry no linux device table\n"); return NULL; } for (i = 0; p[i].match_flags != 0; i++) { if (p[i].match_flags & USB_DEVICE_ID_MATCH_VENDOR && p[i].idVendor != uaa->vendor) continue; if (p[i].match_flags & USB_DEVICE_ID_MATCH_PRODUCT && p[i].idProduct != uaa->product) continue; return p+i; } return NULL; } int fill_linux_descriptors(device_t dev, struct linux_usb_descriptors *ld) { struct usb_attach_arg *uaa = device_get_ivars(dev); usbd_device_handle udev = uaa->device; usb_config_descriptor_t *cdesc = usbd_get_config_descriptor(udev); bzero(ld, sizeof(*ld)); /* initialize FreeBSD fields */ ld->udev = udev; ld->iface = uaa->iface; /* parent struct usb_device (the full device) */ ld->p_dev.dev.parent = NULL; // XXX not sure ld->p_dev.dev.driver_data = NULL; // filled later with linux softc ld->p_dev.descriptor = *(struct usb_device_descriptor *) usbd_get_device_descriptor(udev); // ld->p_dev.devnum = udev->address; // hopefully unused /* done */ /* struct usb_interface fields */ ld->intf.dev.parent = &ld->p_dev.dev; ld->intf.num_altsetting = usbd_get_no_alts(cdesc, uaa->ifaceno); parse_full_config(cdesc, uaa->ifaceno, ld); if (ld->mem == NULL) return ENOMEM; /* failed */ printf("interface %d has %d altsettings (cur %d)\n", uaa->ifaceno, ld->intf.num_altsetting, usbd_get_interface_altindex(uaa->iface)); /* point to the current altsetting */ ld->intf.cur_altsetting = ld->intf.altsetting + usbd_get_interface_altindex(uaa->iface); ld->intf.cur_altsetting->desc = *(struct usb_interface_descriptor *) usbd_get_interface_descriptor(uaa->iface); /* done */ return 0; } /* * Here are the linux api functions that are not implemented as macros. */ /** * usb_make_path - returns stable device path in the usb tree * @dev: the device whose path is being constructed * @buf: where to put the string * @size: how big is "buf"? */ int usb_make_path(struct usb_device *dev, char *buf, size_t size) { int actual; actual = snprintf (buf, size, "usb-%s-%s", "ldev", "foo"); // dev->bus->bus_name, dev->devpath); return (actual >= (int)size) ? -1 : actual; } void usb_deregister(struct usb_driver *driver) { DBG("not complete"); } /** * usb_get_intf - increments the reference count of the usb interface structure * @intf: the interface being referenced * * Each live reference to a interface must be refcounted. * * Drivers for USB interfaces should normally record such references in * their probe() methods, when they bind to an interface, and release * them by calling usb_put_intf(), in their disconnect() methods. * * A pointer to the interface with the incremented reference counter is * returned. */ struct usb_interface *usb_get_intf(struct usb_interface *intf) { DBG("not complete\n"); return NULL; } /** * usb_put_intf - release a use of the usb interface structure * @intf: interface that's been decremented * * Must be called when a user of an interface is finished with it. When the * last user of the interface calls this function, the memory of the interface * is freed. */ void usb_put_intf(struct usb_interface *intf) { DBG("not complete\n"); } /** * usb_get_dev - increments the reference count of the usb device structure * @dev: the device being referenced * * Each live reference to a device should be refcounted. * * Drivers for USB interfaces should normally record such references in * their probe() methods, when they bind to an interface, and release * them by calling usb_put_dev(), in their disconnect() methods. * * A pointer to the device with the incremented reference counter is returned. */ struct usb_device *usb_get_dev(struct usb_device *dev) { DBG("not complete\n"); return NULL; #if 0 if (dev) get_device(&dev->dev); return dev; #endif } /** * usb_put_dev - release a use of the usb device structure * @dev: device that's been disconnected * * Must be called when a user of a device is finished with it. When the last * user of the device calls this function, the memory of the device is freed. */ void usb_put_dev(struct usb_device *dev) { DBG("not complete\n"); #if 0 if (dev) put_device(&dev->dev); #endif } /* * Send a control message. * XXX The 'pipe' parameter is ignored, which can be a problem. * XXX timeout was not present in the original, but it is in ms anyways. */ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout) { usb_device_request_t req; struct linux_usb_descriptors *lud; int ret; lud = container_of(dev, struct linux_usb_descriptors, p_dev); if ((pipe & 0xf) != 0) printf("warning, usb_control_msg for pipe 0x%x\n", pipe); pipe &= 0xf; /* take only the low bits */ req.bRequest = request; req.bmRequestType = requesttype; USETW(req.wValue, value); USETW(req.wIndex, index); USETW(req.wLength,size); #if 0 /* if we want to specify a different pipe... */ //return -usbd_do_request_flags_pipe(udev, udev->default_pipe, &req, data, 0, NULL, timeout); #endif if (0) DBG("usbd_do_request_flags 0x%02x 0x%02x 0x%02x 0x%04x 0x%04x %10p %04x\n", pipe, request, requesttype, value, index, data, size); ret = usbd_do_request_flags(ludev_to_udev(dev), &req, data, 0, NULL, timeout); return ret; } /* * Return the descriptor for the interface */ struct usb_interface * usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) { /* By now assume we have only one interface... */ return &( ludev_to_l_u_d(dev)->intf ); } /* * Return a pointer to the setting for this interface. */ struct usb_host_interface *usb_altnum_to_altsetting( const struct usb_interface *intf, unsigned int altnum) { return intf->altsetting + altnum; } int usb_clear_halt(struct usb_device *dev, int pipe) { DBG("not complete\n"); return -EINVAL; } /* * This function sets a generic interface. This emulation layer * only supports one interface, so we ignore the 'ifnum' argument. * (XXX this needs to be fixed later). */ int usb_set_interface(struct usb_device *dev, int ifnum, int alternate) { int err; struct usb_interface *intf = &(ludev_to_l_u_d(dev)->intf); if (0) DBG("usbd_set_interface ifnum %d to alt %d\n", ifnum, alternate); err = -usbd_set_interface(ludev_to_iface(dev), alternate); intf->cur_altsetting = intf->altsetting + alternate; return err; } /** * usb_string - returns ISO 8859-1 version of a string descriptor * @dev: the device whose string descriptor is being retrieved * @index: the number of the descriptor * @buf: where to put the string * @size: how big is "buf"? * Context: !in_interrupt () * * This converts the UTF-16LE encoded strings returned by devices, from * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones * that are more usable in most kernel contexts. Note that all characters * in the chosen descriptor that can't be encoded using ISO-8859-1 * are converted to the question mark ("?") character, and this function * chooses strings in the first language supported by the device. * * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode, * and is appropriate for use many uses of English and several other * Western European languages. (But it doesn't include the "Euro" symbol.) * * This call is synchronous, and may not be used in an interrupt context. * * Returns length of the string (>= 0) or usb_control_msg status (< 0). */ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) { /* XXX surely there is a FreeBSD equivalent */ DBG("not complete\n"); return -EINVAL; } /* used these for multi-interface device registration */ int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv) { DBG("not complete\n"); return -EINVAL; } /** * usb_interface_claimed - returns true iff an interface is claimed * @iface: the interface being checked * * Returns true (nonzero) iff the interface is claimed, else false (zero). * Callers must own the driver model's usb bus readlock. So driver * probe() entries don't need extra locking, but other call contexts * may need to explicitly claim that lock. * */ int usb_interface_claimed(struct usb_interface *iface) { DBG("not complete\n"); return 0; // return (iface->dev.driver != NULL); } /** * usb_endpoint_dir_in - check if the endpoint has IN direction * @epd: endpoint to be checked * * Returns true if the endpoint is of type IN, otherwise it returns false. */ int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) { return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); } /** * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type * @epd: endpoint to be checked * * Returns true if the endpoint is of type interrupt, otherwise it returns * false. */ int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd) { return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT); } /** * usb_endpoint_is_int_in - check if the endpoint is interrupt IN * @epd: endpoint to be checked * * Returns true if the endpoint has interrupt transfer type and IN direction, * otherwise it returns false. */ int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) { DBG("not complete\n"); return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd)); } /* usb buffers */ /** * This is the linux description: * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP * @dev: device the buffer will be used with * @size: requested buffer size * @mem_flags: affect whether allocation may block * @dma: used to return DMA address of buffer * * Return value is either null (indicating no buffer could be allocated), or * the cpu-space pointer to a buffer that may be used to perform DMA to the * specified device. Such cpu-space buffers are returned along with the DMA * address (through the pointer provided). * * These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags * to avoid behaviors like using "DMA bounce buffers", or tying down I/O * mapping hardware for long idle periods. The implementation varies between * platforms, depending on details of how DMA will work to this device. * Using these buffers also helps prevent cacheline sharing problems on * architectures where CPU caches are not DMA-coherent. * * When the buffer is no longer used, free it with usb_buffer_free(). * * On FreeBSD: * the buffer is allocated and linked to a usbd_xfer_handle x x = usbd_alloc_xfer(sc->udev); data = usbd_alloc_buffer(x, n_isoc*max_isoc_size); * In the emulation layer, we use the transfer_dma field as an alias to * usbd_xfer_handle, which is initialized when we call usb_buffer_alloc() * (when we have enough information to hook into the device). * XXX TODO: honor the flags for malloc ? */ void * usb_buffer_alloc(struct usb_device *dev, size_t size, gfp_t mem_flags, dma_addr_t *dma) { usbd_xfer_handle *xfer = (usbd_xfer_handle *)dma; usbd_device_handle udev = ludev_to_udev(dev); void *ret; if (*xfer != NULL) { /* not an error, but unusual */ DBG("xfer already allocated %p\n", *xfer); } else { /* allocate a fresh xfer descriptor */ *xfer = usbd_alloc_xfer(udev); if (*xfer == NULL) { printf("%s: usbd_alloc_xfer failed\n", __FUNCTION__); return NULL; } } ret = usbd_alloc_buffer(*xfer, size); if (0) DBG("usbd_alloc_buffer size %zd flags 0x%x xfer %p returns %p\n", size, mem_flags, *xfer, ret); return ret; } void usb_buffer_free(struct usb_device *dev, size_t size, void *addr, dma_addr_t dma) { usbd_xfer_handle xfer = (usbd_xfer_handle )dma; if (0) DBG("usbd_free_buffer at %p for xfer %p\n", usbd_get_buffer(xfer), xfer); usbd_free_buffer(xfer); } /* urb functions */ /* * usb_init_urb does almost nothing in our emulation. We keep it separate * in case someone calls it directly (then we must make it global). */ static void usb_init_urb(struct urb *urb) { bzero(urb, sizeof (*urb)); } /* * Allocate a control block and descriptors for 'iso_packets' * packets to be used in the transfer. * When we complete kmalloc we also honor the mem_flags. */ struct urb * usb_alloc_urb(int iso_packets, gfp_t mem_flags) { struct urb *urb = malloc(sizeof(struct urb) + iso_packets * sizeof(struct usb_iso_packet_descriptor), M_USBDEV, M_WAITOK | M_ZERO); if (!urb) { DBG("malloc failed\n"); return NULL; } usb_init_urb(urb); return urb; } /* * Free the urb and the fields (xfer, frlengths[]) possibly allocated in it. */ void usb_free_urb(struct urb *urb) { usbd_xfer_handle xfer = (usbd_xfer_handle )urb->transfer_dma; if (xfer) { if (0) DBG("usbd_free_xfer %p\n", xfer); usbd_free_xfer(xfer); urb->transfer_dma = 0 /* is this an int ??? */; } if (urb->frlengths != NULL) free(urb->frlengths, M_USBDEV); free(urb, M_USBDEV); } /* * The irq handler before passing control to the one * specified in the urb. Actually, it may well be that * this is good also for other transfers. */ static void ldev_isoc_handler(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) { struct urb *urb = (struct urb *)addr; int totlen = 0, i; void *bsd_buf = usbd_get_buffer(xfer); if (status == USBD_CANCELLED) { DBG("usbd_cancelled %p\n", xfer); return; } if (status != USBD_NORMAL_COMPLETION) { DBG("status %d\n", status); return; } if (bsd_buf != urb->transfer_buffer) { if (0) DBG("bsd != linux buffer (%p != %p)\n", bsd_buf, urb->transfer_buffer); /* XXX check direction. this is good for pipe reads */ bcopy(bsd_buf, urb->transfer_buffer, urb->transfer_buffer_length); } /* map status and sizes as needed */ for (i=0; i < urb->number_of_packets; i++) { totlen += urb->frlengths[i]; urb->iso_frame_desc[i].actual_length = urb->frlengths[i]; urb->iso_frame_desc[i].status = 0; /* XXX fake ? */ } urb->actual_length = totlen; // usbd_dump_pipe(ludev_to_l_u_d(urb->dev)->bsd_pipe); // XXX debugging if (0) DBG("status %d bytes %d for urb %p\n", status, totlen, urb); urb->status = status; /* XXX remap ? */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) urb->complete(urb); #else urb->complete(urb, NULL /* pt_regs */); #endif } /* * From the linux documentation: * usb_submit_urb - issue an asynchronous transfer request for an endpoint * @urb: pointer to the urb describing the request * @mem_flags: the type of memory to allocate, see kmalloc() for a list * of valid options for this. * * This submits a transfer request, and transfers control of the URB * describing that request to the USB subsystem. Request completion will * be indicated later, asynchronously, by calling the completion handler. * The three types of completion are success, error, and unlink * (a software-induced fault, also called "request cancellation"). * ... * On Linux: * this is called the first time in the open() or equivalent * routine, after usb_alloc_urb(), usb_buffer_alloc(), and * after the application has manually set the fields of the urb * (dev, context, pipe, transfer_flags, interval, complete, * number_of_packets, transfer_buffer_length, and * iso_frame_desc[i]{.offset, .length} * * In the next rounds, (typically from the 'complete' routine) * the caller sets urb->dev (why ?) and clears urb->status, * and reinvokes the function. * * On FreeBSD: * The manual setting of fields is replaced by * usbd_setup_XXX_xfer(), then this function is equivalent to * usbd_transfer() * XXX is the type of transfer (bulk, control, intr, isoc). * Note, on FreeBSD the individual descriptors are in a private array, * so we need to allocate them here. * * Note 2 - if somebody allocates the buffer externally, i.e. without * usb_buffer_alloc(), we allocate a bounce buffer to get the * necessary DMA pointers. There might be better ways. */ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) { int i, totlen; int xfertype = -1; /* invalid */ usbd_xfer_handle xfer = (usbd_xfer_handle )urb->transfer_dma; usbd_pipe_handle *bsd_pipe = &(ludev_to_l_u_d(urb->dev)->bsd_pipe); void *bsd_buf; int new_allocation = 0; if (xfer == NULL) { new_allocation = 1; DBG("urb buffer not allocated, error\n"); usb_buffer_alloc(urb->dev, urb->transfer_buffer_length, GFP_KERNEL, &urb->transfer_dma); xfer = (usbd_xfer_handle )urb->transfer_dma; } bsd_buf = usbd_get_buffer(xfer); if (bsd_buf == NULL) { printf("%s: transfer buffer not allocated\n", __FUNCTION__); return -EINVAL; } if (bsd_buf != urb->transfer_buffer) { if (new_allocation) DBG("bsd != linux buffer (%p != %p)\n", bsd_buf, urb->transfer_buffer); } if (*bsd_pipe == NULL) { /* open the pipe */ usbd_interface_handle iface = ludev_to_iface(urb->dev); int err = usbd_open_pipe(iface, urb->pipe, 0, bsd_pipe); if (0) DBG("usbd_open_pipe 0x%x speed %d attributes %d\n", urb->pipe, usbd_get_speed(ludev_to_udev(urb->dev)), usbd_get_endpoint_descriptor(iface, urb->pipe)->bmAttributes ); if (err) { DBG("openpipe error %d\n", err); return -err; } } if (urb->number_of_packets > 0) xfertype = UE_ISOCHRONOUS; switch (xfertype) { default: DBG("xfertype %d not supported\n", xfertype); return -EINVAL; /* XXX todo: handlers for other types */ case UE_ISOCHRONOUS: /* copy buffer sizes etc */ if (urb->number_of_packets > urb->n_frames) { if (urb->frlengths != NULL) free(urb->frlengths, M_USBDEV); urb->frlengths = malloc(sizeof(uint16_t) * urb->number_of_packets, M_USBDEV, M_NOWAIT); } if (urb->frlengths == NULL) { DBG("cannot allocate pointers\n"); return -EINVAL; } urb->n_frames = urb->number_of_packets; totlen = 0; for (i=0; i < urb->number_of_packets; i++) { /* XXX probably something is redundant */ urb->frlengths[i] = urb->iso_frame_desc[i].length; urb->iso_frame_desc[i].offset = totlen; urb->iso_frame_desc[i].actual_length = 0; urb->iso_frame_desc[i].status = -EXDEV; totlen += urb->frlengths[i]; } if (0) DBG("usbd_setup_isoc_xfer %p\n", xfer); usbd_setup_isoc_xfer(xfer, *bsd_pipe, urb, urb->frlengths, urb->number_of_packets, USBD_NO_COPY, ldev_isoc_handler); if (0) DBG("usbd_transfer tot %d %p\n", totlen, xfer); usbd_transfer(xfer); /* error return ? */ return 0; } DBG("not complete\n"); return -EINVAL; } /** * usb_unlink_urb - abort/cancel a transfer request for an endpoint * @urb: pointer to urb describing a previously submitted request, * may be NULL * * This routine cancels an in-progress request. URBs complete only * once per submission, and may be canceled only once per submission. */ int usb_unlink_urb(struct urb *urb) { usbd_pipe_handle *bsd_pipe = &(ludev_to_l_u_d(urb->dev)->bsd_pipe); if (*bsd_pipe == NULL) { /* pipe already closed */ return -EINVAL; /* or maybe just 0 ? */ } if (0) DBG("usbd_abort_pipe\n"); usbd_abort_pipe(*bsd_pipe); if (0) DBG("usbd_close_pipe\n"); usbd_close_pipe(*bsd_pipe); *bsd_pipe = NULL; return 0; } /** * usb_kill_urb - cancel a transfer request and wait for it to finish * @urb: pointer to URB describing a previously submitted request, * may be NULL */ void usb_kill_urb(struct urb *urb) { DBG("not complete but try something\n"); usb_unlink_urb(urb); } /* vmalloc/vfree */ /* * vmalloc_32() allocates memory, 32-bit addressable. * On linux it is simply __vmalloc(size, GFP_KERNEL, PAGE_KERNEL); * For the time being, just map it to malloc() */ void * vmalloc_32(unsigned long size) { return malloc(size, M_USBDEV, M_WAITOK | M_ZERO); } void vfree(void *ptr) { free(ptr, M_USBDEV); } /* * Map a vmalloc()-space virtual address to the physical page. */ struct page * vmalloc_to_page(void *addr) { DBG("not complete\n"); return NULL; } /* * Map a vmalloc()-space virtual address to the physical page ? */ unsigned long vmalloc_to_pfn(void *addr) { DBG("not complete\n"); return 0; } void * page_address(struct page *page) { DBG("not complete\n"); return NULL; } int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t pgr) { DBG("not complete\n"); return -EINVAL; } /* jiffies */ u64 get_jiffies_64(void) { return ticks; } int jiffies_to_msecs(const u64 j) { return ticks * 1000 / hz; } /* tasklet */ /* * On linux this is probably meant to be scheduled independently of the * main task. But for the time being, let's just do it as a direct call. */ void tasklet_schedule(struct tasklet_struct *t) { t->func(t->data); } void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data) { t->func = func; t->data = data; } void schedule(void) { DBG("not complete\n"); } /* video, mostly from videodev.c */ /* * on linux, we have the video_device[] array which is set * in video_register_device() and read with video_devdata() */ #define VIDEO_NUM_DEVICES 256 #define VIDEO_NAME "video4linux" static struct video_device *video_device[VIDEO_NUM_DEVICES]; // static DEFINE_MUTEX(videodev_lock); long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) { DBG("not complete\n"); return -EINVAL; } void video_device_remove_file(struct video_device *vfd, struct class_device_attribute *attr) { DBG("not complete\n"); } struct video_device * video_devdata(struct file *f) { int i = 0; DBG("not complete but ok for now\n"); return video_device[i]; } /* * On linux, this does the copyin/copyout around the invocation of * the actual invocation. On FreeBSD, we don't need to copy. * Note that 'inode' is the softc. */ int video_usercopy(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int (*func)(struct inode *inode, struct file *file, unsigned int cmd, void *arg)) { return func(inode, file, cmd, (void *)arg); } /* * register a video device with the system. * There is some complex linkage here, but ultimately: * - d->fops is the struct file_operations; * * - d->dev points to the parent struct device, in turn * contained into a struct usb_device, in turn (on FreeBSD) * contained in a struct linux_usb_descriptors, in turn * contained in the softc, so we can write d->fops in the softc. */ int video_register_device(struct video_device *d, int type, int nr) { struct usb_device *udev = container_of(d->dev, struct usb_device, dev); struct linux_usb_descriptors *l_u_d = ludev_to_l_u_d(udev); l_u_d->fops = d->fops; video_device[0] = d; /* XXX to be fixed */ DBG("to be fixed but ok for now\n"); return 0; } void video_unregister_device(struct video_device *d) { video_device[0] = NULL; DBG("to be fixed but ok for now\n"); } /* * Allocate enough memory to store the video device data. * Note that this is filled in with the template (including fops) * in the _probe routine (i.e. attach, in FreeBSD terminology) */ struct video_device * video_device_alloc(void) { return malloc(sizeof(struct video_device), M_USBDEV, M_WAITOK | M_ZERO); } void video_device_release(struct video_device *vfd) { free(vfd, M_USBDEV); } /* in uaccess.h */ /* * copy a buffer to userspace. * In our emulation, *to is really a uio argument. * XXX TODO: check direction of transfer; return # of bytes not copied. */ unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) { struct uio *uio = to; int i, prev = uio->uio_resid; int err; void *src = (void *)(uintptr_t)from; /* XXX should check the direction. we trust it is out or UIO_READ*/ err = uiomove(src, n, uio); i = (prev - uio->uio_resid); if (i != n) DBG("uiomove asked %ld bytes, uio has %d, done %d\n", n, uio->uio_resid, i); return n - i; } unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) { DBG("not complete\n"); return -EINVAL; } /*--- lib/kref.h */ /** * kref_init - initialize object. * @kref: object in question. */ void kref_init(struct kref *kref) { atomic_set(&kref->refcount,1); } /** * kref_get - increment refcount for object. * @kref: object. */ void kref_get(struct kref *kref) { atomic_inc(&kref->refcount); } /** * kref_put - decrement refcount for object. * @kref: object. * @release: pointer to the function that will clean up the object when the * last reference to the object is released. * This pointer is required, and it is not acceptable to pass kfree * in as this function. * * Decrement the refcount, and if 0, call release(). * Return 1 if the object was removed, otherwise return 0. Beware, if this * function returns 0, you still can not count on the kref from remaining in * memory. Only use the return value if you want to see if the kref is now * gone, not present. */ int kref_put(struct kref *kref, void (*release)(struct kref *kref)) { /* * if current count is one, we are the last user and can release object * right now, avoiding an atomic operation on 'refcount' */ if ((atomic_read(&kref->refcount) == 1) || (atomic_dec_and_test(&kref->refcount))) { release(kref); return 1; } return 0; } linux_compat/pwc-ioctl.h000644 000423 000000 00000022270 10557457520 016105 0ustar00luigiwheel000000 000000 /* * PWCBSD - Philips USB webcam driver for FreeBSD 5.4 and higher * * Copyright (C) 2006 Raaf * * Based on the Linux pwc driver. * * Copyright (C) 1999-2003 Nemosoft Unv. * Copyright (C) 2004-2006 Luc Saillard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ /* This is pwc-ioctl.h It contains structures and defines to communicate from user space directly to the driver. */ #ifndef PWC_IOCTL_H #define PWC_IOCTL_H /* Enumeration of image sizes */ enum { PSZ_SQCIF, /* 120x96 */ PSZ_QSIF, /* 160x120 */ PSZ_QCIF, /* 176x144 */ PSZ_QPAL, /* 192x144 */ PSZ_SIF, /* 320x240 */ PSZ_CIF, /* 352x288 */ PSZ_PAL, /* 384x288 */ PSZ_VGA, /* 640x480 */ PSZ_XGA, /* 1024x768 */ PSZ_MAX }; /* The frame rate is encoded in the video_window.flags parameter using the upper 16 bits, since some flags are defined nowadays. The following defines provide a mask and shift to filter out this value. This value can also be passing using the private flag when using v4l2 and VIDIOC_S_FMT ioctl. In 'Snapshot' mode the camera freezes its automatic exposure and colour balance controls. */ #define PWC_FPS_SHIFT 16 #define PWC_FPS_MASK 0x00FF0000 #define PWC_FPS_FRMASK 0x003F0000 #define PWC_FPS_SNAPSHOT 0x00400000 #define PWC_QLT_MASK 0x03000000 #define PWC_QLT_SHIFT 24 /* structure for transfering x & y coordinates */ struct pwc_coord { int x, y; /* guess what */ int size; /* size, or offset */ }; /* Used with VIDIOCPWCPROBE */ struct pwc_probe { char name[32]; int type; }; struct pwc_serial { char serial[30]; /* String with serial number. Contains terminating 0 */ }; /* pwc_whitebalance.mode values */ #define PWC_WB_INDOOR 0 #define PWC_WB_OUTDOOR 1 #define PWC_WB_FL 2 #define PWC_WB_MANUAL 3 #define PWC_WB_AUTO 4 /* Used with VIDIOCPWC[SG]AWB (Auto White Balance). Set mode to one of the PWC_WB_* values above. *red and *blue are the respective gains of these colour components inside the camera; range 0..65535 When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read; otherwise undefined. 'read_red' and 'read_blue' are read-only. */ struct pwc_whitebalance { int mode; int manual_red, manual_blue; /* R/W */ int read_red, read_blue; /* R/O */ }; /* 'control_speed' and 'control_delay' are used in automatic whitebalance mode, and tell the camera how fast it should react to changes in lighting, and with how much delay. Valid values are 0..65535. */ struct pwc_wb_speed { int control_speed; int control_delay; }; /* Used with VIDIOCPWC[SG]LED */ struct pwc_leds { int led_on; /* Led on-time; range = 0..25000 */ int led_off; /* Led off-time; range = 0..25000 */ }; /* Image size (used with GREALSIZE) */ struct pwc_imagesize { int width; int height; }; /* Defines and structures for Motorized Pan & Tilt */ #define PWC_MPT_PAN 0x01 #define PWC_MPT_TILT 0x02 #define PWC_MPT_TIMEOUT 0x04 /* for status */ /* Set angles; when absolute != 0, the angle is absolute and the driver calculates the relative offset for you. This can only be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns absolute angles. */ struct pwc_mpt_angles { int absolute; /* write-only */ int pan; /* degrees * 100 */ int tilt; /* degress * 100 */ }; /* Range of angles of the camera, both horizontally and vertically. */ struct pwc_mpt_range { int pan_min, pan_max; /* degrees * 100 */ int tilt_min, tilt_max; }; struct pwc_mpt_status { int status; int time_pan; int time_tilt; }; /* This is used for out-of-kernel decompression. With it, you can get all the necessary information to initialize and use the decompressor routines in standalone applications. */ struct pwc_video_command { int type; /* camera type (645, 675, 730, etc.) */ int release; /* release number */ int size; /* one of PSZ_* */ int alternate; int command_len; /* length of USB video command */ unsigned char command_buf[13]; /* Actual USB video command */ int bandlength; /* >0 = compressed */ int frame_size; /* Size of one (un)compressed frame */ }; /* Flags for PWCX subroutines. Not all modules honour all flags. */ #define PWCX_FLAG_PLANAR 0x0001 #define PWCX_FLAG_BAYER 0x0008 /* IOCTL definitions */ /* Restore user settings */ #define VIDIOCPWCRUSER _IO('v', 192) /* Save user settings */ #define VIDIOCPWCSUSER _IO('v', 193) /* Restore factory settings */ #define VIDIOCPWCFACTORY _IO('v', 194) /* You can manipulate the compression factor. A compression preference of 0 means use uncompressed modes when available; 1 is low compression, 2 is medium and 3 is high compression preferred. Of course, the higher the compression, the lower the bandwidth used but more chance of artefacts in the image. The driver automatically chooses a higher compression when the preferred mode is not available. */ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */ #define VIDIOCPWCSCQUAL _IOW('v', 195, int) /* Get preferred compression quality */ #define VIDIOCPWCGCQUAL _IOR('v', 195, int) /* Retrieve serial number of camera */ #define VIDIOCPWCGSERIAL _IOR('v', 198, struct pwc_serial) /* This is a probe function; since so many devices are supported, it becomes difficult to include all the names in programs that want to check for the enhanced Philips stuff. So in stead, try this PROBE; it returns a structure with the original name, and the corresponding Philips type. To use, fill the structure with zeroes, call PROBE and if that succeeds, compare the name with that returned from VIDIOCGCAP; they should be the same. If so, you can be assured it is a Philips (OEM) cam and the type is valid. */ #define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe) /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */ #define VIDIOCPWCSAGC _IOW('v', 200, int) /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */ #define VIDIOCPWCGAGC _IOR('v', 200, int) /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */ #define VIDIOCPWCSSHUTTER _IOW('v', 201, int) /* Get shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */ #define VIDIOCPWCGSHUTTER _IOR('v', 201, int) /* Color compensation (Auto White Balance) */ #define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance) #define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance) /* Auto WB speed */ #define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed) #define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed) /* LEDs on/off/blink; int range 0..65535 */ #define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds) #define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds) /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */ #define VIDIOCPWCSCONTOUR _IOW('v', 206, int) #define VIDIOCPWCGCONTOUR _IOR('v', 206, int) /* Backlight compensation; 0 = off, otherwise on */ #define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int) #define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int) /* Flickerless mode; = 0 off, otherwise on */ #define VIDIOCPWCSFLICKER _IOW('v', 208, int) #define VIDIOCPWCGFLICKER _IOR('v', 208, int) /* Dynamic noise reduction; 0 off, 3 = high noise reduction */ #define VIDIOCPWCSDYNNOISE _IOW('v', 209, int) #define VIDIOCPWCGDYNNOISE _IOR('v', 209, int) /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */ #define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize) /* Motorized pan & tilt functions */ #define VIDIOCPWCMPTRESET _IOW('v', 211, int) #define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range) #define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles) #define VIDIOCPWCMPTGANGLE _IOR('v', 212, struct pwc_mpt_angles) #define VIDIOCPWCMPTSTATUS _IOR('v', 213, struct pwc_mpt_status) /* Get the USB set-video command; needed for initializing libpwcx */ #define VIDIOCPWCGVIDCMD _IOR('v', 215, struct pwc_video_command) struct pwc_table_init_buffer { int len; char *buffer; }; #define VIDIOCPWCGVIDTABLE _IOR('v', 216, struct pwc_table_init_buffer) /* Colour mode ; 0 = off, 1 = on */ #define VIDIOCPWCSCOLOUR _IOW('v', 217, int) #define VIDIOCPWCGCOLOUR _IOR('v', 217, int) /* * This is private command used when communicating with v4l2. * In the future all private ioctl will be remove/replace to * use interface offer by v4l2. */ #define V4L2_CID_PRIVATE_SAVE_USER (V4L2_CID_PRIVATE_BASE + 0) #define V4L2_CID_PRIVATE_RESTORE_USER (V4L2_CID_PRIVATE_BASE + 1) #define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2) #endif linux_compat/pwcview.c000644 000423 000000 00000070715 10673552314 015666 0ustar00luigiwheel000000 000000 /* * pwcview - application to view video, create jpeg snapshots and alter * settings of a webcam controlled by the pwc driver * * Copyright (C) 2006 Raaf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef NOGUI #include #endif #ifdef LOCAL_VIDEODEV #include "videodev.h" #else #include #endif #include "pwc-ioctl.h" #ifndef NOGUI int default_handler(int fd, int dir, char *buf) { if(dir != 0) return -1; snprintf(buf,80,"pwcview"); return 0; } int framerate_handler(int fd, int dir, char *buf) { int fps; struct video_window vw; if(ioctl(fd,VIDIOCGWIN,&vw) == -1) { perror("Failed to get current framerate"); return -1; } fps = vw.flags >> PWC_FPS_SHIFT; if((dir == -1 && fps >= 9) ||(dir == 1 && fps <= 25)) { fps += dir == -1 ? -5 : 5; vw.flags = fps << PWC_FPS_SHIFT; if(ioctl(fd,VIDIOCSWIN,&vw) == -1) fprintf(stderr,"Failed to set framerate to %d fps: %s\n",fps,strerror(errno)); if(ioctl(fd,VIDIOCGWIN,&vw) == -1) { perror("Failed to get new framerate"); return -1; } fps = vw.flags >> PWC_FPS_SHIFT; } snprintf(buf,80,"framerate: %d fps",fps); return 0; } int compression_handler(int fd, int dir, char *buf) { int qual; if(ioctl(fd,VIDIOCPWCGCQUAL,&qual) == -1) { perror("Failed to get current compression"); return -1; } if((dir == -1 && qual > 0) || (dir == 1 && qual < 3)) { qual += dir == -1 ? -1 : 1; if(ioctl(fd,VIDIOCPWCSCQUAL,&qual) == -1) perror("Failed to set compression"); if(ioctl(fd,VIDIOCPWCGCQUAL,&qual) == -1) { perror("Failed to get new compression"); return -1; } } snprintf(buf,80,"compression: %d",qual); return 0; } int brightness_handler(int fd, int dir, char *buf) { struct video_picture pict; static int fake_bright = 0, bri = 0; #define DELTA_BRI 128 if(ioctl(fd,VIDIOCGPICT,&pict) == -1) { perror("Failed to get current brightness"); return -1; } if (fake_bright) pict.brightness = bri; if((dir == -1) || (dir == 1)) { int x; pict.brightness += dir * DELTA_BRI; x = pict.brightness; if(ioctl(fd,VIDIOCSPICT,&pict) == -1) perror("Failed to set brightness"); if(ioctl(fd,VIDIOCGPICT,&pict) == -1) { perror("Failed to get new brightness"); return -1; } if (x != pict.brightness) { if (fake_bright == 0) fprintf(stderr, "using fake brightness %d\n", x); fake_bright = 1; } pict.brightness = bri = x; } snprintf(buf,80,"brightness: %d", pict.brightness); return 0; } int contrast_handler(int fd, int dir, char *buf) { struct video_picture pict; static int fake_contrast = 0, contrast = 0; #define DELTA_CONTRAST 128 if(ioctl(fd,VIDIOCGPICT,&pict) == -1) { perror("Failed to get current contrast"); return -1; } if (fake_contrast) pict.contrast = contrast; if((dir == -1) || (dir == 1)) { int x; pict.contrast += dir * DELTA_CONTRAST; x = pict.contrast; if(ioctl(fd,VIDIOCSPICT,&pict) == -1) perror("Failed to set contrast"); if(ioctl(fd,VIDIOCGPICT,&pict) == -1) { perror("Failed to get new contrast"); return -1; } if (x != pict.contrast) { if (fake_contrast == 0) fprintf(stderr, "using fake contrast %d\n", x); fake_contrast = 1; } pict.contrast = contrast = x; } snprintf(buf,80,"contrast: %d",pict.contrast); return 0; } int saturation_handler(int fd, int dir, char *buf) { struct video_picture pict; if(ioctl(fd,VIDIOCGPICT,&pict) == -1) { perror("Failed to get current saturation"); return -1; } if((dir == -1) || (dir == 1)) { pict.colour += dir == -1 ? -327 : 327; if(ioctl(fd,VIDIOCSPICT,&pict) == -1) perror("Failed to set saturation"); if(ioctl(fd,VIDIOCGPICT,&pict) == -1) { perror("Failed to get new saturation"); return -1; } } snprintf(buf,80,"saturation: %d",(pict.colour - 32768) / 327); return 0; } int gamma_handler(int fd, int dir, char *buf) { struct video_picture pict; if(ioctl(fd,VIDIOCGPICT,&pict) == -1) { perror("Failed to get current gamma"); return -1; } if((dir == -1) ||(dir == 1)) { pict.whiteness += dir == -1 ? -2048 : 2048; if(ioctl(fd,VIDIOCSPICT,&pict) == -1) perror("Failed to set gamma"); if(ioctl(fd,VIDIOCGPICT,&pict) == -1) { perror("Failed to get new gamma"); return -1; } } snprintf(buf,80,"gamma: %d",pict.whiteness >> 11); return 0; } int agc_handler(int fd, int dir, char *buf) { static u_int16_t agc = 32768; static int agcmode = 1; int val; if(dir == 2) { if(++agcmode == 2) agcmode = 0; } else if(dir == -1 && agcmode == 0) agc -= 1024; else if(dir == 1 && agcmode == 0) agc += 1024; if(agcmode == 1) { val = -1; snprintf(buf,80,"gain control: auto"); } else { val = agc; snprintf(buf,80,"gain control: %d",agc >> 10); } ioctl(fd,VIDIOCPWCSAGC,&val); return 0; } int shutter_handler(int fd, int dir, char *buf) { static u_int16_t shutter = 32768; static int shuttermode = 1; int val; if(dir == 2) { if(++shuttermode == 2) shuttermode = 0; } else if(dir == -1 && shuttermode == 0) shutter -= 256; else if(dir == 1 && shuttermode == 0) shutter += 256; if(shuttermode == 1) { val = -1; snprintf(buf,80,"shutter speed: auto"); } else { val = shutter; snprintf(buf,80,"shutter speed: %d",shutter >> 8); } ioctl(fd,VIDIOCPWCSSHUTTER,&val); return 0; } int whitebalance_handler(int fd, int dir, char *buf) { static int skip = 0; struct pwc_whitebalance wb; char *names[] = { "indoor", "outdoor", "fluorescent","manual","auto" }; int *val = NULL; if(ioctl(fd,VIDIOCPWCGAWB,&wb) == -1) { perror("Failed to get whitebalance"); return -1; } if(dir == 2 && !skip) { if(--wb.mode < PWC_WB_INDOOR) wb.mode = PWC_WB_AUTO; } if(wb.mode == PWC_WB_MANUAL) { if(dir == 2) { skip = !skip; if(skip) { wb.manual_red = wb.read_red; wb.manual_blue = wb.read_blue; } } val = skip ? &wb.manual_red : &wb.manual_blue; if(dir == -1) *val -= 256; else if(dir == 1) *val += 256; } if(ioctl(fd,VIDIOCPWCSAWB,&wb) == -1) perror("Failed to set whitebalance"); if(ioctl(fd,VIDIOCPWCGAWB,&wb) == -1) { perror("Failed to get whitebalance"); return -1; } if(wb.mode == PWC_WB_MANUAL) snprintf(buf,80,"whitebalance %s gain: %d",skip ? "red" : "blue",*val >> 8); else snprintf(buf,80,"whitebalance: %s",names[wb.mode]); return 0; } int whitebalancespeed_handler(int fd, int dir, char *buf) { struct pwc_wb_speed speed; if(ioctl(fd,VIDIOCPWCGAWBSPEED,&speed) == -1) { perror("Failed to get current awb speed"); return -1; } if((dir == -1) || (dir == 1)) { speed.control_speed += dir == -1 ? -2032 : 2032; if(ioctl(fd,VIDIOCPWCSAWBSPEED,&speed) == -1) perror("Failed to set awb speed"); if(ioctl(fd,VIDIOCPWCGAWBSPEED,&speed) == -1) { perror("Failed to get new awb speed"); return -1; } } snprintf(buf,80,"whitebalance speed: %d",speed.control_speed / 2032); return 0; } int whitebalancedelay_handler(int fd, int dir, char *buf) { struct pwc_wb_speed speed; if(ioctl(fd,VIDIOCPWCGAWBSPEED,&speed) == -1) { perror("Failed to get current awb delay"); return -1; } if((dir == -1) || (dir == 1)) { speed.control_delay += dir == -1 ? -1024 : 1024; if(ioctl(fd,VIDIOCPWCSAWBSPEED,&speed) == -1) perror("Failed to set awb delay"); if(ioctl(fd,VIDIOCPWCGAWBSPEED,&speed) == -1) { perror("Failed to get new awb delay"); return -1; } } snprintf(buf,80,"whitebalance delay: %d",speed.control_delay >> 10); return 0; } int contour_handler(int fd, int dir,char *buf) { static u_int16_t contour = 32768; static int contourmode = 1; int val; if(dir == 2) { if(++contourmode == 2) contourmode = 0; } else if(dir == -1 && contourmode == 0) contour -= 1024; else if(dir == 1 && contourmode == 0) contour += 1024; if(contourmode == 1) val = -1; else val = contour; if(ioctl(fd,VIDIOCPWCSCONTOUR,&val) == -1) perror("Failed to set contour"); if(contourmode == 1) snprintf(buf,80,"contour: auto"); else { if(ioctl(fd,VIDIOCPWCGCONTOUR,&contour) == -1) { perror("Failed to get contour"); return -1; } snprintf(buf,80,"contour: %d",contour >> 10); } return 0; } int dynamicnoise_handler(int fd, int dir, char *buf) { int dynnoise; if(ioctl(fd,VIDIOCPWCGDYNNOISE,&dynnoise) == -1) { perror("Failed to get current dynamic noise reduction mode"); return -1; } if(dir == 2) { if(++dynnoise == 4) dynnoise = 0; if(ioctl(fd,VIDIOCPWCSDYNNOISE,&dynnoise) == -1) perror("Failed to set dynamic noise reduction mode"); if(ioctl(fd,VIDIOCPWCGDYNNOISE,&dynnoise) == -1) { perror("Failed to get new dynamic noise reduction mode"); return -1; } } snprintf(buf,80,"dnr mode: %d",dynnoise); return 0; } int backlight_handler(int fd, int dir, char *buf) { int backlight; if(ioctl(fd,VIDIOCPWCGBACKLIGHT,&backlight) == -1) { perror("Failed to get backlight mode"); return -1; } if(dir == 2) { backlight = !backlight; if(ioctl(fd,VIDIOCPWCSBACKLIGHT,&backlight) == -1) perror("Failed to set backlight mode"); if(ioctl(fd,VIDIOCPWCGBACKLIGHT,&backlight) == -1) { perror("Failed to get new backlight mode"); return -1; } } snprintf(buf,80,"backlight compensation: %s",backlight ? "on" : "off"); return 0; } int flicker_handler(int fd, int dir, char *buf) { int flicker; if(ioctl(fd,VIDIOCPWCGFLICKER,&flicker) == -1) { perror("Failed to get flicker mode"); return -1; } if(dir == 2) { flicker = !flicker; if(ioctl(fd,VIDIOCPWCSFLICKER,&flicker) == -1) perror("Failed to set flicker mode"); if(ioctl(fd,VIDIOCPWCGFLICKER,&flicker) == -1) { perror("Failed to get new flicker mode"); return -1; } } snprintf(buf,80,"anti flicker mode: %s",flicker ? "on" : "off"); return 0; } int colour_handler(int fd, int dir, char *buf) { int colour; if(ioctl(fd,VIDIOCPWCGCOLOUR,&colour) == -1) { perror("Failed to get colour mode"); return -1; } if(dir == 2) { colour = !colour; if(ioctl(fd,VIDIOCPWCSCOLOUR,&colour) == -1) perror("Failed to set colour mode"); if(ioctl(fd,VIDIOCPWCGCOLOUR,&colour) == -1) { perror("Failed to get new colour mode"); return -1; } } snprintf(buf,80,"colour mode: %s",colour ? "color" : "black & white"); return 0; } int saveuser_handler(int fd, int dir, char *buf) { if(dir == 0) { snprintf(buf,80,"save user settings"); } else if(dir == 2) { if(ioctl(fd,VIDIOCPWCSUSER) == -1) snprintf(buf,80,"Error: %s",strerror(errno)); else snprintf(buf,80,"User settings saved"); return 0; } else { return -1; } return 0; } int restoreuser_handler(int fd, int dir, char *buf) { if(dir == 0) { snprintf(buf,80,"restore user settings"); } else if(dir == 2) { if(ioctl(fd,VIDIOCPWCRUSER) == -1) snprintf(buf,80,"Error: %s",strerror(errno)); else snprintf(buf,80,"User settings restored"); } else { return -1; } return 0; } int restorefactory_handler(int fd, int dir, char *buf) { if(dir == 0) { snprintf(buf,80,"restore factory settings"); } else if(dir == 2) { if(ioctl(fd,VIDIOCPWCFACTORY) == -1) snprintf(buf,80,"Error: %s",strerror(errno)); else snprintf(buf,80,"Factory settings restored"); } else { return -1; } return 0; } int (*handler[])(int fd, int direction, char *buf) = { /* direction: -1 = down, 0 = init, 1 = up, 2 = special */ default_handler, framerate_handler, brightness_handler, contrast_handler, saturation_handler, gamma_handler, agc_handler, shutter_handler, whitebalance_handler, whitebalancespeed_handler, whitebalancedelay_handler, contour_handler, dynamicnoise_handler, backlight_handler, flicker_handler, colour_handler, compression_handler, saveuser_handler, restoreuser_handler, restorefactory_handler }; Uint32 cbtimer(Uint32 interval, void *param) { SDL_Event event; SDL_UserEvent userevent; userevent.type = SDL_USEREVENT; userevent.code = 0; userevent.data1 = NULL; userevent.data2 = NULL; event.type = SDL_USEREVENT; event.user = userevent; SDL_PushEvent(&event); return interval; } #endif void sig_chld(int signo) { int stat; while(waitpid(-1, &stat, WNOHANG) > 0) ; } void jpeg_init(int width, int height, int quality, struct jpeg_compress_struct *cinfo, struct jpeg_error_mgr *jerr, JSAMPIMAGE jimage, JSAMPROW y) { int i; JSAMPROW u,v; cinfo->err = jpeg_std_error(jerr); jpeg_create_compress(cinfo); cinfo->image_width = width; cinfo->image_height = height; cinfo->input_components = 3; cinfo->in_color_space = JCS_YCbCr; jpeg_set_defaults(cinfo); /* cinfo->dct_method = JDCT_FLOAT; */ cinfo->raw_data_in = TRUE; cinfo->comp_info[0].h_samp_factor = 2; cinfo->comp_info[0].v_samp_factor = 2; cinfo->comp_info[1].h_samp_factor = 1; cinfo->comp_info[1].v_samp_factor = 1; cinfo->comp_info[2].h_samp_factor = 1; cinfo->comp_info[2].v_samp_factor = 1; jimage[0] = malloc(height * 2 * sizeof(JSAMPROW)); if(jimage[0] == NULL) { fprintf(stderr,"Error: out of memory\n"); exit(1); } jimage[1] = jimage[0] + height; jimage[2] = jimage[1] + (height/2); u = y + width * height; v = u + width * height / 4; for(i = 0; i < height; ++i, y+=width) { jimage[0][i] = y; } for(i = 0; i < height/2; ++i, u+=width/2, v+=width/2) { jimage[1][i] = u; jimage[2][i] = v; } jpeg_set_quality(cinfo, quality, TRUE); } void jpeg_write(int height, JSAMPIMAGE jimage, struct jpeg_compress_struct *cinfo, const char *fmt, const char *cmd) { JSAMPARRAY jdata[3]; char filename[1024]; FILE *outfile; time_t tt; struct tm *tm; int i; tt = time(NULL); if(tt == (time_t)-1) { perror("Failed to get time"); return; } tm = localtime(&tt); if(strftime(filename,1024,fmt,tm) == 0) { fprintf(stderr,"Error: resulting filename to long\n"); return; } if ((outfile = fopen(filename, "wb")) == NULL) { perror("Error opening output file"); return; } jdata[0] = jimage[0]; jdata[1] = jimage[1]; jdata[2] = jimage[2]; jpeg_stdio_dest(cinfo, outfile); jpeg_start_compress(cinfo, TRUE); for (i = 0;i < height;i += 2*DCTSIZE) { jpeg_write_raw_data(cinfo, jdata, 2*DCTSIZE); jdata[0] += 2*DCTSIZE; jdata[1] += DCTSIZE; jdata[2] += DCTSIZE; } jpeg_finish_compress(cinfo); fclose(outfile); if(cmd != NULL) { switch(fork()) { case 0: execlp(cmd,cmd,filename,NULL); fprintf(stderr,"Failed to execute %s: %s\n",cmd,strerror(errno)); _exit(1); case -1: perror("fork failed"); /* Fall through */ default: break; } } } #define PSZ_MAX 6 struct { char *name; int width; int height; } sizes[PSZ_MAX] = { { "sqcif", 128, 96 }, { "qsif", 160, 120 }, { "qcif", 176, 144 }, { "sif", 320, 240 }, { "cif", 352, 288 }, { "vga", 640, 480 } }; int usage() { fprintf(stderr, #ifndef NOGUI "Usage: pwcview [ options ]\n\n" #else "Usage: pwcsnap [ options ]\n\n" #endif "Options:\n" " -? Display this help message\n" #ifndef NOGUI " -h Run in headless mode\n" " -x Create window without frame\n" " -y Use IYUV overlay instead of YV12 overlay\n" " -z 2x zoom (implies -y)\n" " -2 two images on x (implies -y)\n" " -4 four images (implies -y)\n" " -M mirror images\n" " -m Create the video surface in system memory (SDL_SWSURFACE)\n" " -a Always use video surface (SDL_ANYFORMAT)\n" " -b Bits per pixel to setup SDL video surface with (default: 0)\n" #endif " -c Number of jpeg snapshots to take (default: 0 (-1=unlimited))\n" " -i Jpeg snapshot interval in milliseconds (default: 3000)\n" " -q Quality of jpeg output image (range: 0 -100, default: 75)\n" " -o Filename for jpeg output (default: /tmp/%%Y%%m%%d%%H%%M%%S.jpg)\n" " -e Command to execute after each snaphot (default: none)\n" " -d Video device to open (default: /dev/video0)\n" " -s Video size to use (default: sif)\n" " -f Video framerate to use (default: 5)\n\n" " See the pwcview(1) manpage for details\n\n"); return 1; } struct my_window { SDL_Rect rect; // x, y, w, h; int format; SDL_Overlay *overlay; }; int create_window(SDL_Surface *screen, struct my_window *win) { if((win->overlay = SDL_CreateYUVOverlay(win->rect.w, win->rect.h, win->format, screen)) == NULL) { fprintf(stderr,"Failed to create yuvoverlay: %s\n", SDL_GetError()); return 1; } SDL_DisplayYUVOverlay(win->overlay, &win->rect); return 0; } int mirror = 0; /* mirror image in -2/-4 modes */ /* * copy a block mirroring the x and y direction. * do it so src and dst may be the same. */ static void mirror_x(const char *src, char *dst, int w, int h) { int ix, iy; for (iy = 0; iy < h; iy++) { for (ix = 0; ix < w/2; ix++) { char a = src[ix]; char b = src[w - ix - 1]; dst[ix] = b; dst[w - ix - 1] = a; } src += w; dst += w; } } static void mirror_y(const char *src, char *dst, int w, int h) { int iy; char *buf, *buf2, *dst2; const char *src2; buf = alloca(w); buf2 = alloca(w); src2 = src + w * (h - 1); dst2 = dst + w * (h - 1); /* move to the end */ for (iy = 0; iy < h/2; iy++) { memcpy(buf, src, w); memcpy(buf2, src2, w); memcpy(dst2, buf, w); memcpy(dst, buf2, w); src += w; dst += w; src2 -= w; dst2 -= w; } } int refill_image(struct my_window *win, char *y, char *u, char *v, int ysize, int uvsize, int zoom) { int which = 0; /* how to mirror, really */ SDL_Overlay *ov = win->overlay; SDL_LockYUVOverlay(ov); if (mirror) { which |= (win->rect.x > 0 ? 1 : 0 /* mirror x */); which |= (win->rect.y > 0 ? 2 : 0 /* mirror y */); } if (zoom > 1) { int ix, iy; int w = win->rect.w; /* Full width */ /* y image has width w/2. u, v have width w/4 */ char *dy = ov->pixels[0], *du = ov->pixels[1], *dv = ov->pixels[2]; for (iy = 0; iy < win->rect.h ; iy += 2) { for (ix = 0; ix < w ; ix += 2) { dy[ix] = y[ix/2]; dy[ix+1] = y[ix/2]; dy[ w + ix] = y[ix/2]; dy[ w + ix+1] = y[ix/2]; du[ix/2] = u[ix/4]; dv[ix/2] = v[ix/4]; } dy += 2*w; // 2 vertical lines du += w/2; // 2 vertical lines dv += w/2; // 2 vertical lines y += w/2; if (iy & 2) { u += w / 4; v += w / 4; } } } else switch (which) { case 0: memcpy(ov->pixels[0],y,ysize); memcpy(ov->pixels[1],u,uvsize); memcpy(ov->pixels[2],v,uvsize); break; case 1: /* mirror x */ mirror_x(y, ov->pixels[0], win->rect.w, win->rect.h); mirror_x(u, ov->pixels[1], win->rect.w/2, win->rect.h/2); mirror_x(v, ov->pixels[2], win->rect.w/2, win->rect.h/2); break; case 2: /* mirror y */ mirror_y(y, ov->pixels[0], win->rect.w, win->rect.h); mirror_y(u, ov->pixels[1], win->rect.w/2, win->rect.h/2); mirror_y(v, ov->pixels[2], win->rect.w/2, win->rect.h/2); break; case 3: /* mirror x, then mirror y */ mirror_x(y, ov->pixels[0], win->rect.w, win->rect.h); mirror_y(ov->pixels[0], ov->pixels[0], win->rect.w, win->rect.h); mirror_x(u, ov->pixels[1], win->rect.w/2, win->rect.h/2); mirror_y(ov->pixels[1], ov->pixels[1], win->rect.w/2, win->rect.h/2); mirror_x(v, ov->pixels[2], win->rect.w/2, win->rect.h/2); mirror_y(ov->pixels[2], ov->pixels[2], win->rect.w/2, win->rect.h/2); break; } SDL_UnlockYUVOverlay(win->overlay); return 0; } int main(int argc, char **argv) { #ifndef NOGUI int zoom = 1; Uint8 *keylist; struct my_window w1, w2, w3, w4; SDL_Surface *screen; int n_win = 1; /* or 2 */ int n_y = 1; /* or 2 */ int fullscreen = 0; int mode = 0, failed = 0; SDL_Event event; SDL_TimerID timerid; SDL_Rect rect = { 0 }; int initflags = SDL_INIT_VIDEO; int sdlflags = SDL_RESIZABLE; int format = SDL_YV12_OVERLAY; int swsurface = 0; int bpp = 0; int ysize, uvsize; unsigned char *u, *v; char buf[80]; Uint32 interval = 3000; int headless = 0; int greymode = 0; #else unsigned int interval = 3000; int headless = 1; #endif int use_select = 0; struct timespec tv; struct video_window vw = { 0 }; struct video_picture vp; const char *device = "/dev/video0"; unsigned int fps = 5; int snapcnt = 0; int frozen = 0; int i = 3; /* sizeidx (sif) */ JSAMPARRAY jdata[3]; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; int quality = 75; const char *outfile = "/tmp/%Y%m%d%H%M%S.jpg"; const char *command = NULL; int fd; int imgsize; int ch, size; unsigned char *y; int palette = VIDEO_PALETTE_YUV420P; while((ch = getopt(argc,argv,"24SzyaxhmMb:p:q:o:d:e:f:i:c:s:?")) != -1) { switch(ch) { #ifndef NOGUI case '2': n_win = 2; format = SDL_IYUV_OVERLAY; break; /* two windows */ case '4': n_win = 2; n_y = 2; format = SDL_IYUV_OVERLAY; break; /* two windows */ case 'z': zoom = 2; format = SDL_IYUV_OVERLAY; break; case 'y': format = SDL_IYUV_OVERLAY; break; case 'a': sdlflags |= SDL_ANYFORMAT; break; case 'x': sdlflags |= SDL_NOFRAME; break; case 'h': headless = 1; break; case 'M': mirror = 1; break; case 'm': swsurface = 1; break; case 'b': bpp = atoi(optarg); break; case 'p': palette = atoi(optarg); break; #endif case 'S': use_select = 1; break; /* test whether select works */ case 'q': quality = atoi(optarg); break; case 'o': outfile = optarg; break; case 'd': device = optarg; break; case 'e': command = optarg; break; case 'f': fps = strtoul(optarg,NULL,10); break; case 'i': interval = strtoul(optarg,NULL,10); break; case 'c': snapcnt = atoi(optarg); if(snapcnt < -1) { fprintf(stderr,"Invalid snapshot count: %d\n",snapcnt); return 1; } break; case 's': for(i = 0; i < PSZ_MAX; ++i) if(strcmp(sizes[i].name,optarg) == 0) break; if(i == PSZ_MAX) { fprintf(stderr,"Invalid size, valid sizes: sqcif, qsif, qcif, sif, cif, vga\n"); return 1; } break; case '?': default: return usage(); } } if(fps < 5 || fps > 30) { fprintf(stderr,"Invalid framerate, framerate must be in the range 5-30\n"); return 1; } if(!headless && interval < (((1000 / fps)/10)*10)) interval = (((1000 / fps)/10)*10); vw.width = sizes[i].width; vw.height= sizes[i].height; vw.flags = fps << PWC_FPS_SHIFT; /* XXX pwc-specific ? */ imgsize = (vw.width * vw.height * 3)/2; if((fd = open(device, O_RDONLY)) < 0) { perror("Failed to open webcam"); exit(1); } fcntl(fd,F_SETFD,FD_CLOEXEC); if(ioctl(fd,VIDIOCSWIN,&vw) == -1) { fprintf(stderr,"Failed to set webcam to: %dx%d (%s) at %d fps (%s)\n", vw.width,vw.height,sizes[i].name,fps,strerror(errno)); exit(1); } fprintf(stderr,"Webcam set to: %dx%d (%s) at %d fps\n",vw.width,vw.height,sizes[i].name,fps); if(ioctl(fd,VIDIOCGPICT,&vp) == -1) { perror("Failed to get current picture info"); return -1; } fprintf(stderr, "contrast %d bright %d colour %d hue %d whiteness %d palette %d\n", vp.contrast, vp.brightness, vp.colour, vp.hue, vp.whiteness, vp.palette); if (palette > 0) { vp.palette = palette; if(ioctl(fd,VIDIOCSPICT,&vp) == -1) { perror("Failed to set new palette"); return -1; } } if(headless && snapcnt == 0) { /* Done */ close(fd); exit(0); } y = malloc(imgsize); if(y == NULL) { perror("Out of memory"); exit(1); } jpeg_init(vw.width,vw.height,quality,&cinfo,&jerr,jdata,(JSAMPROW)y); if(command != NULL) signal(SIGCHLD,sig_chld); #ifndef NOGUI if(!headless) { rect.w = vw.width * zoom; rect.h = vw.height * zoom; ysize = vw.width * vw.height; uvsize = ysize / 4; if(format == SDL_IYUV_OVERLAY) { u = y + ysize; v = u + uvsize; } else { v = y + ysize; u = v + uvsize; } if(snapcnt != 0) initflags |= SDL_INIT_TIMER; if (SDL_Init(initflags) < 0) { fprintf(stderr,"Failed to init sdl: %s\n", SDL_GetError()); exit(1); } atexit(SDL_Quit); sdlflags |= swsurface ? SDL_SWSURFACE : SDL_HWSURFACE; if((screen = SDL_SetVideoMode(n_win*rect.w, n_y*rect.h, bpp, sdlflags)) == NULL) { fprintf(stderr,"SDL Failed to set videomode: %s\n", SDL_GetError()); exit(1); } w1.rect = rect; w1.format = format; if (create_window(screen, &w1)) exit(1); if (n_win == 2) { w2 = w1; w2.rect.x = w2.rect.w; /* offset */ if (create_window(screen, &w2)) exit(1); if (n_y == 2) { w3 = w1; w3.rect.y = w1.rect.h; /* offset */ if (create_window(screen, &w3)) exit(1); w4 = w2; w2.rect.y = w2.rect.h; /* offset */ if (create_window(screen, &w4)) exit(1); } } snprintf(buf,80,"pwcview"); keylist = SDL_GetKeyState(NULL); if(snapcnt != 0) timerid = SDL_AddTimer(interval,cbtimer,NULL); } #endif for (;;) { int res; if (use_select) { struct timeval to = { 1, 0 }; struct fd_set r; int nfds = fd + 1; int i; struct pollfd p[1]; FD_ZERO(&r); FD_SET(fd, &r); i = select (nfds, &r, NULL, NULL, &to); if (i <= 0 ) fprintf(stderr, "select returns %d\n", i); p[0].fd = fd; p[0].events = POLLIN | POLLRDNORM; i = poll(p, 1, 1000); if (i <= 0 ) fprintf(stderr, "poll returns %d\n", i); } res = frozen || ((size = read(fd,y,imgsize)) > 0) || (size == -1 && errno == EINTR); if (!res) break; if(!frozen && size != imgsize) { if(size != -1) { fprintf(stderr,"Warning short read, got only %d of %d bytes\n",size,imgsize); } continue; } if(headless) { jpeg_write(vw.height,jdata,&cinfo,outfile,command); if(snapcnt > 0) snapcnt--; if(snapcnt == 0) exit(0); tv.tv_sec = interval / 1000; tv.tv_nsec = (interval % 1000) * 1000000; while(nanosleep(&tv,&tv) == -1 && errno == EINTR) ; continue; } if (greymode) { memset(u, 128, uvsize); memset(v, 128, uvsize); } #ifndef NOGUI refill_image(&w1, y, u, v, ysize, uvsize, zoom); if (n_win == 2) { refill_image(&w2, y, u, v, ysize, uvsize, zoom); if (n_y == 2) { refill_image(&w3, y, u, v, ysize, uvsize, zoom); refill_image(&w4, y, u, v, ysize, uvsize, zoom); } } SDL_DisplayYUVOverlay(w1.overlay, &w1.rect); if (n_win == 2) { SDL_DisplayYUVOverlay(w2.overlay, &w2.rect); if (n_y == 2) { SDL_DisplayYUVOverlay(w3.overlay, &w3.rect); SDL_DisplayYUVOverlay(w4.overlay, &w4.rect); } } SDL_PumpEvents(); if(failed == 0) SDL_WM_SetCaption(buf,buf); failed = 1; if (event.type == SDL_KEYDOWN) { if(keylist[SDLK_RIGHT]) { failed = handler[mode](fd,1,buf); continue; } else if(keylist[SDLK_LEFT]) { failed = handler[mode](fd,-1,buf); continue; } } for (;;) { if ( (frozen && !SDL_WaitEvent(&event) ) || (!frozen && !SDL_PollEvent(&event)) ) break; /* no events to handle */ if(event.type == SDL_KEYDOWN) { switch(event.key.keysym.sym) { case SDLK_DOWN: if(mode != sizeof(handler)/sizeof(handler[0]) - 1) failed = handler[++mode](fd,0,buf); break; case SDLK_UP: if(mode != 0) failed = handler[--mode](fd,0,buf); break; case SDLK_RETURN: failed = handler[mode](fd,2,buf); break; case SDLK_g: greymode = !greymode; break; case SDLK_f: SDL_WM_ToggleFullScreen(screen); fullscreen = !fullscreen; SDL_WM_GrabInput(fullscreen ? SDL_GRAB_ON : SDL_GRAB_OFF); break; case SDLK_p: jpeg_write(vw.height,jdata,&cinfo,outfile,command); break; case SDLK_SPACE: frozen = !frozen; break; case SDLK_q: exit(0); default: break; } } else if(event.type == SDL_VIDEORESIZE) { rect.w = event.resize.w / n_win; rect.h = event.resize.h; if((screen = SDL_SetVideoMode(n_win*rect.w, n_y*rect.h, bpp, sdlflags)) == NULL) { fprintf(stderr,"SDL Failed to set videomode: %s\n", SDL_GetError()); exit(1); } } else if(event.type == SDL_USEREVENT) { jpeg_write(vw.height,jdata,&cinfo,outfile,command); if(snapcnt > 0) snapcnt--; if(snapcnt == 0) SDL_RemoveTimer(timerid); } else if(event.type == SDL_QUIT) { exit(0); } } #endif } if(size != 0) perror("Error reading from webcam"); close(fd); jpeg_destroy_compress(&cinfo); return 0; } linux_compat/asm000755 000423 000000 00000000000 10601723335 014517 5ustar00luigiwheel000000 000000 linux_compat/linux000755 000423 000000 00000000000 10601723335 015076 5ustar00luigiwheel000000 000000 linux_compat/media000755 000423 000000 00000000000 10601723335 015016 5ustar00luigiwheel000000 000000 linux_compat/media/v4l2-common.h000644 000423 000000 00000000247 10560214250 017321 0ustar00luigiwheel000000 000000 #ifndef _LINUX_V4L2_COMMON_H_ #define _LINUX_V4L2_COMMON_H_ #include void v4l_printk_ioctl(unsigned int cmd); #endif /* _LINUX_V4L2_COMMON_H_ */ linux_compat/media/v4l2-dev.h000644 000423 000000 00000002366 10562713306 016623 0ustar00luigiwheel000000 000000 /* * * V 4 L 2 D R I V E R H E L P E R A P I * * Moved from videodev2.h * * Some commonly needed functions for drivers (v4l2-common.o module) */ #ifndef _LINUX_V4L2_DEV_H #define _LINUX_V4L2_DEV_H #include /* NULL */ #include /* some hidden struct... */ struct video_device; struct file; // #include /* struct file */ // struct class_device_attribute; #include /* full struct device */ #include /* 32 Bits compatibility layer for 64 bits processors */ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg); void video_device_remove_file(struct video_device *vfd, struct class_device_attribute *attr); /* Compatibility layer interface -- v4l1-compat module */ typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file, unsigned int cmd, void *arg); #ifdef CONFIG_VIDEO_V4L1_COMPAT int v4l_compat_translate_ioctl(struct inode *inode, struct file *file, int cmd, void *arg, v4l2_kioctl driver_ioctl); #else #define v4l_compat_translate_ioctl(inode,file,cmd,arg,ioctl) -EINVAL #endif #endif /* _LINUX_V4L2_DEV_H */ linux_compat/linux/capability.h000644 000423 000000 00000000000 10560333140 017430 0ustar00luigiwheel000000 000000 linux_compat/linux/compiler.h000644 000423 000000 00000004305 10560205144 017137 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef __LINUX_COMPILER_H #define __LINUX_COMPILER_H /* * $Id: compiler.h,v 1.4 2007/01/31 21:30:12 luigi Exp $ * * Stripped down version of the attribute-like defines used in the * linux kernel. We normally redefine everything to a no-op * (booleans become 0 as that is the OK case). */ #define __user #define __kernel #define __safe #define __force #define __nocast #define __iomem #define __chk_user_ptr(x) 0 #define __chk_io_ptr(x) 0 #define __builtin_warning(x, y...) (1) #define __acquires(x) #define __releases(x) #define __acquire(x) 0 #define __release(x) 0 #define __cond_lock(x,c) (c) #define __devinitdata // unknown attribute #define __init // __attribute ((constructor)) #define __exit // __attribute ((destructor)) #define __stringify(x) #x // for use outside macros #define typeof(x) __typeof(x) #endif /* __LINUX_COMPILER_H */ linux_compat/linux/config.h000644 000423 000000 00000000000 10554510224 016557 0ustar00luigiwheel000000 000000 linux_compat/linux/cputype.h000644 000423 000000 00000000000 10554510224 017003 0ustar00luigiwheel000000 000000 linux_compat/linux/ctype.h000644 000423 000000 00000004456 10560214247 016464 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _LINUX_CTYPE_H #define _LINUX_CTYPE_H /* * stub for the linux ctype.h - we remap it to the FreeBSD one. */ #include /* * endiannes conversion */ static inline uint32_t le32_to_cpup(const __le32 *p) { return p[0] + (p[1]<<8) + (p[2] << 16) + (p[3]<<24); } static inline uint16_t le16_to_cpup(const __le16 *p) { return p[0] + p[1]*256; } static inline uint16_t le16_to_cpu(__le16 x) { uint8_t *p = (uint8_t *)&x; return p[0] + p[1]*256; } #define cpu_to_le32(x) __cpu_to_le32(x) #define cpu_to_le16(x) __cpu_to_le16(x) static inline uint32_t __cpu_to_le32(uint32_t x) { __le32 dst; uint8_t *p = (uint8_t *)&dst; p[0] = x & 0xff; p[1] = (x>>8) & 0xff; p[2] = (x>>16) & 0xff; p[3] = (x>>24) & 0xff; return dst; } static inline uint16_t __cpu_to_le16(uint16_t x) { __le16 dst; uint8_t *p = (uint8_t *)&dst; p[0] = x & 0xff; p[1] = (x>>8) & 0xff; return dst; } unsigned int hweight8(unsigned int w); #endif /* _LINUX_CTYPE_H */ linux_compat/linux/device.h000644 000423 000000 00000013224 10556707034 016576 0ustar00luigiwheel000000 000000 #ifndef _LINUX_DEVICE_H_ #define _LINUX_DEVICE_H_ // #include /* in sysfs.h */ struct attribute { const char * name; struct module * owner; mode_t mode; }; /* end sysfs.h */ struct class; struct class_device; struct class_attribute { struct attribute attr; ssize_t (*show)(struct class *, char * buf); ssize_t (*store)(struct class *, const char * buf, size_t count); }; struct class_device_attribute { struct attribute attr; ssize_t (*show)(struct class_device *, char * buf); ssize_t (*store)(struct class_device *, const char * buf, size_t count); }; #define __ATTR(_name,_mode,_show,_store) { \ .attr = { \ .name = __stringify(_name), \ .mode = _mode, \ .owner = THIS_MODULE }, \ .show = _show, \ .store = _store, \ } #define CLASS_DEVICE_ATTR(_name,_mode,_show,_store) \ struct class_device_attribute \ __attribute__ ((unused)) \ class_device_attr_##_name = \ __ATTR(_name,_mode,_show,_store) /** * struct class_device - class devices * @class: pointer to the parent class for this class device. This is required. * @devt: for internal use by the driver core only. * @node: for internal use by the driver core only. * @kobj: for internal use by the driver core only. * @devt_attr: for internal use by the driver core only. * @groups: optional additional groups to be created * @dev: if set, a symlink to the struct device is created in the sysfs * directory for this struct class device. * @class_data: pointer to whatever you want to store here for this struct * class_device. Use class_get_devdata() and class_set_devdata() to get and * set this pointer. * @parent: pointer to a struct class_device that is the parent of this struct * class_device. If NULL, this class_device will show up at the root of the * struct class in sysfs (which is probably what you want to have happen.) * @release: pointer to a release function for this struct class_device. If * set, this will be called instead of the class specific release function. * Only use this if you want to override the default release function, like * when you are nesting class_device structures. * @uevent: pointer to a uevent function for this struct class_device. If * set, this will be called instead of the class specific uevent function. * Only use this if you want to override the default uevent function, like * when you are nesting class_device structures. */ struct class_device { #if 0 struct list_head node; struct kobject kobj; struct class * class; /* required */ dev_t devt; /* dev_t, creates the sysfs "dev" */ struct class_device_attribute *devt_attr; struct class_device_attribute uevent_attr; struct device * dev; /* not necessary, but nice to have */ void * class_data; /* class-specific data */ struct class_device *parent; /* parent of this child device, if there is one */ struct attribute_group ** groups; /* optional groups */ void (*release)(struct class_device *dev); int (*uevent)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size); char class_id[BUS_ID_SIZE]; /* unique to this class */ #endif }; /* * In FreeBSD, a struct device is defined only in kern/subr_bus.c */ struct device { #if 0 struct klist klist_children; struct klist_node knode_parent; /* node in sibling list */ struct klist_node knode_driver; struct klist_node knode_bus; #endif struct device * parent; #if 0 struct kobject kobj; char bus_id[BUS_ID_SIZE]; /* position on parent bus */ struct device_attribute uevent_attr; struct semaphore sem; /* semaphore to synchronize calls to * its driver. */ struct bus_type * bus; /* type of bus device is on */ struct device_driver *driver; /* which driver has allocated this device */ #endif void *driver_data; /* data private to the driver */ #if 0 void *platform_data; /* Platform specific data, device core doesn't touch it */ void *firmware_data; /* Firmware specific data (e.g. ACPI, BIOS data),reserved for device core*/ struct dev_pm_info power; u64 *dma_mask; /* dma mask (if dma'able device) */ u64 coherent_dma_mask;/* Like dma_mask, but for alloc_coherent mappings as not all hardware supports 64 bit addresses for consistent allocations such descriptors. */ struct list_head dma_pools; /* dma pools (if dma'ble) */ struct dma_coherent_mem *dma_mem; /* internal for coherent mem override */ void (*release)(struct device * dev); #endif }; static inline void * dev_get_drvdata (struct device *dev) { return dev->driver_data; } static inline void dev_set_drvdata (struct device *dev, void *data) { dev->driver_data = data; } #endif /* _LINUX_DEVICE_H_ */ linux_compat/linux/fs.h000644 000423 000000 00000010262 10556701514 015743 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _LINUX_FS_H #define _LINUX_FS_H /* * $Id: fs.h,v 1.4 2007/01/27 16:52:28 luigi Exp $ * Prototype of the struct file_operations used in device drivers. * We also include here a placeholder for 'struct file' */ /* from file.h */ struct file { void *private_data; int f_flags; }; // struct kiocb; /* in aio.h */ struct poll_table_struct; // XXX dummy // struct dentry; // XXX dummy struct vm_area_struct; // XXX dummy // struct file_lock; // XXX dummy // typedef void * filldir_t; // XXX dummy // typedef void * read_actor_t; // XXX dummy #define no_llseek NULL /* * NOTE: * read, write, poll, fsync, readv, writev, unlocked_ioctl and compat_ioctl * can be called without the big kernel lock held in all filesystems. */ struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); // ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); // ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t); // int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); // int (*fsync) (struct file *, struct dentry *, int datasync); // int (*aio_fsync) (struct kiocb *, int datasync); // int (*fasync) (int, struct file *, int); // int (*lock) (struct file *, int, struct file_lock *); // ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); // ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); // ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *); // ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); // unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*dir_notify)(struct file *filp, unsigned long arg); // int (*flock) (struct file *, int, struct file_lock *); // ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); // ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); }; #endif /* _LINUX_FS_H */ linux_compat/linux/gfp.h000644 000423 000000 00000000664 10560061360 016105 0ustar00luigiwheel000000 000000 #ifndef __LINUX_GFP_H #define __LINUX_GFP_H //unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order); #define __get_free_page(gfp_mask) malloc(4096, M_USBDEV, M_NOWAIT) //void __free_pages(struct page *page, unsigned int order); //void free_pages(unsigned long addr, unsigned int order); //#define __free_page(page) __free_pages((page), 0) #define free_page(addr) free((void *)(addr), M_USBDEV) #endif /* __LINUX_GFP_H */ linux_compat/linux/init.h000644 000423 000000 00000011474 10562707224 016305 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id: init.h,v 1.20 2007/02/08 20:56:52 luigi Exp $ * * Init info for linux-over-FreeBSD modules. * This has been basically rewritten from scratch and has significant * differences from the equivalent linux file because we need some * emulation stuff as well. In particular, we define the following: * * - macro MODINFO_NAME(x) to generate a unique name for entry 'x', * dependent on the DRIVER_NAME macro (set at compile time). * We use this macro to name globally visible symbols, so to avoid * name clashes in case we want to link the modules statically; * * - a linker set that is used to store information on the linux driver * collected at compile time (through macros). These go into * "struct bsd_module_init_t" entries in the ldev_info linker set; * * - "struct linux_dev_info" to store information on the linux driver * collected at run time, either directly (e.g. through usb_register()), * or later imported from the linker set. * There is a global variable of this type, named MODINFO_NAME(info), * because its fields are set by different source files. * * - functions to fill linux_dev_info */ #ifndef _LINUX_INIT_H #define _LINUX_INIT_H #include // device_t #include // SET_DECLARE /* * types and struct for the entries saved in the linker set. */ enum bsd_module_entry { BSD_MOD_UNDEFINED = 0, BSD_MOD_LOAD_HANDLER, BSD_MOD_UNLOAD_HANDLER, BSD_MOD_DEVICE_TABLE, BSD_MOD_DEVINFO, }; struct bsd_module_init_t { enum bsd_module_entry type; const char * name; void * value; }; SET_DECLARE(ldev_info, struct bsd_module_init_t); /* * The structure where device-specific info is stored, either directly * (e.g. usb_register stores here) or after being collected from a * linker data_set. * There is one global variable of this type for each * driver, named MODINFO_NAME(info) */ struct linux_dev_info { int (*init_f)(void); int (*exit_f)(void); struct usb_device_id *device_table; struct usb_driver *usb_driver_desc; int initialized; }; /* * Generate a unique variable name for the driver. * We need the two passes to cause the expansion of the * second argument. */ #define __M2(x, y) module_ ## y ## _ ## x #define __M1(x, y) __M2(x, y) #define MODINFO_NAME(x) __M1(x, DRIVER_NAME) extern struct linux_dev_info MODINFO_NAME(info); /* * Some info are collected in a linker set, below. */ #define _bsd_module_ty(t, ptr) \ static struct bsd_module_init_t _mod_##ptr = { \ .type = t, \ .name = #ptr, \ .value = ptr \ }; \ DATA_SET(ldev_info, _mod_##ptr) #define module_init(initfn) \ _bsd_module_ty(BSD_MOD_LOAD_HANDLER, initfn) #define module_exit(exitfn) \ _bsd_module_ty(BSD_MOD_UNLOAD_HANDLER, exitfn) /* * This is called at the beginning of the modevent_handler to copy the * information from the linker set to a struct where it is easier to use. */ void linux_devinfo_init(struct linux_dev_info *i); /* * This is the basic usb device matching routine. */ const struct usb_device_id * ldev_lookup(device_t dev, struct usb_device_id *p); struct linux_usb_descriptors; /* in linux/ldev_stub.h */ /* * Prepare the linux emulation descriptors before the linux calls */ int fill_linux_descriptors(device_t dev, struct linux_usb_descriptors *ld); /* wrapper around tsleep */ int wait_event_body(void *wc, int flags); #endif /* _LINUX_INIT_H */ linux_compat/linux/jiffies.h000644 000423 000000 00000003125 10557406736 016763 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id: jiffies.h,v 1.4 2007/01/29 15:08:14 luigi Exp $ * * For those routines using jiffies... */ #ifndef _LINUX_JIFFIES_H #define _LINUX_JIFFIES_H u64 get_jiffies_64(void); int jiffies_to_msecs(u64 j); #endif /* _LINUX_JIFFIES_H */ linux_compat/linux/kernel.h000644 000423 000000 00000002777 10562713277 016635 0ustar00luigiwheel000000 000000 #ifndef __LINUX_KERNEL_H #define __LINUX_KERNEL_H #define DBG(fmt , A...) \ printf("%d [%4d] %s: " fmt , ticks, __LINE__, __FUNCTION__, ## A) #define BUG() DBG("BUG\n") /* * unfortunately printf is in systm.h */ // int printf(const char *, ...) __printflike(1, 2); /* * These macros are used to navigate within nested structures. * * offsetof(TYPE, MEMBER) returns the offset of the member in the type. * It is already in the base FreeBSD so we don't redefine it * * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * * Note that this implementation is slightly different from the linux one, * which triggered sme compiler warnings. */ #define container_of(ptr, type, member) ({ \ __typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define KERN_EMERG "<0>" /* system is unusable */ #define KERN_ALERT "<1>" /* action must be taken immediately */ #define KERN_CRIT "<2>" /* critical conditions */ #define KERN_ERR "<3>" /* error conditions */ #define KERN_WARNING "<4>" /* warning conditions */ #define KERN_NOTICE "<5>" /* normal but significant condition */ #define KERN_INFO "<6>" /* informational */ #define KERN_DEBUG "<7>" /* debug-level messages */ #endif /* __LINUX_KERNEL_H */ linux_compat/linux/kref.h000644 000423 000000 00000001251 10560333140 016247 0ustar00luigiwheel000000 000000 /* * kref.c - library routines for handling generic reference counted objects * * Copyright (C) 2004 Greg Kroah-Hartman * Copyright (C) 2004 IBM Corp. * * based on kobject.h which was: * Copyright (C) 2002-2003 Patrick Mochel * Copyright (C) 2002-2003 Open Source Development Labs * * This file is released under the GPLv2. * */ #ifndef _LINUX_KREF_H_ #define _LINUX_KREF_H_ #include #include struct kref { atomic_t refcount; }; void kref_init(struct kref *kref); void kref_get(struct kref *kref); int kref_put(struct kref *kref, void (*release) (struct kref *kref)); #endif /* _KREF_H_ */ linux_compat/linux/list.h000644 000423 000000 00000014561 10563032571 016312 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id: list.h,v 1.8 2007/02/09 08:48:57 luigi Exp $ * * Simple linked list head */ #ifndef _LINUX_LIST_H #define _LINUX_LIST_H /********** include/linux/list.h **********/ /* * These are non-NULL pointers that will result in page faults * under normal circumstances, used to verify that nobody uses * non-initialized list entries. */ #define LIST_POISON1 ((void *) 0x00100100) #define LIST_POISON2 ((void *) 0x00200200) static inline void prefetch(const void *x) {} // don't bother for now struct list_head { struct list_head *next; struct list_head *prev; }; #if 0 // ndef _SYS_QUEUE_H_ /* FreeBSD_CONFLICT */ #define _SYS_QUEUE_H_ /* these conflict with the FreeBSD macros */ #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) #endif /* _SYS_QUEUE_H_ */ static inline void INIT_LIST_HEAD(struct list_head *list) { list->next = list; list->prev = list; } /** * list_empty - tests whether a list is empty * @head: the list to test. */ static inline int list_empty(const struct list_head *head) { return head->next == head; } /* * Delete a list entry by making the prev/next entries * point to each other. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static inline void __list_del(struct list_head * prev, struct list_head * next) { next->prev = prev; prev->next = next; } /** * list_del - deletes entry from list. * @entry: the element to delete from the list. * Note: list_empty on entry does not return true after this, the entry is * in an undefined state. */ static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; } /** * list_entry - get the struct for this entry * @ptr: the &struct list_head pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. */ #define list_entry(ptr, type, member) \ container_of(ptr, type, member) /** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */ #define list_for_each(pos, head) \ for (pos = (head)->next; prefetch(pos->next), pos != (head); \ pos = pos->next) /** * list_for_each_safe - iterate over a list safe against removal of list entry * @pos: the &struct list_head to use as a loop cursor. * @n: another &struct list_head to use as temporary storage * @head: the head for your list. */ #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) /** * list_for_each_entry - iterate over list of given type * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_struct within the struct. */ #define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ prefetch(pos->member.next), &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) /** * list_for_each_entry_continue - continue iteration over list of given type * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_struct within the struct. * * Continue to iterate over list of given type, continuing after * the current position. */ #define list_for_each_entry_continue(pos, head, member) \ for (pos = list_entry(pos->member.next, typeof(*pos), member); \ prefetch(pos->member.next), &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) /* * Insert a new entry between two known consecutive entries. * * This is only for internal list manipulation where we know * the prev/next entries already! */ static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new; } /** * list_add - add a new entry * @new: new entry to be added * @head: list head to add it after * * Insert a new entry after the specified head. * This is good for implementing stacks. */ static inline void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); } /** * list_add_tail - add a new entry * @new: new entry to be added * @head: list head to add it before * * Insert a new entry before the specified head. * This is useful for implementing queues. */ static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } #endif /* _LINUX_LIST_H */ linux_compat/linux/mm.h000644 000423 000000 00000006710 10560214247 015744 0ustar00luigiwheel000000 000000 #ifndef _LINUX_MM_H #define _LINUX_MM_H #include struct vm_operations_struct; /* * This struct defines a memory VMM memory area. There is one of these * per VM-area/task. A VM area is any part of the process virtual memory * space that has a special rule for the page-fault handlers (ie a shared * library, the executable area etc). * XXX we do the minimum we need. */ struct vm_area_struct { unsigned long vm_start; /* Our start address within vm_mm. */ unsigned long vm_end; /* The first byte after our end address within vm_mm. */ unsigned long vm_flags; /* Flags, listed below. */ unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */ struct vm_operations_struct * vm_ops; void * vm_private_data; /* was vm_pte (shared mem) */ }; /* * vm_flags.. */ /* * vm_flags.. */ #define VM_READ 0x00000001 /* currently active flags */ #define VM_WRITE 0x00000002 #define VM_EXEC 0x00000004 #define VM_SHARED 0x00000008 /* mprotect() hardcodes VM_MAYREAD >> 4 == VM_READ, and so for r/w/x bits. */ #define VM_MAYREAD 0x00000010 /* limits for mprotect() etc */ #define VM_MAYWRITE 0x00000020 #define VM_MAYEXEC 0x00000040 #define VM_MAYSHARE 0x00000080 #define VM_GROWSDOWN 0x00000100 /* general info on the segment */ #define VM_GROWSUP 0x00000200 #define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */ #define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */ #define VM_EXECUTABLE 0x00001000 #define VM_LOCKED 0x00002000 #define VM_IO 0x00004000 /* Memory mapped I/O or similar */ /* Used by sys_madvise() */ #define VM_SEQ_READ 0x00008000 /* App will access data sequentially */ #define VM_RAND_READ 0x00010000 /* App will not benefit from clustered reads */ #define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork */ #define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() */ #define VM_RESERVED 0x00080000 /* Count as reserved_vm like IO */ #define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */ #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */ #define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */ #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS #endif /* * These are the virtual MM functions - opening of an area, closing and * unmapping it (needed to keep files on disk up-to-date etc), pointer * to the functions called when a no-page or a wp-page exception occurs. */ struct vm_operations_struct { void (*open)(struct vm_area_struct * area); void (*close)(struct vm_area_struct * area); /* there are more */ }; int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *); unsigned long vmalloc_to_pfn(void *addr); /* XXX this should not be done so late! */ #include #include /* from slab.h */ #define kzalloc(sz, gfp_t) malloc(sz, M_USBDEV, M_NOWAIT | M_ZERO) #endif /* _LINUX_MM_H */ linux_compat/linux/module.h000644 000423 000000 00000022023 10776737730 016633 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _LINUX_MODULE_H #define _LINUX_MODULE_H /* * $Id: module.h,v 1.26 2008/04/08 18:56:24 luigi Exp $ * * Emulation of linux/module.h * * We start including all the FreeBSD kernel files normally used by modules, * followed by the linux-specific files (those in this directory). */ #include /* conflict on list macros, try -D_SYS_QUEUE_H_ */ #if 0 // ndef _SYS_QUEUE_H_ #define _SYS_QUEUE_H_ /* disable lists */ #endif #include // conflict on version #include /* ticks */ #include /* _IOR and friends */ // #include // #include //- #include // list.h #include /* O_NONBLOCK */ // #include // #include // #include // #include // #include // #include // #include // #include // #include #include /* * now the linux-specific stuff */ #include #include #include #include #include // XXX our types... #include #include #include // __u16 etc #include // module_param etc #include // file etc. /* in stat.h */ /* this is used in CLASS_DEVICE_ATTR() macros. * We don't really care about it by now. */ #define S_IRUGO 0 // XXX not really /* in errno.h */ /* Should never be seen by user programs */ #define ERESTARTSYS 512 #define ENOIOCTLCMD 515 /* No ioctl command */ #define ENODATA 61 /* No data available (2.4 only ?) */ #define ETIME 62 /* Timer expired */ #define ENOSR 63 /* Out of streams resources */ #define EREMOTEIO 121 /* Remote I/O error */ /* v4l2 defs */ #define VFL_TYPE_GRABBER 0 #define VFL_TYPE_VBI 1 #define VFL_TYPE_RADIO 2 #define VFL_TYPE_VTX 3 /* videodev.h extensions */ struct video_device { /* device info */ struct device *dev; char name[32]; int type; /* v4l1 */ int type2; /* v4l2 */ int hardware; int minor; /* device ops + callbacks */ const struct file_operations *fops; void (*release)(struct video_device *vfd); #if 1 /* to be removed in 2.6.15 */ /* obsolete -- fops->owner is used instead */ struct module *owner; /* dev->driver_data will be used instead some day. * Use the video_{get|set}_drvdata() helper functions, * so the switch over will be transparent for you. * Or use {pci|usb}_{get|set}_drvdata() directly. */ void *priv; /* we use this as a pointer to the softc */ #endif /* for videodev.c intenal usage -- please don't touch */ int users; /* video_exclusive_{open|close} ... */ struct mtx lock; /* ... helper function uses these */ // XXX was mutex char devfs_name[64]; /* devfs */ struct class_device class_dev; /* sysfs */ }; /* * These two are obsolete and might be removed */ static inline void *video_get_drvdata(struct video_device *dev) { return dev->priv; } static inline void video_set_drvdata(struct video_device *dev, void *data) { dev->priv = data; } struct video_device* video_devdata(struct file*); int video_usercopy(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int (*func)(struct inode *inode, struct file *file, unsigned int cmd, void *arg)); int video_register_device(struct video_device *, int type, int nr); void video_unregister_device(struct video_device *); #define to_video_device(cd) container_of(cd, struct video_device, class_dev) struct video_device *video_device_alloc(void); void video_device_release(struct video_device *vfd); /* do something useless to silence compiler. * XXX try unused or something better */ #define video_device_create_file(a, b) ({void *x=a; (x == a) ? 0 : 1;}) #if 0 int video_device_create_file(struct video_device *vfd, struct class_device_attribute *attr); #endif /* in linux/module.h */ /* * In our emulation layer, the device table is stored in a linker set. */ #define MODULE_DEVICE_TABLE(type,name) \ _bsd_module_ty(BSD_MOD_DEVICE_TABLE, name) #define MODULE_PARM_DESC(_parm, desc) #define MODULE_AUTHOR(_name) #define MODULE_DESCRIPTION(_name) #define MODULE_LICENSE(_name) // extern struct module __this_module; #define THIS_MODULE (NULL) // (&__this_module) /* in uaccess.h */ unsigned long copy_to_user(void __user *to, const void *from, unsigned long n); unsigned long copy_from_user(void *to, const void __user *from, unsigned long n); #define info(format, arg...) \ printf("%s: " format "\n", __FUNCTION__ , ## arg) /* maybe somewhere else ? */ #define printk(fmt , args...) printf(fmt , ##args) #define warn(X...) printf(X) #define dbg(X...) printf(X) #define err(X...) printf(X) // #define udelay(x) tsleep("spca", PCATCH, "xx", x*HZ/1000000) /* make this non blocking */ #define kmalloc(siz,opt) malloc(siz, M_USBDEV, M_NOWAIT) #define kfree(pt) free(pt, M_USBDEV) #define HZ hz // on freebsd... #define udelay(t) DELAY(t) void linux_msleep(int ms); #if __FreeBSD_version > 700100 // adapt to a change between FreeBSD 6.x and 7.x #define msleep_compat(ms) linux_msleep(ms) #undef msleep #endif #define msleep(ms) linux_msleep(ms) // #define mdelay(ms) linux_msleep(ms) // maybe DELAY... */ #define mdelay(ms) DELAY(ms) // maybe DELAY... */ /* in gfp.h */ #define __GFP_WAIT ((gfp_t)0x10u) /* Can wait and reschedule? */ #define __GFP_HIGH ((gfp_t)0x20u) /* Should access emergency pools? */ #define __GFP_IO ((gfp_t)0x40u) /* Can start physical IO? */ #define __GFP_FS ((gfp_t)0x80u) /* Can call down to low-level FS? */ #define __GFP_COLD ((gfp_t)0x100u) /* Cache-cold page required */ #define __GFP_NOWARN ((gfp_t)0x200u) /* Suppress page allocation failure warning */ #define __GFP_REPEAT ((gfp_t)0x400u) /* Retry the allocation. Might fail */ #define __GFP_NOFAIL ((gfp_t)0x800u) /* Retry for ever. Cannot fail */ #define __GFP_NORETRY ((gfp_t)0x1000u)/* Do not retry. Might fail */ #define __GFP_NO_GROW ((gfp_t)0x2000u)/* Slab internal usage */ #define __GFP_COMP ((gfp_t)0x4000u)/* Add compound page metadata */ #define __GFP_ZERO ((gfp_t)0x8000u)/* Return zeroed page on success */ #define __GFP_NOMEMALLOC ((gfp_t)0x10000u) /* Don't use emergency reserves */ #define __GFP_HARDWALL ((gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */ /* This equals 0, but use constants in case they ever change */ #define GFP_NOWAIT (GFP_ATOMIC & ~__GFP_HIGH) /* GFP_ATOMIC means both !wait (__GFP_WAIT not set) and use emergency pool */ #define GFP_ATOMIC (__GFP_HIGH) #define GFP_NOIO (__GFP_WAIT) #define GFP_NOFS (__GFP_WAIT | __GFP_IO) #define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS) #define GFP_USER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL) #define GFP_HIGHUSER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \ __GFP_HIGHMEM) /* interrupt.h */ struct tasklet_struct { #if 0 struct tasklet_struct *next; unsigned long state; atomic_t count; #endif void (*func)(unsigned long); unsigned long data; }; void tasklet_schedule(struct tasklet_struct *t); void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data); #endif /* _LINUX_MODULE_H */ linux_compat/linux/moduleparam.h000644 000423 000000 00000002337 10563047140 017641 0ustar00luigiwheel000000 000000 #ifndef _LINUX_MODULEPARAM_H #define _LINUX_MODULEPARAM_H /* * module_param are user-settable controls that influence the * behaviour of a module. * The best way to implement them is, perhaps, a sysctl. */ #if 0 /* leave it empty for now... */ #define module_param(name, type, perm) \ type param__##name #else #include #define __a2(y) _debug_ ## y #define __a1(y) __a2(y) #define _mod_sysctl_name __a1(DRIVER_NAME) /* expansion of sysctl arguments */ #define SYSCTL_DECLn(x) SYSCTL_DECL1(x) #define SYSCTL_DECL1(x) SYSCTL_DECL(x) #define SYSCTL_NODEn(a, b, c, d, e, f) SYSCTL_NODE1(a, b, c, d, e, f) #define SYSCTL_NODE1(a, b, c, d, e, f) SYSCTL_NODE(a, b, c, d, e, f) #define SYSCTL_INTn(a, b, c, d, e, f, g) SYSCTL_INT1(a, b, c, d, e, f, g); #define SYSCTL_INT1(a, b, c, d, e, f, g) SYSCTL_INT(a, b, c, d, e, f, g); SYSCTL_DECLn(_mod_sysctl_name); #define module_param(name, type, perm) \ SYSCTL_INTn(_mod_sysctl_name, OID_AUTO, name, CTLFLAG_RW, \ &name, 0, "ldev " #name); #endif #define module_param_named(_name, _var, _ty, _val) #define module_param_array(name, type, ptr, perm) \ struct __dummy__##name { \ int *p; \ } __dummy_##name##__obj = { ptr } #endif /* _LINUX_MODULEPARAM_H */ linux_compat/linux/mutex.h000644 000423 000000 00000000661 10560155644 016501 0ustar00luigiwheel000000 000000 #ifndef __LINUX_MUTEX_H #define __LINUX_MUTEX_H #include #include #include struct mutex { struct mtx m; }; #define mutex_init(_m) mtx_init(&(_m)->m, "ldev", NULL, MTX_DEF) #define mutex_lock(_m) mtx_lock(&(_m)->m) static inline int mutex_lock_interruptible(struct mutex *_m) { mtx_lock(&(_m)->m); return 0; } #define mutex_unlock(_m) mtx_unlock(&(_m)->m) #endif /* __LINUX_MUTEX_H */ linux_compat/linux/page.h000644 000423 000000 00000002775 10560055652 016261 0ustar00luigiwheel000000 000000 #ifndef _LINUX_PAGE_H #define _LINUX_PAGE_H /* in page.h */ typedef struct { unsigned long pgprot; } pgprot_t; #define __pgprot(x) ((pgprot_t) { (x) } ) /* in page-flags.h */ #define SetPageReserved(page) do {} while (0) // set_bit(PG_reserved, &(page)->flags) #define ClearPageReserved(page) do {} while (0) // clear_bit(PG_reserved, &(page)->flags) /* end page-flags.h */ /* in pgtable.h */ /* XXX remap to freebsd */ #define _PAGE_PRESENT 0x001 #define _PAGE_RW 0x002 #define _PAGE_USER 0x004 #define _PAGE_ACCESSED 0x020 #define PAGE_SHARED \ __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) int remap_pfn_range(struct vm_area_struct *, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t); /* * XXX these need to be remapped to the FreeBSD equivalent. */ struct page; struct page *vmalloc_to_page(void *addr); /* Align the pointer to the (next) page boundary. * Note that on FreeBSD, PAGE_MASK = PAGE_SIZE -1, * whereas on Linux PAGE_MASK = (~(PAGE_SIZE-1)) */ #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&(~(PAGE_SIZE - 1))) void *page_address(struct page *page); /* * I think PAGE_OFFSET is the start of the kernel (virtual?) addres space. * Let's set it at 0xC0000000 for the time being. Not sure it is correct. * XXX note, this stuff is used in the mmap support. */ #define PAGE_OFFSET 0xC0000000 // XXX check it... #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) #endif /* _LINUX_PAGE_H */ linux_compat/linux/pagemap.h000644 000423 000000 00000000000 10554510224 016724 0ustar00luigiwheel000000 000000 linux_compat/linux/param.h000644 000423 000000 00000000000 10554510224 016412 0ustar00luigiwheel000000 000000 linux_compat/linux/poll.h000644 000423 000000 00000001345 10563032571 016301 0ustar00luigiwheel000000 000000 #ifndef _LINUX_POLL_H #define _LINUX_POLL_H #include /* POLLIN and friends */ // #include #include // #include // #include // #include struct poll_table_struct; /* * structures and helpers for f_op->poll implementations */ typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *); struct poll_table_struct { poll_queue_proc qproc; }; typedef struct poll_table_struct poll_table; static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) { if (p && wait_address) p->qproc(filp, wait_address, p); } #endif /* _LINUX_POLL_H */ linux_compat/linux/proc_fs.h000644 000423 000000 00000000000 10554510224 016745 0ustar00luigiwheel000000 000000 linux_compat/linux/sched.h000644 000423 000000 00000001355 10555154632 016426 0ustar00luigiwheel000000 000000 #ifndef _LINUX_SCHED_H #define _LINUX_SCHED_H /* * Task state bitmask. NOTE! These bits are also * encoded in fs/proc/array.c: get_task_state(). * * We have two separate sets of flags: task->state * is about runnability, while task->exit_state are * about the task exiting. Confusing, but this way * modifying one set can't modify the other one by * mistake. */ #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 #define TASK_STOPPED 4 #define TASK_TRACED 8 /* in tsk->exit_state */ #define EXIT_ZOMBIE 16 #define EXIT_DEAD 32 /* in tsk->state again */ #define TASK_NONINTERACTIVE 64 void schedule(void); #endif /* _LINUX_SCHED_H */ linux_compat/linux/slab.h000644 000423 000000 00000000000 10554510224 016233 0ustar00luigiwheel000000 000000 linux_compat/linux/smp_lock.h000644 000423 000000 00000000000 10554510224 017121 0ustar00luigiwheel000000 000000 linux_compat/linux/spinlock.h000644 000423 000000 00000001412 10562655616 017162 0ustar00luigiwheel000000 000000 #ifndef __LINUX_SPINLOCK_H #define __LINUX_SPINLOCK_H #include #include /* fromm spinlock_types.h */ typedef struct { // raw_spinlock_t raw_lock; struct mtx m; } spinlock_t; static inline void spin_lock_init(spinlock_t *lock) { mtx_init(&lock->m, "ldev-spin", NULL, MTX_SPIN); } static inline void spin_lock(spinlock_t *lock) { mtx_lock_spin(&lock->m); } static inline void spin_unlock(spinlock_t *lock) { mtx_unlock_spin(&lock->m); } #define spin_lock_irq(lock) spin_lock(lock) #define spin_lock_irqsave(lock, flags) do {flags = 0; spin_lock(lock); } while (0) #define spin_unlock_irqrestore(lock, flags) do { spin_unlock(lock); } while (0) #define spin_unlock_irq(lock) spin_unlock(lock) #endif /* __LINUX_SPINLOCK_H */ linux_compat/linux/stddef.h000644 000423 000000 00000000000 10555075224 016572 0ustar00luigiwheel000000 000000 linux_compat/linux/string.h000644 000423 000000 00000000453 10562707224 016643 0ustar00luigiwheel000000 000000 /* * string-related prototypes. */ #ifndef _LINUX_STRING_H #define _LINUX_STRING_H /* * in the freebsd kernel, string functions are in systm.h * which is problematic because it also brings in a lot of * extra stuff that might conflict with linux definitions. */ #endif /* _LINUX_STRING_H */ linux_compat/linux/time.h000644 000423 000000 00000000215 10560061360 016257 0ustar00luigiwheel000000 000000 #ifndef _LINUX_TIME_H #define _LINUX_TIME_H #include #define do_gettimeofday(tv) microtime(tv) #endif /* _LINUX_TIME_H */ linux_compat/linux/types.h000644 000423 000000 00000000666 10557775213 016516 0ustar00luigiwheel000000 000000 #ifndef _LINUX_TYPES_H #define _LINUX_TYPES_H /* stripped down version of the linux types */ #include #include #include /* linux-specific */ typedef __u16 __le16; typedef __u32 __le32; typedef unsigned long kernel_ulong_t; typedef unsigned int uint; typedef long long loff_t; // XXX double check typedef unsigned gfp_t; struct inode; /* dummy */ #endif /* _LINUX_TYPES_H */ linux_compat/linux/usb.h000644 000423 000000 00000122101 10776737730 016135 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id: usb.h,v 1.41 2008/04/08 18:56:24 luigi Exp $ * Compat file for linux/usb.h * * Here we implement the data structures needed to emulate the linux * kernel API on FreeBSD. The main part of this file is documentation * on the different structures seen by usb devices in both kernels. * Then we have the definition of various linux data structures, * trimmed removing all parts not used by drivers. */ #ifndef _LINUX_USB_H #define _LINUX_USB_H #include /* module_t */ #include /* KERNEL_VERSION */ #include /* for struct kref */ #include #include #include #include struct usb_device; struct usb_interface; #if 0 /* comments */ A bit of information on what (i think) are the usb architectures on Linux and FreeBSD. Each usb device has one or more interfaces. Each interface can have up to 8 endpoints. An endpoint can have a few alternate configurations. ===================== Linux Data Structures ====================== linux/device.h: struct device { ... struct device * parent; struct device_driver *driver; void *driver_data; ... } struct usb_host_interface { struct usb_interface_descriptor desc; /* array of desc.bNumEndpoint endpoints associated with this * interface setting. these will be in no particular order. * XXX we need to allocate this. */ struct usb_host_endpoint *endpoint; ... }; struct usb_interface { ... struct usb_host_interface *cur_altsetting; /* current setting */ struct device dev; ... } struct usb_device { ... struct device dev; ... } There is one descriptor per interface (intf), linked to the parent usb_device (udev) through the 'struct device' in each of them, as below: struct usb_interface *intf; // an interface struct usb_device *udev; // the parent device intf->dev.parent == &udev->dev; We reach the container of the 'struct device' through the macro container_of(). At the beginning of the probe routine we have: struct usb_interface *intf; // an interface struct usb_device *dev = interface_to_usbdev(intf); i.e. container of intf->dev.parent in FreeBSD, intf->device interface = &intf->cur_altsetting->desc; in FreeBSD, interface = intf->idesc In order to emulate these data structures, we need to provide the following data structures, appropriately linked. In our emulation layer, these are allocated as part of the softc, within the structure struct linux_usb_descriptors { ... struct file struct usb_interface for the interface in use must be persistent struct usb_device for the parent device ? must be persistent struct usb_host_interface for the (current ?altsetting) struct usb_host_endpoint[N] for the endpoints. } which is defined in ldev_stub.h (XXX should be elsewhere). -- Descriptor linkage: --- We refer here to linux videodev devices: softc...{ <-----------------------+ . vdev .--> video_device....{ | . . . priv ---------.--+ . . . fops ---------.--> file_operations { . dev -->-+ . dev -->--+ . open, close, ioctl... }........ | }...........|.... } | | +----------------+ | linux_usb_descriptors { | | | usb_interface { <--------- intf to linux probe routine | device { | parent -->--+ } | | } | | usb_device { | | device { <-----+ } } } ===================== FreeBSD Data Structures ====================== (note, device_t and device_ptr_t are actually the same thing) Most descriptors are 'struc usbd_foo' and have a matching typedef-d pointer typedef struct usbd_foo * usbd_foo_handle defined in usbdi.h sys/dev/usb/usbdivar.h: struct usbd_device { // ptd by usbd_device_handle ... struct usbd_pipe *default_pipe; // pipe 0 u_int8_t config; // current configuration # */ ... struct usbd_endpoint def_ep; /* for pipe 0 */ usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */ struct usbd_interface *ifaces; /* array of all interfaces */ usb_device_descriptor_t ddesc; /* device descriptor */ usb_config_descriptor_t *cdesc; /* full config descr */ device_ptr_t *subdevs; /* sub-devices, 0 terminated */ uint8_t *ifacenums; /* sub-device interfacenumbers */ } struct usbd_interface { struct usbd_device *device; usb_interface_descriptor_t *idesc; int index; int altindex; struct usbd_endpoint *endpoints; void *priv; LIST_HEAD(, usbd_pipe) pipes; }; struct usbd_pipe { struct usbd_interface *iface; struct usbd_device *device; struct usbd_endpoint *endpoint; int refcnt; char running; char aborting; SIMPLEQ_HEAD(, usbd_xfer) queue; LIST_ENTRY(usbd_pipe) next; usbd_xfer_handle intrxfer; /* used for repeating requests */ char repeat; int interval; /* Filled by HC driver. */ struct usbd_pipe_methods *methods; }; sys/dev/usb/usbdi.h: /* Attach data */ struct usb_attach_arg { int port; int configno; int ifaceno; int vendor; int product; int release; int matchlvl; usbd_device_handle device; /* current device */ usbd_interface_handle iface; /* current interface */ int usegeneric; usbd_interface_handle *ifaces; /* all interfaces */ int nifaces; /* number of interfaces */ }; The match/attach routines are passed a device_t dev argument, which can access the softc and attach arg with struct ldev_softc *sc = device_get_softc(dev); struct usb_attach_arg *uaa = device_get_ivars(dev); and from the latter you can get the interface, the parent device and so on. It is probably a good idea to store the device/interface in the softc during the attach process: sc->udev = uaa->device; sc->sc_iface = uaa->iface; sc->sc_dev = dev; In the other routines, you get struct cdev *dev [the naming is confusing] as first argument; from here you can do int unit = LDEVUNIT(dev); struct ldev_softc *sc = devclass_get_softc(ldev_devclass, unit); and from the softc you can access the linux emulation fields. #endif /* COMMENTS */ #define interface_to_usbdev(intf) \ container_of(intf->dev.parent, struct usb_device, dev) /* in mod_devicetable.h */ /** * Device table entry for "new style" table-driven USB drivers. * User mode code can read these tables to choose which modules to load. * Declare the table as a MODULE_DEVICE_TABLE. * * A probe() parameter will point to a matching entry from this table. * Use the driver_info field for each match to hold information tied * to that match: device quirks, etc. * * Terminate the driver's table with an all-zeroes entry. * Use the flag values to control which fields are compared. */ /** * struct usb_device_id - identifies USB devices for probing and hotplugging * @match_flags: Bit mask controlling of the other fields are used to match * against new devices. Any field except for driver_info may be used, * although some only make sense in conjunction with other fields. * This is usually set by a USB_DEVICE_*() macro, which sets all * other fields in this structure except for driver_info. * @idVendor: USB vendor ID for a device; numbers are assigned * by the USB forum to its members. * @idProduct: Vendor-assigned product ID. * @bcdDevice_lo: Low end of range of vendor-assigned product version numbers. * This is also used to identify individual product versions, for * a range consisting of a single device. * @bcdDevice_hi: High end of version number range. The range of product * versions is inclusive. * @bDeviceClass: Class of device; numbers are assigned * by the USB forum. Products may choose to implement classes, * or be vendor-specific. Device classes specify behavior of all * the interfaces on a devices. * @bDeviceSubClass: Subclass of device; associated with bDeviceClass. * @bDeviceProtocol: Protocol of device; associated with bDeviceClass. * @bInterfaceClass: Class of interface; numbers are assigned * by the USB forum. Products may choose to implement classes, * or be vendor-specific. Interface classes specify behavior only * of a given interface; other interfaces may support other classes. * @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass. * @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass. * @driver_info: Holds information used by the driver. Usually it holds * a pointer to a descriptor understood by the driver, or perhaps * device flags. * * In most cases, drivers will create a table of device IDs by using * USB_DEVICE(), or similar macros designed for that purpose. * They will then export it to userspace using MODULE_DEVICE_TABLE(), * and provide it to the USB core through their usb_driver structure. * * See the usb_match_id() function for information about how matches are * performed. Briefly, you will normally use one of several macros to help * construct these entries. Each entry you provide will either identify * one or more specific products, or will identify a class of products * which have agreed to behave the same. You should put the more specific * matches towards the beginning of your table, so that driver_info can * record quirks of specific products. */ struct usb_device_id { /* which fields to match against? */ __u16 match_flags; /* Used for product specific matches; range is inclusive */ __u16 idVendor; __u16 idProduct; __u16 bcdDevice_lo; __u16 bcdDevice_hi; /* Used for device class matches */ __u8 bDeviceClass; __u8 bDeviceSubClass; __u8 bDeviceProtocol; /* Used for interface class matches */ __u8 bInterfaceClass; __u8 bInterfaceSubClass; __u8 bInterfaceProtocol; /* not matched against */ kernel_ulong_t driver_info; }; #define USB_DEVICE_ID_MATCH_VENDOR 0x0001 #define USB_DEVICE_ID_MATCH_PRODUCT 0x0002 #define USB_DEVICE_ID_MATCH_DEV_LO 0x0004 #define USB_DEVICE_ID_MATCH_DEV_HI 0x0008 #define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010 #define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020 #define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040 #define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080 #define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 #define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 #define USB_DEVICE_ID_MATCH_DEVICE \ (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT) #define USB_DEVICE_ID_MATCH_INT_INFO \ (USB_DEVICE_ID_MATCH_INT_CLASS | \ USB_DEVICE_ID_MATCH_INT_SUBCLASS | \ USB_DEVICE_ID_MATCH_INT_PROTOCOL) #define USB_DEVICE(vend,prod) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), \ .idProduct = (prod) /** * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces * @cl: bInterfaceClass value * @sc: bInterfaceSubClass value * @pr: bInterfaceProtocol value * * This macro is used to create a struct usb_device_id that matches a * specific class of interfaces. */ #define USB_INTERFACE_INFO(cl,sc,pr) \ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \ .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr) #if 0 struct device_driver { // dummy, to be completed }; struct usb_dynids { spinlock_t lock; struct list_head list; }; #endif struct usb_driver { const char *name; int (*probe) (struct usb_interface *intf, const struct usb_device_id *id); void (*disconnect) (struct usb_interface *intf); #if 0 /* not currently used */ int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf); int (*suspend) (struct usb_interface *intf, pm_message_t message); int (*resume) (struct usb_interface *intf); #endif /* not currently used */ const struct usb_device_id *id_table; #if 0 /* not currently used */ struct usb_dynids dynids; struct device_driver driver; unsigned int no_dynamic_id:1; #endif /* not currently used */ }; /* * When a device registers (usually from the .init function, * which in our emulation is called from modinit_handler()), * we store the driver info in the structure containing the * other device information. * On deregister, we don't do anything - in principle we could * check that the device is registered and remove the entry. */ static inline int usb_register(struct usb_driver *driver) { if (MODINFO_NAME(info).usb_driver_desc != NULL) return -EINVAL; /* already registered */ MODINFO_NAME(info).usb_driver_desc = driver; return 0; } void usb_deregister(struct usb_driver *); /* * All standard descriptor start with bLength and bDescriptorType * followed by descriptor-specific stuff. For feature 'foo': * * on linux there is a struct usb_foo_descriptor, and a macro * USB_DT_FOO_SIZE indicating the size. * * on FreeBSD there is a typedef usb_foo_descriptor_t, and a macro * USB_FOO_DESCRIPTOR_SIZE indicating the size. * * The structure is the same, so we can cast or copy between them. * Beware though that on FreeBSD __le16 becomes uWord, which is * an array of bytes (little endian) that needs to be read with * UGETW and writtend with USETW. * * Linux FreeBSD * device device * config config * string string [127max ] * interface interface * endpoint endpoint * qualifier device_qualifier (non-std name) * otg otg * interface_assoc * security * key * encryption * bos * cap * wireless_cap * wireless_ep */ /* * Descriptor types ... USB 2.0 spec table 9.5 */ #define USB_DT_DEVICE 0x01 #define USB_DT_CONFIG 0x02 #define USB_DT_STRING 0x03 #define USB_DT_INTERFACE 0x04 #define USB_DT_ENDPOINT 0x05 #define USB_DT_DEVICE_QUALIFIER 0x06 #define USB_DT_OTHER_SPEED_CONFIG 0x07 #define USB_DT_INTERFACE_POWER 0x08 /* these are from a minor usb 2.0 revision (ECN) */ #define USB_DT_OTG 0x09 #define USB_DT_DEBUG 0x0a #define USB_DT_INTERFACE_ASSOCIATION 0x0b /* these are from the Wireless USB spec */ #define USB_DT_SECURITY 0x0c #define USB_DT_KEY 0x0d #define USB_DT_ENCRYPTION_TYPE 0x0e #define USB_DT_BOS 0x0f #define USB_DT_DEVICE_CAPABILITY 0x10 #define USB_DT_WIRELESS_ENDPOINT_COMP 0x11 #define USB_DT_WIRE_ADAPTER 0x21 #define USB_DT_RPIPE 0x22 /* conventional codes for class-specific descriptors */ #define USB_DT_CS_DEVICE 0x21 #define USB_DT_CS_CONFIG 0x22 #define USB_DT_CS_STRING 0x23 #define USB_DT_CS_INTERFACE 0x24 #define USB_DT_CS_ENDPOINT 0x25 struct usb_device_descriptor { __u8 bLength; __u8 bDescriptorType; __le16 bcdUSB; __u8 bDeviceClass; __u8 bDeviceSubClass; __u8 bDeviceProtocol; __u8 bMaxPacketSize0; __le16 idVendor; __le16 idProduct; __le16 bcdDevice; __u8 iManufacturer; __u8 iProduct; __u8 iSerialNumber; __u8 bNumConfigurations; } __attribute__ ((packed)); #define USB_DT_DEVICE_SIZE 18 /* * Device and/or Interface Class codes * as found in bDeviceClass or bInterfaceClass * and defined by www.usb.org documents */ #define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ #define USB_CLASS_AUDIO 1 #define USB_CLASS_COMM 2 #define USB_CLASS_HID 3 #define USB_CLASS_PHYSICAL 5 #define USB_CLASS_STILL_IMAGE 6 #define USB_CLASS_PRINTER 7 #define USB_CLASS_MASS_STORAGE 8 #define USB_CLASS_HUB 9 #define USB_CLASS_CDC_DATA 0x0a #define USB_CLASS_CSCID 0x0b /* chip+ smart card */ #define USB_CLASS_CONTENT_SEC 0x0d /* content security */ #define USB_CLASS_VIDEO 0x0e #define USB_CLASS_WIRELESS_CONTROLLER 0xe0 #define USB_CLASS_APP_SPEC 0xfe #define USB_CLASS_VENDOR_SPEC 0xff /* USB_DT_CONFIG: Configuration descriptor information. * * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the * descriptor type is different. Highspeed-capable devices can look * different depending on what speed they're currently running. Only * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG * descriptors. */ struct usb_config_descriptor { __u8 bLength; __u8 bDescriptorType; __le16 wTotalLength; __u8 bNumInterfaces; __u8 bConfigurationValue; __u8 iConfiguration; __u8 bmAttributes; __u8 bMaxPower; } __attribute__ ((packed)); #define USB_DT_CONFIG_SIZE 9 /* USB_DT_STRING: String descriptor */ struct usb_string_descriptor { __u8 bLength; __u8 bDescriptorType; __le16 wData[1]; /* UTF-16LE encoded */ } __attribute__ ((packed)); /* note that "string" zero is special, it holds language codes that * the device supports, not Unicode characters. */ /* USB_DT_INTERFACE: Interface descriptor */ struct usb_interface_descriptor { __u8 bLength; __u8 bDescriptorType; __u8 bInterfaceNumber; __u8 bAlternateSetting; __u8 bNumEndpoints; __u8 bInterfaceClass; __u8 bInterfaceSubClass; __u8 bInterfaceProtocol; __u8 iInterface; } __attribute__ ((packed)); #define USB_DT_INTERFACE_SIZE 9 /* USB_DT_ENDPOINT: Endpoint descriptor */ struct usb_endpoint_descriptor { __u8 bLength; __u8 bDescriptorType; __u8 bEndpointAddress; __u8 bmAttributes; __le16 wMaxPacketSize; /* uWord on FreeBSD */ __u8 bInterval; /* NOTE: these two are _only_ in audio endpoints. */ /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */ __u8 bRefresh; __u8 bSynchAddress; } __attribute__ ((packed)); /* size in bytes of the above structure, without or with audio extension */ #define USB_DT_ENDPOINT_SIZE 7 #define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd); int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd); int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd); /* * Endpoints */ #define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ #define USB_ENDPOINT_DIR_MASK 0x80 #define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ #define USB_ENDPOINT_XFER_CONTROL 0 #define USB_ENDPOINT_XFER_ISOC 1 #define USB_ENDPOINT_XFER_BULK 2 #define USB_ENDPOINT_XFER_INT 3 #define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 struct usb_host_interface { struct usb_interface_descriptor desc; /* array of desc.bNumEndpoint endpoints associated with this * interface setting. these will be in no particular order. */ struct usb_host_endpoint *endpoint; #if 0 char *string; /* iInterface string, if present */ #endif /* XXX need to fill them for uvc */ unsigned char *extra; /* Extra descriptors */ int extralen; }; int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout); /* CONTROL REQUEST SUPPORT */ /* * USB directions * * This bit flag is used in endpoint descriptors' bEndpointAddress field. * It's also one of three fields in control requests bRequestType: * dtt...rr * on the right we indicate the equivalent FreeBSD macro */ #define USB_DIR_OUT 0 /* to device, UT_WRITE */ #define USB_DIR_IN 0x80 /* to host, UT_READ */ /* * USB types, the second of three bRequestType fields */ #define USB_TYPE_MASK (0x03 << 5) // 0x60 #define USB_TYPE_STANDARD (0x00 << 5) // 0x00, UT_STANDARD #define USB_TYPE_CLASS (0x01 << 5) // 0x20, UT_CLASS #define USB_TYPE_VENDOR (0x02 << 5) // 0x40, UT_VENDOR #define USB_TYPE_RESERVED (0x03 << 5) // 0x60 /* * USB recipients, the third of three bRequestType fields */ #define USB_RECIP_MASK 0x1f #define USB_RECIP_DEVICE 0x00 // UT_DEVICE #define USB_RECIP_INTERFACE 0x01 // UT_INTERFACE #define USB_RECIP_ENDPOINT 0x02 // UT_ENDPOINT #define USB_RECIP_OTHER 0x03 // UT_OTHER /* * On FreeBSD there are also macros that combine the * three fields above e.g UT_READ_CLASS_DEVICE... */ /* * Standard requests, for the bRequest field of a SETUP packet. * * These are qualified by the bRequestType field, so that for example * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved * by a GET_STATUS request. * On FreeBSD, these macro replace USB_REQ_ with UR_ */ #define USB_REQ_GET_STATUS 0x00 // UR_GET_STATUS #define USB_REQ_CLEAR_FEATURE 0x01 // ... #define USB_REQ_SET_FEATURE 0x03 #define USB_REQ_SET_ADDRESS 0x05 #define USB_REQ_GET_DESCRIPTOR 0x06 /* * On FreeBSD there is a set of UDESC_* macros that indicate * descriptor types in the GET/SET_DESCRIPTOR commands. */ #define USB_REQ_SET_DESCRIPTOR 0x07 #define USB_REQ_GET_CONFIGURATION 0x08 #define USB_REQ_SET_CONFIGURATION 0x09 #define USB_REQ_GET_INTERFACE 0x0A #define USB_REQ_SET_INTERFACE 0x0B #define USB_REQ_SYNCH_FRAME 0x0C /* These are not present in the FreeBSD version */ #define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */ #define USB_REQ_GET_ENCRYPTION 0x0E #define USB_REQ_SET_HANDSHAKE 0x0F #define USB_REQ_GET_HANDSHAKE 0x10 #define USB_REQ_SET_CONNECTION 0x11 #define USB_REQ_SET_SECURITY_DATA 0x12 #define USB_REQ_GET_SECURITY_DATA 0x13 #define USB_REQ_SET_WUSB_DATA 0x14 #define USB_REQ_LOOPBACK_DATA_WRITE 0x15 #define USB_REQ_LOOPBACK_DATA_READ 0x16 #define USB_REQ_SET_INTERFACE_DS 0x17 /* * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and * are read as a bit array returned by USB_REQ_GET_STATUS. (So there * are at most sixteen features of each type.) * On FreeBSD, */ #define USB_DEVICE_SELF_POWERED 0 /* (read only) */ #define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ #define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ #define USB_DEVICE_BATTERY 2 /* (wireless) */ #define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ #define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ #define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ #define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ #define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ // for more see http://www.gelato.unsw.edu.au/lxr/source/include/linux/usb_ch9.h#L35 enum usb_device_speed { USB_SPEED_UNKNOWN = 0, /* enumerating */ #if 0 /* these are already #defined on FreeBSD in sys/dev/usb/usb.h */ USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ USB_SPEED_HIGH, /* usb 2.0 */ #endif USB_SPEED_VARIABLE = 4, /* wireless (usb 2.5) */ }; enum usb_device_state { /* NOTATTACHED isn't in the USB spec, and this state acts * the same as ATTACHED ... but it's clearer this way. */ USB_STATE_NOTATTACHED = 0, /* chapter 9 and authentication (wireless) device states */ USB_STATE_ATTACHED, USB_STATE_POWERED, /* wired */ USB_STATE_UNAUTHENTICATED, /* auth */ USB_STATE_RECONNECTING, /* auth */ USB_STATE_DEFAULT, /* limited function */ USB_STATE_ADDRESS, USB_STATE_CONFIGURED, /* most functions */ USB_STATE_SUSPENDED /* NOTE: there are actually four different SUSPENDED * states, returning to POWERED, DEFAULT, ADDRESS, or * CONFIGURED respectively when SOF tokens flow again. */ }; #define __create_pipe(dev, endpoint) (endpoint) #define PIPE_ISOCHRONOUS 0 #define PIPE_INTERRUPT 1 #define PIPE_CONTROL 2 #define PIPE_BULK 3 /* * On linux, pipes have the type and direction encoded in. * On FreeBSD, they don't. */ #define usb_sndctrlpipe(dev,endpoint) \ ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint)) #define usb_rcvctrlpipe(dev,endpoint) \ ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) #define usb_sndisocpipe(dev,endpoint) \ ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint)) #define usb_rcvisocpipe(dev,endpoint) \ ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) #define usb_sndbulkpipe(dev,endpoint) \ ((PIPE_BULK << 30) | __create_pipe(dev,endpoint)) #define usb_rcvbulkpipe(dev,endpoint) \ ((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) #define usb_sndintpipe(dev,endpoint) \ ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint)) #define usb_rcvintpipe(dev,endpoint) \ ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) /* used these for multi-interface device registration */ int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv); /** * usb_interface_claimed - returns true iff an interface is claimed * @iface: the interface being checked * * Returns true (nonzero) iff the interface is claimed, else false (zero). * Callers must own the driver model's usb bus readlock. So driver * probe() entries don't need extra locking, but other call contexts * may need to explicitly claim that lock. * */ int usb_interface_claimed(struct usb_interface *iface); struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum); struct usb_host_interface *usb_altnum_to_altsetting( const struct usb_interface *intf, unsigned int altnum); struct usb_host_endpoint { struct usb_endpoint_descriptor desc; #if 0 struct list_head urb_list; void *hcpriv; struct kobject *kobj; /* For sysfs info */ unsigned char *extra; /* Extra descriptors */ int extralen; #endif }; /* This is arbitrary. * From USB 2.0 spec Table 11-13, offset 7, a hub can * have up to 255 ports. The most yet reported is 10. */ #define USB_MAXCHILDREN (16) // struct usb_tt; struct usb_bus { char *bus_name; /* stable id (PCI slot_name etc) */ }; /* * We do not support the full implementation of the linux usb device, * but only a partial one. * This one is similar to the struct usbd_device in FreeBSD * defined in usbdivar.h (pointed to by usbd_device_handle) */ struct usb_device { #if 1 /* this is our simulated implementation */ struct device dev; /* Generic device interface */ struct usb_device_descriptor descriptor;/* Descriptor */ /* 'ddesc' on FreeBSD */ int devnum; /* addr. on USB bus, XXX only on 1 debug msg */ /* uint8_t address on FreeBSD */ /* XXX to be filled */ char devpath [16]; /* Use in messages: /port/port/... */ char *product; /* iProduct string, if present */ struct usb_bus *bus; /* Bus we're part of */ enum usb_device_speed speed; /* high/full/low (or error) */ #else /* this is the linux implementation */ int devnum; /* Address on USB bus */ /* uint8_t address on FreeBSD */ char devpath [16]; /* Use in messages: /port/port/... */ /* not on FreeBSD */ enum usb_device_state state; /* configured, not attached, etc */ /* config ? on FreeBSD */ enum usb_device_speed speed; /* high/full/low (or error) */ /* speed on FreeBSD */ struct usb_tt *tt; /* low/full speed dev, highspeed hub */ int ttport; /* device port on that tt hub */ unsigned int toggle[2]; /* one bit for each endpoint * ([0] = IN, [1] = OUT) */ struct usb_device *parent; /* our hub, unless we're the root */ struct usb_bus *bus; /* Bus we're part of */ /* bus on FreeBSD */ struct usb_host_endpoint ep0; /* def_ep on FreeNSD */ struct device dev; /* Generic device interface */ struct usb_device_descriptor descriptor;/* Descriptor */ /* ddesc on FreeBSD */ struct usb_host_config *config; /* All of the configs */ struct usb_host_config *actconfig;/* the active configuration */ struct usb_host_endpoint *ep_in[16]; struct usb_host_endpoint *ep_out[16]; char **rawdescriptors; /* Raw descriptors for each config */ unsigned short bus_mA; /* Current available from the bus */ u8 portnum; /* Parent port number (origin 1) */ int have_langid; /* whether string_langid is valid */ int string_langid; /* language ID for strings */ /* static strings from the device */ char *product; /* iProduct string, if present */ char *manufacturer; /* iManufacturer string, if present */ char *serial; /* iSerialNumber string, if present */ struct list_head filelist; struct class_device *class_dev; struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ /* * Child devices - these can be either new devices * (if this is a hub device), or different instances * of this same device. * * Each instance needs its own set of data structures. */ int maxchild; /* Number of ports if hub */ struct usb_device *children[USB_MAXCHILDREN]; #endif }; /* * URB support, for asynchronous request completions */ struct urb; struct pt_regs; // XXX maybe somewhere else /* * The handler called at the end of a transfer. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) typedef void (*usb_complete_t)(struct urb *); #else typedef void (*usb_complete_t)(struct urb *, struct pt_regs *); #endif /* * urb->transfer_flags: */ #define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */ #define URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame * ignored */ #define URB_NO_TRANSFER_DMA_MAP 0x0004 /* urb->transfer_dma valid on submit */ #define URB_NO_SETUP_DMA_MAP 0x0008 /* urb->setup_dma valid on submit */ #define URB_NO_FSBR 0x0020 /* UHCI-specific */ #define URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */ #define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt * needed */ struct usb_iso_packet_descriptor { unsigned int offset; unsigned int length; /* expected length */ unsigned int actual_length; unsigned int status; }; struct urb { /* * Fields for FreeBSD emulation: * + the array of sizes is separate so we need to allocate * it explicitly (at interrupt time, this means NOWAIT). * + memory is associated to the xfer, so we _might_ need * to copy if someone scrambles us. * + there is a usbd_private_handle which is the argument to * the callback, but in fact this is the 'context' argument. * note, we don't use the 'pipe' here but rely on the usbd_pipe_handle * recorded in the struct linux_usb_descriptor. * This should be fixed linking the urb to the pipes instead. */ int n_frames; /* how many frames */ uint16_t *frlengths; /* the array of sizes */ #if 0 /* private: usb core and host controller only fields in the urb */ struct kref kref; /* reference count of the URB */ spinlock_t lock; /* lock for the URB */ void *hcpriv; /* private data for host controller */ int bandwidth; /* bandwidth for INT/ISO request */ atomic_t use_count; /* concurrent submissions counter */ u8 reject; /* submissions will fail */ /* public: documented fields in the urb that can be used by drivers */ struct list_head urb_list; /* list head for use by the urb's * current owner */ #endif struct usb_device *dev; /* (in) pointer to associated device */ unsigned int pipe; /* (in) pipe information */ int status; /* (return) non-ISO status */ unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ char *transfer_buffer; /* (in) associated data buffer */ dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ int transfer_buffer_length; /* (in) data buffer length */ /* XXX must set this */ int actual_length; /* (return) actual transfer length */ #if 0 unsigned char *setup_packet; /* (in) setup packet (control only) */ dma_addr_t setup_dma; /* (in) dma addr for setup_packet */ #endif int start_frame; /* (modify) start frame (ISO) XX unused*/ int number_of_packets; /* (in) number of ISO packets */ int interval; /* (modify) transfer interval * (INT/ISO) */ #if 0 int error_count; /* (return) number of ISO errors */ #endif void *context; /* (in) context for completion */ usb_complete_t complete; /* (in) completion routine */ struct usb_iso_packet_descriptor iso_frame_desc[0]; /* (in) ISO ONLY */ }; /** * usb_fill_bulk_urb - macro to help initialize a bulk urb * @urb: pointer to the urb to initialize. * @dev: pointer to the struct usb_device for this urb. * @pipe: the endpoint pipe * @transfer_buffer: pointer to the transfer buffer * @buffer_length: length of the transfer buffer * @complete_fn: pointer to the usb_complete_t function * @context: what to set the urb context to. * * Initializes a bulk urb with the proper information needed to submit it * to a device. */ static inline void usb_fill_bulk_urb (struct urb *urb, struct usb_device *dev, unsigned int pipe, void *transfer_buffer, int buffer_length, usb_complete_t complete_fn, void *context) { // spin_lock_init(&urb->lock); urb->dev = dev; urb->pipe = pipe; urb->transfer_buffer = transfer_buffer; urb->transfer_buffer_length = buffer_length; urb->complete = complete_fn; urb->context = context; } /** * usb_fill_int_urb - macro to help initialize a interrupt urb * @urb: pointer to the urb to initialize. * @dev: pointer to the struct usb_device for this urb. * @pipe: the endpoint pipe * @transfer_buffer: pointer to the transfer buffer * @buffer_length: length of the transfer buffer * @complete_fn: pointer to the usb_complete_t function * @context: what to set the urb context to. * @interval: what to set the urb interval to, encoded like * the endpoint descriptor's bInterval value. * * Initializes a interrupt urb with the proper information needed to submit * it to a device. * Note that high speed interrupt endpoints use a logarithmic encoding of * the endpoint interval, and express polling intervals in microframes * (eight per millisecond) rather than in frames (one per millisecond). */ static inline void usb_fill_int_urb (struct urb *urb, struct usb_device *dev, unsigned int pipe, void *transfer_buffer, int buffer_length, usb_complete_t complete_fn, void *context, int interval) { // spin_lock_init(&urb->lock); urb->dev = dev; urb->pipe = pipe; urb->transfer_buffer = transfer_buffer; urb->transfer_buffer_length = buffer_length; urb->complete = complete_fn; urb->context = context; if (dev->speed == USB_SPEED_HIGH) urb->interval = 1 << (interval - 1); else urb->interval = interval; urb->start_frame = -1; } /* * Descriptor for the current status of an interface. * On FreeBSD, probably a partially matching structure is * struct usbd_interface */ struct usb_interface { /* array of alternate settings for this interface, * stored in no particular order */ struct usb_host_interface *altsetting; struct usb_host_interface *cur_altsetting; /* the currently * active alternate setting */ unsigned num_altsetting; /* number of alternate settings */ #if 0 int minor; /* minor number this interface is * bound to */ enum usb_interface_condition condition; /* state of binding */ #endif struct device dev; /* interface specific device info */ struct class_device *class_dev; }; struct usb_device *usb_get_dev(struct usb_device *dev); void usb_put_dev(struct usb_device *dev); int usb_clear_halt(struct usb_device *dev, int pipe); int usb_set_interface(struct usb_device *dev, int ifnum, int alternate); void *usb_buffer_alloc (struct usb_device *dev, size_t size, gfp_t mem_flags, dma_addr_t *dma); void usb_buffer_free (struct usb_device *dev, size_t size, void *addr, dma_addr_t dma); /// maybe init_urb is exposed // void usb_init_urb(struct urb *urb); struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags); void usb_free_urb(struct urb *urb); int usb_submit_urb(struct urb *urb, gfp_t mem_flags); int usb_unlink_urb(struct urb *urb); void usb_kill_urb(struct urb *urb); static inline void *usb_get_intfdata (struct usb_interface *intf) { return dev_get_drvdata (&intf->dev); } static inline void usb_set_intfdata (struct usb_interface *intf, void *data) { dev_set_drvdata(&intf->dev, data); } struct usb_interface *usb_get_intf(struct usb_interface *intf); void usb_put_intf(struct usb_interface *intf); int usb_string(struct usb_device *dev, int index, char *buf, size_t size); /* devfs support... */ /** * usb_make_path - returns stable device path in the usb tree * @dev: the device whose path is being constructed * @buf: where to put the string * @size: how big is "buf"? */ int usb_make_path (struct usb_device *dev, char *buf, size_t size); #endif /* _LINUX_USB_H */ linux_compat/linux/version.h000644 000423 000000 00000000507 10557776024 017032 0ustar00luigiwheel000000 000000 /* * compat file for linux/version.h */ #ifndef _LINUX_VERSION_H #define _LINUX_VERSION_H #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) /* emulate a modern version */ // #define LINUX_VERSION_CODE KERNEL_VERSION(2, 6, 16) #define LINUX_VERSION_CODE KERNEL_VERSION(2, 6, 19) #endif /* _LINUX_MODULE_H */ linux_compat/linux/videodev.h000644 000423 000000 00000044170 10562676625 017160 0ustar00luigiwheel000000 000000 /* * This is a reimplementation of the videodev.h file containing * the Video for Linux (1) API specification. * The API is documented at http://linux.bytesex.org/v4l2/API.html * as part of the v4l2 description, and we try to follow that * one here. * See also http://v4l2spec.bytesex.org/spec/c12160.htm * * Part of the information contained here (especially, the numeric * values of the constants) also comes from the * videodev.h file * in the linux distribution, whose origin seems to be uncertain. * * Please realise that this is an API so there are very few degrees * of freedom in writing this header. * Names (constants, types and field names, API functions) must * necessarily be the same or very similar, what does change to some * limited degree is the set of headers that this file may depend * on, or the internal structure of the file. Hence, it makes little * if any sense to claim for copyrights on these elements. * * On the other hand, the documentation of this file is completely * new and compiled from external sources. */ #ifndef __LINUX_VIDEODEV_H /* protect against nested include */ #define __LINUX_VIDEODEV_H #include /* make sure we have the basic types */ /* * On FreeBSD we don't have many of the linux types available, * and depending on where this file is included, we may need to * redefine them here. * XXX todo: check if we can replace with some linux header. */ #if 0 // ndef _LINUX_TYPES_H #define _LINUX_TYPES_H typedef int32_t __s32; typedef int64_t __s64; typedef uint16_t __u16; typedef uint32_t __u32; typedef uint64_t __u64; typedef uint8_t __u8; #endif /* _LINUX_TYPES_H */ /* * Bring in the common definition for v4l1 and v4l2. */ #include #if 1 // defined(CONFIG_VIDEO_V4L1_COMPAT) || !defined (__KERNEL__) /* * Here we have a number of descriptors used to interact with * the driver. Most of them are arguments for ioctl() calls, * so we include them next to the definition of the structure. * * The basic way of interacting with a device is open() it and * issue a VIDIOCGCAP ioctl to figure out the capabilities * of the device. At this point we have the following tasks: * - set the video format and controls, VIDIOCSPICT * - set the capture size, VIDIOCSWIN and possibly also * VIDIOCSCAPTURE and (if capturing to screen) VIDIOCSFBUF * - if needed, set the tuner (VIDIOCSCHAN and more) * - if using the read() interface, just call it to grab data; * - if using the mmap interface, issue VIDIOCGMBUF to know * how memory is organized; then call mmap() as needed, * then issue VIDIOCMCAPTURE(0..n-1) for each of the * frames that you want, and possibly use VIDIOCSYNC(i) * to wait until frame i has been captured. * While capture is active you can use further ioctls to change * the video/audio controls including tuner and so on. */ /* * Description of a video device, as set by the driver. * * Name is a device-specific string eg. camera or card name; * Type is a bitfield with the set of capabilities (VID_TYPE_* * constants, defined in videodev2.h) supported by the device. * V4L1 has a small set e.g. CAPTURE, TUNER, TELETEXT, CLIPPING... * Channels is the number of radio/tv channels available. * Audios is the number of audio devices. * The last four fields are the range of supported image sizes. * Note that in many cases only a discrete set of sizes within the * range is available. Some drivers may do the conversion (e.g. * cropping or padding) on their own. * * There is only one related ioctl(), to fetch the capabilities * of the device. */ struct video_capability { char name[32]; int type; /* capabilities, see videodev2.h */ int channels; int audios; int maxwidth; int maxheight; int minwidth; int minheight; }; #define VIDIOCGCAP _IOR('v', 1, struct video_capability) /* * OVERLAY CAPTURE SUPPORT * * Some cards can write directly into the frame buffer, in which case * we use the VIDIOCSFBUF to tell the driver the base address, size, * depth and bytes per line for the buffer. */ struct video_buffer { void *base; /* use NULL to indicate unset */ int height; int width; int depth; /* XXX per pixel ? */ int bytesperline; /* offset between start of two lines */ }; #define VIDIOCGFBUF _IOR('v',11, struct video_buffer) #define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* * CAPTURE AREA DESCRIPTION * * struct video_window describes the capture area, plus optional * clipping information if relevant (e.g. VID_TYPE_CLIPPING is * set in the capabilities and we want it.). * A windows is specified as position and size, clipping rectangles * must be specified as a list of 'struct video_clip' and their * count in clipcount. 'clips' is not used in the VIDIOCGWIN call. * A -1 in clipcount means that clips is a * poonter to a 1024x625 bitmap, where a '1' represent a clipped pixel. * Flags supports interlace and chromakey. * * NOTE: setting the window does not start/stop capture, you need * do a VIDIOCCAPTURE with an argument of 1 (start) or 0 (stop). */ struct video_clip { __s32 x; __s32 y; __s32 width; __s32 height; struct video_clip *next; }; struct video_window { __u32 x; __u32 y; __u32 width; __u32 height; __u32 chromakey; /* host order, RGB32 chromakey */ __u32 flags; /* more capture flags */ #define VIDEO_WINDOW_INTERLACE 1 #define VIDEO_WINDOW_CHROMAKEY 0x10 /* Overlay by chromakey */ struct video_clip *clips; /* set only, see note above */ int clipcount; #define VIDEO_CLIP_BITMAP -1 /* see note above */ #define VIDEO_CLIPMAP_SIZE (128 * 625) }; #define VIDIOCCAPTURE _IOW('v', 8, int) /* Start/end capture */ /* Get/set the video overlay window with clip list. */ #define VIDIOCGWIN _IOR('v', 9, struct video_window) #define VIDIOCSWIN _IOW('v',10, struct video_window) /* * Some devices can capture a subfield of the image, in which case * we can specify here its position and size, possibly a decimation * factor, and whether we want even or odd frames. * XXX how can we ask for both ? */ struct video_capture { __u32 x; __u32 y; __u32 width; __u32 height; __u16 decimation; /* Decimation divider */ __u16 flags; /* odd/even */ #define VIDEO_CAPTURE_ODD 0 #define VIDEO_CAPTURE_EVEN 1 }; #define VIDIOCGCAPTURE _IOR('v', 22, struct video_capture) #define VIDIOCSCAPTURE _IOW('v', 23, struct video_capture) /* * Video sources definition. * * Each device has one or more channels, described * by the following structures * Each video channel has a numeric identifier, a name, * possibly a tuner associated, a type, and a 'norm' field. * We can read or set the channel info with VIDIOC[GS]CHAN */ struct video_channel { int channel; char name[32]; int tuners; __u32 flags; #define VIDEO_VC_TUNER 1 /* Channel has a tuner */ #define VIDEO_VC_AUDIO 2 /* Channel has audio */ /* #define VIDEO_VC_NORM ??? mentioned but not defined */ __u16 type; #define VIDEO_TYPE_TV 1 #define VIDEO_TYPE_CAMERA 2 __u16 norm; /* Norm set by channel */ }; #define VIDIOCGCHAN _IOWR('v', 2, struct video_channel) #define VIDIOCSCHAN _IOW('v', 3, struct video_channel) /* * This is the main structure to get/set picture features, * in particular the video controls (brightness etc), * the data format (depth, palette). * All values except palette (XXX and depth ?) are scaled to * the full 16 bit range irrespective of the native range. * * We can get or set the picture info with VIDIOC[GS]PICT. * Consider that changes to the video controls are often * inexpensive operations, whereas changing to the video * format (depth, palette) might require stopping and * restarting the video device. */ struct video_picture { __u16 brightness; __u16 hue; __u16 colour; __u16 contrast; __u16 whiteness; /* Black and white only */ __u16 depth; /* Capture depth */ __u16 palette; /* Palette in use */ /* Available palettes i.e. video formats */ #define VIDEO_PALETTE_GREY 1 /* Linear greyscale */ #define VIDEO_PALETTE_HI240 2 /* BT848 high 240 color cube */ #define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */ #define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */ #define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */ #define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */ /* * These formats are 'component' type, i.e. the components for * each pixel are contiguous (technically, the ones above are * the same; perhaps component refers to the 'YUV' vs 'RGB' * format). */ #define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */ #define VIDEO_PALETTE_YUV422 7 /* 4bit Y, 2bit U, 2bit V */ #define VIDEO_PALETTE_YUYV 8 #define VIDEO_PALETTE_UYVY 9 #define VIDEO_PALETTE_YUV420 10 #define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */ #define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */ /* * These formats are 'planar' i.e. each 'plane' is stored contiguously. * This is more useful when we want to do compression. */ #define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */ #define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */ #define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */ #define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */ #define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */ }; #define VIDIOCGPICT _IOR('v', 6, struct video_picture) #define VIDIOCSPICT _IOW('v', 7, struct video_picture) /* * READING IMAGES -- read() and mmap() * * The read() system call will return the next available image. * Before this, the app should call VIDIOCSPICT and VIDIOCSWIN * to set the format and size of the input data. * * An alternative method is to use the mmap interface. * * First set the image size and depth (with XXX ?). * Then issue VIDIOCGMBUF to _ask_ the driver how much memory to mmap, * the number n of frames, and their offsets in the buffer. * VIDEO_MAX_FRAME is defined in videodev2.h. * Then you should * * Finally, issue VIDIOCMCAPTURE to tell the driver to start * capturing the specified frame (XXX redundant size info ?). * VIDIOCMCAPTURE does not wait until capture completes, * _and_ you need to issue one VIDIOCMCAPTURE for each of the * frames (0..n-1) that you want to capture. * VIDIOCSYNC(x) blocks until x frames are captured. * Note you can have many pending VIDIOCMCAPTURE calls, which * you would use if you want to do 'double buffering'. */ struct video_mbuf { int size; /* Total memory to map */ int frames; /* Frames */ int offsets[VIDEO_MAX_FRAME]; }; #define VIDIOCGMBUF _IOR('v',20, struct video_mbuf) struct video_mmap { unsigned int frame; /* Frame (0..n-1) */ int height; int width; unsigned int format; /* should be VIDEO_PALETTE_* */ }; #define VIDIOCMCAPTURE _IOW('v', 19, struct video_mmap) #define VIDIOCSYNC _IOW('v', 18, int) /* * OTHER CONTROLS: tuners, audio controls, vbi... */ /* * Same as for channels, a tuner has a numeric identifier, a name, * and a mixture of flags indicating capabilities. * Of importance are the frequency range (in 1/16 MHZ or 1/16KHz * units depending on VIDEO_TUNER_LOW status), * and the signal strenght if known (range 0..65535). * * We can read and set the info with VIDIOC[GS]TUNER, * and get and set the frequency with VIDIOC[GS]FREQ */ struct video_tuner { int tuner; char name[32]; unsigned long rangelow, rangehigh; /* Tuner range */ __u32 flags; #define VIDEO_TUNER_PAL 0x0001 #define VIDEO_TUNER_NTSC 0x0002 #define VIDEO_TUNER_SECAM 0x0004 #define VIDEO_TUNER_LOW 0x0008 /* Uses KHz not MHz */ #define VIDEO_TUNER_NORM 0x0010 /* Tuner can set norm */ #define VIDEO_TUNER_STEREO_ON 0x0080 /* Tuner is seeing stereo */ #define VIDEO_TUNER_RDS_ON 0x0100 /* Tuner is seeing RDS stream */ #define VIDEO_TUNER_MBS_ON 0x0200 /* Tuner is seeing MBS stream */ __u16 mode; /* PAL/NTSC/SECAM/OTHER */ #define VIDEO_MODE_PAL 0 #define VIDEO_MODE_NTSC 1 #define VIDEO_MODE_SECAM 2 #define VIDEO_MODE_AUTO 3 __u16 signal; }; #define VIDIOCGTUNER _IOWR('v', 4, struct video_tuner) #define VIDIOCSTUNER _IOW('v', 5, struct video_tuner) #define VIDIOCGFREQ _IOR('v', 14, unsigned long) #define VIDIOCSFREQ _IOW('v', 15, unsigned long) /* * Read/set the controls for each audio channel. * Note how the structure differs from others e.g. the * name[] field is in the middle. */ struct video_audio { int audio; /* Audio channel */ __u16 volume; /* If settable */ __u16 bass; __u16 treble; __u32 flags; /* which controls do exist */ #define VIDEO_AUDIO_MUTE 0x0001 #define VIDEO_AUDIO_MUTABLE 0x0002 #define VIDEO_AUDIO_VOLUME 0x0004 #define VIDEO_AUDIO_BASS 0x0008 #define VIDEO_AUDIO_TREBLE 0x0010 #define VIDEO_AUDIO_BALANCE 0x0020 char name[16]; __u16 mode; /* which modes are supported */ #define VIDEO_SOUND_MONO 1 #define VIDEO_SOUND_STEREO 2 #define VIDEO_SOUND_LANG1 4 #define VIDEO_SOUND_LANG2 8 __u16 balance; /* Stereo balance */ __u16 step; /* Step actual volume uses */ }; #define VIDIOCGAUDIO _IOR('v', 16, struct video_audio) #define VIDIOCSAUDIO _IOW('v', 17, struct video_audio) /* * XXX to be documented */ struct video_key { __u8 key[8]; __u32 flags; }; /* Video key event - to dev 255 is to all - * cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */ #define VIDIOCKEY _IOR('v',13, struct video_key) /* * This is mostly a linux-specific ioctl. * VIDIOCGUNIT returns the minor device numbers for all devices * associated with the current one, e.g. if a video device * also has vbi, teletext, etc. associated. * This is useful if you need to open them independently. * Probably returns VIDEO_NO_UNIT if a function is not available. * XXX On FreeBSD, it is unclear how to map these. */ struct video_unit { /* fields are all minor numbers */ int video; int vbi; int radio; int audio; int teletext; }; #define VIDEO_NO_UNIT (-1) #define VIDIOCGUNIT _IOR('v', 21, struct video_unit) /* * VBI interface */ struct vbi_format { __u32 sampling_rate; /* in Hz */ __u32 samples_per_line; __u32 sample_format; /* VIDEO_PALETTE_RAW only (1 byte) */ __s32 start[2]; /* starting line for each frame */ __u32 count[2]; /* count of lines for each frame */ __u32 flags; #define VBI_UNSYNC 1 /* can distinguish between top/bottom field */ #define VBI_INTERLACED 2 /* lines are interlaced */ }; /* get/set vbi information */ #define VIDIOCGVBIFMT _IOR('v',28, struct vbi_format) #define VIDIOCSVBIFMT _IOW('v',29, struct vbi_format) /* * video_info is biased towards hardware mpeg encode/decode * but it could apply generically to any hardware * compressor/decompressor */ struct video_info { __u32 frame_count; /* frames output since decode/encode began */ __u32 h_size; /* current unscaled horizontal size */ __u32 v_size; /* current unscaled veritcal size */ __u32 smpte_timecode; /* current SMPTE timecode (for current GOP) */ __u32 picture_type; /* current picture type */ __u32 temporal_reference; /* current temporal reference */ __u8 user_data[256]; /* user data last found in compressed stream */ /* user_data[0] contains user data flags, user_data[1] has count */ }; #define VIDIOCGPLAYINFO _IOR('v',26, struct video_info) /* Get current playback info from hardware */ /* generic structure for setting playback modes */ struct video_play_mode { int mode; int p1; int p2; }; #define VIDIOCSPLAYMODE _IOW('v',24, struct video_play_mode) /* Set output video mode/feature */ /* for loading microcode / fpga programming */ struct video_code { char loadwhat[16]; /* name or tag of file being passed */ int datasize; __u8 *data; }; #define VIDIOCSMICROCODE _IOW('v',27, struct video_code) /* Load microcode into hardware */ /* * The remaining ioctl supported by the video4linux v1 interface: * VIDIOCSWRITEMODE passes one of the VID_WRITE_ parameters * (unknown meaning). */ #define VIDIOCSWRITEMODE _IOW('v', 25, int) /* Set write mode */ /* VIDIOCSWRITEMODE */ #define VID_WRITE_MPEG_AUD 0 #define VID_WRITE_MPEG_VID 1 #define VID_WRITE_OSD 2 #define VID_WRITE_TTX 3 #define VID_WRITE_CC 4 #define VID_WRITE_MJPEG 5 #define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */ /* * mode values for VIDIOCSPLAYMODE */ #define VID_PLAY_VID_OUT_MODE 0 /* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */ #define VID_PLAY_GENLOCK 1 /* p1: 0 = OFF, 1 = ON */ /* p2: GENLOCK FINE DELAY value */ #define VID_PLAY_NORMAL 2 #define VID_PLAY_PAUSE 3 #define VID_PLAY_SINGLE_FRAME 4 #define VID_PLAY_FAST_FORWARD 5 #define VID_PLAY_SLOW_MOTION 6 #define VID_PLAY_IMMEDIATE_NORMAL 7 #define VID_PLAY_SWITCH_CHANNELS 8 #define VID_PLAY_FREEZE_FRAME 9 #define VID_PLAY_STILL_MODE 10 #define VID_PLAY_MASTER_MODE 11 /* p1: see below */ #define VID_PLAY_MASTER_NONE 1 #define VID_PLAY_MASTER_VIDEO 2 #define VID_PLAY_MASTER_AUDIO 3 #define VID_PLAY_ACTIVE_SCANLINES 12 /* p1 = first active; p2 = last active */ #define VID_PLAY_RESET 13 #define VID_PLAY_END_MARK 14 /* * Various hardware types. */ #define VID_HARDWARE_BT848 1 #define VID_HARDWARE_QCAM_BW 2 #define VID_HARDWARE_PMS 3 #define VID_HARDWARE_QCAM_C 4 #define VID_HARDWARE_PSEUDO 5 #define VID_HARDWARE_SAA5249 6 #define VID_HARDWARE_AZTECH 7 #define VID_HARDWARE_SF16MI 8 #define VID_HARDWARE_RTRACK 9 #define VID_HARDWARE_ZOLTRIX 10 #define VID_HARDWARE_SAA7146 11 #define VID_HARDWARE_VIDEUM 12 /* Reserved for Winnov videum */ #define VID_HARDWARE_RTRACK2 13 #define VID_HARDWARE_PERMEDIA2 14 /* Reserved for Permedia2 */ #define VID_HARDWARE_RIVA128 15 /* Reserved for RIVA 128 */ #define VID_HARDWARE_PLANB 16 /* PowerMac motherboard video-in */ #define VID_HARDWARE_BROADWAY 17 /* Broadway project */ #define VID_HARDWARE_GEMTEK 18 #define VID_HARDWARE_TYPHOON 19 #define VID_HARDWARE_VINO 20 /* SGI Indy Vino */ #define VID_HARDWARE_CADET 21 /* Cadet radio */ #define VID_HARDWARE_TRUST 22 /* Trust FM Radio */ #define VID_HARDWARE_TERRATEC 23 /* TerraTec ActiveRadio */ #define VID_HARDWARE_CPIA 24 #define VID_HARDWARE_ZR36120 25 /* Zoran ZR36120/ZR36125 */ #define VID_HARDWARE_ZR36067 26 /* Zoran ZR36067/36060 */ #define VID_HARDWARE_OV511 27 #define VID_HARDWARE_ZR356700 28 /* Zoran 36700 series */ #define VID_HARDWARE_W9966 29 #define VID_HARDWARE_SE401 30 /* SE401 USB webcams */ #define VID_HARDWARE_PWC 31 /* Philips webcams */ #define VID_HARDWARE_MEYE 32 /* Sony Vaio MotionEye cameras */ #define VID_HARDWARE_CPIA2 33 #define VID_HARDWARE_VICAM 34 #define VID_HARDWARE_SF16FMR2 35 #define VID_HARDWARE_W9968CF 36 #define VID_HARDWARE_SAA7114H 37 #define VID_HARDWARE_SN9C102 38 #define VID_HARDWARE_ARV 39 #endif /* CONFIG_VIDEO_V4L1_COMPAT */ #endif /* __LINUX_VIDEODEV_H */ linux_compat/linux/videodev2.h000644 000423 000000 00000132531 10562205707 017226 0ustar00luigiwheel000000 000000 /* * Video for Linux 2 API header. * * According to the discussion on the the video4linux-list * * https://www.redhat.com/mailman/private/video4linux-list/2007-January/msg00571.html * * this file is under a dual license - either BSD (3 clause) * or GPLv2. * * The spec for the v4l2 is at * * http://v4l2spec.bytesex.org/spec/ * * $Id: videodev2.h,v 1.6 2007/02/06 23:14:15 luigi Exp $ */ /* * Video for Linux Two * * Header file for v4l or V4L2 drivers and applications * with public API. * All kernel-specific stuff were moved to media/v4l2-dev.h, so * no #if __KERNEL tests are allowed here * * See http://linuxtv.org for more info * * Author: Bill Dirks * Justin Schoeman * et al. */ #ifndef __LINUX_VIDEODEV2_H /* protect from nested includes */ #define __LINUX_VIDEODEV2_H /* * This file has some anonymous unions that are invalid for C99, * but required by some linux apps that use this interface. * As a workaround, we put a default name of 'u' to them, * unless the caller compiles with -DANONYMOUS_UNION * and then we set to the empty string. */ #ifndef ANONYMOUS_UNION #define ANONYMOUS_UNION u #else #undef ANONYMOUS_UNION /* clear previous value */ #define ANONYMOUS_UNION /* and set to empty */ #endif #ifdef __KERNEL__ #include /* need struct timeval */ #include /* need __user */ #else #define __user #endif #include /* * Common stuff for both V4L1 and V4L2 * Moved from videodev.h */ #define VIDEO_MAX_FRAME 32 /* max mmap frames ? */ /* * type field for struct video_capability. * These are bitfields. */ #define VID_TYPE_CAPTURE 0x0001 /* Can capture */ #define VID_TYPE_TUNER 0x0002 /* Can tune */ #define VID_TYPE_TELETEXT 0x0004 /* Does teletext */ #define VID_TYPE_OVERLAY 0x0008 /* Overlay onto frame buffer */ #define VID_TYPE_CHROMAKEY 0x0010 /* Overlay by chromakey */ #define VID_TYPE_CLIPPING 0x0020 /* Can clip */ #define VID_TYPE_FRAMERAM 0x0040 /* Uses the frame buffer memory */ #define VID_TYPE_SCALES 0x0080 /* Scalable */ #define VID_TYPE_MONOCHROME 0x0100 /* Monochrome only */ #define VID_TYPE_SUBCAPTURE 0x0200 /* Can capture subareas of the image */ #define VID_TYPE_MPEG_DECODER 0x0400 /* Can decode MPEG streams */ #define VID_TYPE_MPEG_ENCODER 0x0800 /* Can encode MPEG streams */ #define VID_TYPE_MJPEG_DECODER 0x1000 /* Can decode MJPEG streams */ #define VID_TYPE_MJPEG_ENCODER 0x2000 /* Can encode MJPEG streams */ /* * M I S C E L L A N E O U S */ /* Four-character-code (FOURCC) */ #define v4l2_fourcc(a,b,c,d)\ (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) /* * E N U M S */ enum v4l2_field { V4L2_FIELD_ANY = 0, /* driver can choose from none, top, bottom, interlaced depending on whatever it thinks is approximate ... */ V4L2_FIELD_NONE = 1, /* this device has no fields ... */ V4L2_FIELD_TOP = 2, /* top field only */ V4L2_FIELD_BOTTOM = 3, /* bottom field only */ V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */ V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one buffer, top-bottom order */ V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */ V4L2_FIELD_ALTERNATE = 7, /* both fields alternating into separate buffers */ }; #define V4L2_FIELD_HAS_TOP(field) \ ((field) == V4L2_FIELD_TOP || \ (field) == V4L2_FIELD_INTERLACED || \ (field) == V4L2_FIELD_SEQ_TB || \ (field) == V4L2_FIELD_SEQ_BT) #define V4L2_FIELD_HAS_BOTTOM(field) \ ((field) == V4L2_FIELD_BOTTOM || \ (field) == V4L2_FIELD_INTERLACED || \ (field) == V4L2_FIELD_SEQ_TB || \ (field) == V4L2_FIELD_SEQ_BT) #define V4L2_FIELD_HAS_BOTH(field) \ ((field) == V4L2_FIELD_INTERLACED || \ (field) == V4L2_FIELD_SEQ_TB || \ (field) == V4L2_FIELD_SEQ_BT) enum v4l2_buf_type { V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, V4L2_BUF_TYPE_VBI_CAPTURE = 4, V4L2_BUF_TYPE_VBI_OUTPUT = 5, #if 1 /* Experimental Sliced VBI */ V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, #endif V4L2_BUF_TYPE_PRIVATE = 0x80, }; enum v4l2_ctrl_type { V4L2_CTRL_TYPE_INTEGER = 1, V4L2_CTRL_TYPE_BOOLEAN = 2, V4L2_CTRL_TYPE_MENU = 3, V4L2_CTRL_TYPE_BUTTON = 4, V4L2_CTRL_TYPE_INTEGER64 = 5, V4L2_CTRL_TYPE_CTRL_CLASS = 6, }; enum v4l2_tuner_type { V4L2_TUNER_RADIO = 1, V4L2_TUNER_ANALOG_TV = 2, V4L2_TUNER_DIGITAL_TV = 3, }; enum v4l2_memory { V4L2_MEMORY_MMAP = 1, V4L2_MEMORY_USERPTR = 2, V4L2_MEMORY_OVERLAY = 3, }; /* see also http://vektor.theorem.ca/graphics/ycbcr/ */ enum v4l2_colorspace { /* ITU-R 601 -- broadcast NTSC/PAL */ V4L2_COLORSPACE_SMPTE170M = 1, /* 1125-Line (US) HDTV */ V4L2_COLORSPACE_SMPTE240M = 2, /* HD and modern captures. */ V4L2_COLORSPACE_REC709 = 3, /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */ V4L2_COLORSPACE_BT878 = 4, /* These should be useful. Assume 601 extents. */ V4L2_COLORSPACE_470_SYSTEM_M = 5, V4L2_COLORSPACE_470_SYSTEM_BG = 6, /* I know there will be cameras that send this. So, this is * unspecified chromaticities and full 0-255 on each of the * Y'CbCr components */ V4L2_COLORSPACE_JPEG = 7, /* For RGB colourspaces, this is probably a good start. */ V4L2_COLORSPACE_SRGB = 8, }; enum v4l2_priority { V4L2_PRIORITY_UNSET = 0, /* not initialized */ V4L2_PRIORITY_BACKGROUND = 1, V4L2_PRIORITY_INTERACTIVE = 2, V4L2_PRIORITY_RECORD = 3, V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE, }; struct v4l2_rect { __s32 left; __s32 top; __s32 width; __s32 height; }; struct v4l2_fract { __u32 numerator; __u32 denominator; }; /* * D R I V E R C A P A B I L I T I E S */ struct v4l2_capability { __u8 driver[16]; /* i.e. "bttv" */ __u8 card[32]; /* i.e. "Hauppauge WinTV" */ __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ __u32 version; /* should use KERNEL_VERSION() */ __u32 capabilities; /* Device capabilities */ __u32 reserved[4]; }; /* * Values for 'capabilities' field. * If set, it means that the device can perform the specified * operation. */ #define V4L2_CAP_VIDEO_CAPTURE 0x00000001 #define V4L2_CAP_VIDEO_OUTPUT 0x00000002 #define V4L2_CAP_VIDEO_OVERLAY 0x00000004 #define V4L2_CAP_VBI_CAPTURE 0x00000010 /* raw VBI */ #define V4L2_CAP_VBI_OUTPUT 0x00000020 /* raw VBI */ #if 1 #define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* sliced VBI */ #define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* sliced VBI */ #endif #define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ #define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ #define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ #define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ #define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */ #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ #define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ /* * V I D E O I M A G E F O R M A T */ struct v4l2_pix_format { __u32 width; __u32 height; __u32 pixelformat; enum v4l2_field field; __u32 bytesperline; /* for padding, zero if unused */ __u32 sizeimage; enum v4l2_colorspace colorspace; __u32 priv; /* private data, depends on pixelformat */ }; /* Pixel format FOURCC depth Description */ #define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R','G','B','1') /* 8 RGB-3-3-2 */ #define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R','G','B','O') /* 16 RGB-5-5-5 */ #define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R','G','B','P') /* 16 RGB-5-6-5 */ #define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R','G','B','Q') /* 16 RGB-5-5-5 BE */ #define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R','G','B','R') /* 16 RGB-5-6-5 BE */ #define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B','G','R','3') /* 24 BGR-8-8-8 */ #define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R','G','B','3') /* 24 RGB-8-8-8 */ #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */ #define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */ #define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */ #define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */ #define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */ #define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y','U','Y','V') /* 16 YUV 4:2:2 */ #define V4L2_PIX_FMT_UYVY v4l2_fourcc('U','Y','V','Y') /* 16 YUV 4:2:2 */ #define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4','2','2','P') /* 16 YVU422 planar */ #define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4','1','1','P') /* 16 YVU411 planar */ #define V4L2_PIX_FMT_Y41P v4l2_fourcc('Y','4','1','P') /* 12 YUV 4:1:1 */ /* two planes -- one Y, one Cr + Cb interleaved */ #define V4L2_PIX_FMT_NV12 v4l2_fourcc('N','V','1','2') /* 12 Y/CbCr 4:2:0 */ #define V4L2_PIX_FMT_NV21 v4l2_fourcc('N','V','2','1') /* 12 Y/CrCb 4:2:0 */ /* The following formats are not defined in the V4L2 specification */ #define V4L2_PIX_FMT_YUV410 v4l2_fourcc('Y','U','V','9') /* 9 YUV 4:1:0 */ #define V4L2_PIX_FMT_YUV420 v4l2_fourcc('Y','U','1','2') /* 12 YUV 4:2:0 */ #define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */ #define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */ #define V4L2_PIX_FMT_HM12 v4l2_fourcc('H','M','1','2') /* 8 YUV 4:2:0 16x16 macroblocks */ /* see http://www.siliconimaging.com/RGB%20Bayer.htm */ #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ /* compressed formats */ #define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M','J','P','G') /* Motion-JPEG */ #define V4L2_PIX_FMT_JPEG v4l2_fourcc('J','P','E','G') /* JFIF JPEG */ #define V4L2_PIX_FMT_DV v4l2_fourcc('d','v','s','d') /* 1394 */ #define V4L2_PIX_FMT_MPEG v4l2_fourcc('M','P','E','G') /* MPEG-1/2/4 */ /* Vendor-specific formats */ #define V4L2_PIX_FMT_WNVA v4l2_fourcc('W','N','V','A') /* Winnov hw compress */ #define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S','9','1','0') /* SN9C10x compression */ #define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1') /* pwc older webcam */ #define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2') /* pwc newer webcam */ #define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */ /* * F O R M A T E N U M E R A T I O N */ struct v4l2_fmtdesc { __u32 index; /* Format number */ enum v4l2_buf_type type; /* buffer type */ __u32 flags; __u8 description[32]; /* Description string */ __u32 pixelformat; /* Format fourcc */ __u32 reserved[4]; }; #define V4L2_FMT_FLAG_COMPRESSED 0x0001 #if 1 /* Experimental Frame Size and frame rate enumeration */ /* * F R A M E S I Z E E N U M E R A T I O N */ enum v4l2_frmsizetypes { V4L2_FRMSIZE_TYPE_DISCRETE = 1, V4L2_FRMSIZE_TYPE_CONTINUOUS = 2, V4L2_FRMSIZE_TYPE_STEPWISE = 3, }; struct v4l2_frmsize_discrete { __u32 width; /* Frame width [pixel] */ __u32 height; /* Frame height [pixel] */ }; struct v4l2_frmsize_stepwise { __u32 min_width; /* Min frame width [pixel] */ __u32 max_width; /* Max frame width [pixel] */ __u32 step_width; /* Frame width step size [pixel] */ __u32 min_height; /* Min frame height [pixel] */ __u32 max_height; /* Max frame height [pixel] */ __u32 step_height; /* Frame height step size [pixel] */ }; struct v4l2_frmsizeenum { __u32 index; /* Frame size number */ __u32 pixel_format; /* Pixel format */ __u32 type; /* Frame size type the device supports. */ union { /* Frame size */ struct v4l2_frmsize_discrete discrete; struct v4l2_frmsize_stepwise stepwise; } ANONYMOUS_UNION; /* XXX this is an error for c99 but not gcc99 */ __u32 reserved[2]; /* Reserved space for future use */ }; /* * F R A M E R A T E E N U M E R A T I O N */ enum v4l2_frmivaltypes { V4L2_FRMIVAL_TYPE_DISCRETE = 1, V4L2_FRMIVAL_TYPE_CONTINUOUS = 2, V4L2_FRMIVAL_TYPE_STEPWISE = 3, }; struct v4l2_frmival_stepwise { struct v4l2_fract min; /* Minimum frame interval [s] */ struct v4l2_fract max; /* Maximum frame interval [s] */ struct v4l2_fract step; /* Frame interval step size [s] */ }; struct v4l2_frmivalenum { __u32 index; /* Frame format index */ __u32 pixel_format; /* Pixel format */ __u32 width; /* Frame width */ __u32 height; /* Frame height */ __u32 type; /* Frame interval type the device supports. */ union { /* Frame interval */ struct v4l2_fract discrete; struct v4l2_frmival_stepwise stepwise; } ANONYMOUS_UNION; /* XXX this is an error for gcc */ __u32 reserved[2]; /* Reserved space for future use */ }; #endif /* * T I M E C O D E */ struct v4l2_timecode { __u32 type; __u32 flags; __u8 frames; __u8 seconds; __u8 minutes; __u8 hours; __u8 userbits[4]; }; /* Type */ #define V4L2_TC_TYPE_24FPS 1 #define V4L2_TC_TYPE_25FPS 2 #define V4L2_TC_TYPE_30FPS 3 #define V4L2_TC_TYPE_50FPS 4 #define V4L2_TC_TYPE_60FPS 5 /* Flags */ #define V4L2_TC_FLAG_DROPFRAME 0x0001 /* "drop-frame" mode */ #define V4L2_TC_FLAG_COLORFRAME 0x0002 #define V4L2_TC_USERBITS_field 0x000C #define V4L2_TC_USERBITS_USERDEFINED 0x0000 #define V4L2_TC_USERBITS_8BITCHARS 0x0008 /* The above is based on SMPTE timecodes */ #ifdef __KERNEL__ /* * M P E G C O M P R E S S I O N P A R A M E T E R S * * ### WARNING: This experimental MPEG compression API is obsolete. * ### It is replaced by the MPEG controls API. * ### This old API will disappear in the near future! * */ enum v4l2_bitrate_mode { V4L2_BITRATE_NONE = 0, /* not specified */ V4L2_BITRATE_CBR, /* constant bitrate */ V4L2_BITRATE_VBR, /* variable bitrate */ }; struct v4l2_bitrate { /* rates are specified in kbit/sec */ enum v4l2_bitrate_mode mode; __u32 min; __u32 target; /* use this one for CBR */ __u32 max; }; enum v4l2_mpeg_streamtype { V4L2_MPEG_SS_1, /* MPEG-1 system stream */ V4L2_MPEG_PS_2, /* MPEG-2 program stream */ V4L2_MPEG_TS_2, /* MPEG-2 transport stream */ V4L2_MPEG_PS_DVD, /* MPEG-2 program stream with DVD header fixups */ }; enum v4l2_mpeg_audiotype { V4L2_MPEG_AU_2_I, /* MPEG-2 layer 1 */ V4L2_MPEG_AU_2_II, /* MPEG-2 layer 2 */ V4L2_MPEG_AU_2_III, /* MPEG-2 layer 3 */ V4L2_MPEG_AC3, /* AC3 */ V4L2_MPEG_LPCM, /* LPCM */ }; enum v4l2_mpeg_videotype { V4L2_MPEG_VI_1, /* MPEG-1 */ V4L2_MPEG_VI_2, /* MPEG-2 */ }; enum v4l2_mpeg_aspectratio { V4L2_MPEG_ASPECT_SQUARE = 1, /* square pixel */ V4L2_MPEG_ASPECT_4_3 = 2, /* 4 : 3 */ V4L2_MPEG_ASPECT_16_9 = 3, /* 16 : 9 */ V4L2_MPEG_ASPECT_1_221 = 4, /* 1 : 2,21 */ }; struct v4l2_mpeg_compression { /* general */ enum v4l2_mpeg_streamtype st_type; struct v4l2_bitrate st_bitrate; /* transport streams */ __u16 ts_pid_pmt; __u16 ts_pid_audio; __u16 ts_pid_video; __u16 ts_pid_pcr; /* program stream */ __u16 ps_size; __u16 reserved_1; /* align */ /* audio */ enum v4l2_mpeg_audiotype au_type; struct v4l2_bitrate au_bitrate; __u32 au_sample_rate; __u8 au_pesid; __u8 reserved_2[3]; /* align */ /* video */ enum v4l2_mpeg_videotype vi_type; enum v4l2_mpeg_aspectratio vi_aspect_ratio; struct v4l2_bitrate vi_bitrate; __u32 vi_frame_rate; __u16 vi_frames_per_gop; __u16 vi_bframes_count; __u8 vi_pesid; __u8 reserved_3[3]; /* align */ /* misc flags */ __u32 closed_gops:1; __u32 pulldown:1; __u32 reserved_4:30; /* align */ /* I don't expect the above being perfect yet ;) */ __u32 reserved_5[8]; }; #endif struct v4l2_jpegcompression { int quality; int APPn; /* Number of APP segment to be written, * must be 0..15 */ int APP_len; /* Length of data in JPEG APPn segment */ char APP_data[60]; /* Data in the JPEG APPn segment. */ int COM_len; /* Length of data in JPEG COM segment */ char COM_data[60]; /* Data in JPEG COM segment */ __u32 jpeg_markers; /* Which markers should go into the JPEG * output. Unless you exactly know what * you do, leave them untouched. * Inluding less markers will make the * resulting code smaller, but there will * be fewer aplications which can read it. * The presence of the APP and COM marker * is influenced by APP_len and COM_len * ONLY, not by this property! */ #define V4L2_JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ #define V4L2_JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ #define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ #define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will * allways use APP0 */ }; /* * M E M O R Y - M A P P I N G B U F F E R S */ struct v4l2_requestbuffers { __u32 count; enum v4l2_buf_type type; enum v4l2_memory memory; __u32 reserved[2]; }; struct v4l2_buffer { __u32 index; enum v4l2_buf_type type; __u32 bytesused; __u32 flags; enum v4l2_field field; struct timeval timestamp; struct v4l2_timecode timecode; __u32 sequence; /* memory location */ enum v4l2_memory memory; union { __u32 offset; unsigned long userptr; } m; __u32 length; __u32 input; __u32 reserved; }; /* Flags for 'flags' field */ #define V4L2_BUF_FLAG_MAPPED 0x0001 /* Buffer is mapped (flag) */ #define V4L2_BUF_FLAG_QUEUED 0x0002 /* Buffer is queued for processing */ #define V4L2_BUF_FLAG_DONE 0x0004 /* Buffer is ready */ #define V4L2_BUF_FLAG_KEYFRAME 0x0008 /* Image is a keyframe (I-frame) */ #define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */ #define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */ #define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */ #define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */ /* * O V E R L A Y P R E V I E W */ struct v4l2_framebuffer { __u32 capability; __u32 flags; /* FIXME: in theory we should pass something like PCI device + memory * region + offset instead of some physical address */ void* base; struct v4l2_pix_format fmt; }; /* Flags for the 'capability' field. Read only */ #define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 #define V4L2_FBUF_CAP_CHROMAKEY 0x0002 #define V4L2_FBUF_CAP_LIST_CLIPPING 0x0004 #define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008 /* Flags for the 'flags' field. */ #define V4L2_FBUF_FLAG_PRIMARY 0x0001 #define V4L2_FBUF_FLAG_OVERLAY 0x0002 #define V4L2_FBUF_FLAG_CHROMAKEY 0x0004 struct v4l2_clip { struct v4l2_rect c; struct v4l2_clip *next; }; struct v4l2_window { struct v4l2_rect w; enum v4l2_field field; __u32 chromakey; struct v4l2_clip *clips; __u32 clipcount; void *bitmap; }; /* * C A P T U R E P A R A M E T E R S */ struct v4l2_captureparm { __u32 capability; /* Supported modes */ __u32 capturemode; /* Current mode */ struct v4l2_fract timeperframe; /* Time per frame in .1us units */ __u32 extendedmode; /* Driver-specific extensions */ __u32 readbuffers; /* # of buffers for read */ __u32 reserved[4]; }; /* Flags for 'capability' and 'capturemode' fields */ #define V4L2_MODE_HIGHQUALITY 0x0001 /* High quality imaging mode */ #define V4L2_CAP_TIMEPERFRAME 0x1000 /* timeperframe field is supported */ struct v4l2_outputparm { __u32 capability; /* Supported modes */ __u32 outputmode; /* Current mode */ struct v4l2_fract timeperframe; /* Time per frame in seconds */ __u32 extendedmode; /* Driver-specific extensions */ __u32 writebuffers; /* # of buffers for write */ __u32 reserved[4]; }; /* * I N P U T I M A G E C R O P P I N G */ struct v4l2_cropcap { enum v4l2_buf_type type; struct v4l2_rect bounds; struct v4l2_rect defrect; struct v4l2_fract pixelaspect; }; struct v4l2_crop { enum v4l2_buf_type type; struct v4l2_rect c; }; /* * Analog video standards are bit arrays. * They are further grouped per coding standard, field frequency, * and so on. */ typedef __u64 v4l2_std_id; /* one bit for each */ #define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001) #define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002) #define V4L2_STD_PAL_G ((v4l2_std_id)0x00000004) #define V4L2_STD_PAL_H ((v4l2_std_id)0x00000008) #define V4L2_STD_PAL_I ((v4l2_std_id)0x00000010) #define V4L2_STD_PAL_D ((v4l2_std_id)0x00000020) #define V4L2_STD_PAL_D1 ((v4l2_std_id)0x00000040) #define V4L2_STD_PAL_K ((v4l2_std_id)0x00000080) #define V4L2_STD_PAL_M ((v4l2_std_id)0x00000100) #define V4L2_STD_PAL_N ((v4l2_std_id)0x00000200) #define V4L2_STD_PAL_Nc ((v4l2_std_id)0x00000400) #define V4L2_STD_PAL_60 ((v4l2_std_id)0x00000800) #define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) #define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) #define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) #define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000) #define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) #define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) #define V4L2_STD_SECAM_G ((v4l2_std_id)0x00040000) #define V4L2_STD_SECAM_H ((v4l2_std_id)0x00080000) #define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000) #define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000) #define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000) #define V4L2_STD_SECAM_LC ((v4l2_std_id)0x00800000) /* ATSC/HDTV */ #define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000) #define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000) /* some merged standards */ #define V4L2_STD_MN (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC) #define V4L2_STD_B (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B) #define V4L2_STD_GH (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H) #define V4L2_STD_DK (V4L2_STD_PAL_DK|V4L2_STD_SECAM_DK) /* some common needed stuff */ #define V4L2_STD_PAL_BG \ (V4L2_STD_PAL_B | V4L2_STD_PAL_B1 | V4L2_STD_PAL_G) #define V4L2_STD_PAL_DK \ (V4L2_STD_PAL_D | V4L2_STD_PAL_D1 | V4L2_STD_PAL_K) #define V4L2_STD_PAL \ (V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | \ V4L2_STD_PAL_H | V4L2_STD_PAL_I) #define V4L2_STD_NTSC \ (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR) #define V4L2_STD_SECAM_DK \ (V4L2_STD_SECAM_D | V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1) #define V4L2_STD_SECAM \ (V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H |\ V4L2_STD_SECAM_DK | V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC) #define V4L2_STD_525_60 \ (V4L2_STD_PAL_M | V4L2_STD_PAL_60 | V4L2_STD_NTSC | \ V4L2_STD_NTSC_443) #define V4L2_STD_625_50 \ (V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | \ V4L2_STD_SECAM) #define V4L2_STD_ATSC \ (V4L2_STD_ATSC_8_VSB | V4L2_STD_ATSC_16_VSB) #define V4L2_STD_UNKNOWN 0 #define V4L2_STD_ALL \ (V4L2_STD_525_60 | V4L2_STD_625_50) struct v4l2_standard { __u32 index; v4l2_std_id id; __u8 name[24]; struct v4l2_fract frameperiod; /* Frames, not fields */ __u32 framelines; __u32 reserved[4]; }; /* * Video input descriptor, gives name, type and video standard, * and links to a tuner, and a set of input audio descriptors. */ struct v4l2_input { __u32 index; /* Which input */ __u8 name[32]; /* Label */ __u32 type; /* Type of input */ __u32 audioset; /* Associated audios (bitfield) */ __u32 tuner; /* Associated tuner */ v4l2_std_id std; __u32 status; __u32 reserved[4]; }; /* Values for the 'type' field */ #define V4L2_INPUT_TYPE_TUNER 1 #define V4L2_INPUT_TYPE_CAMERA 2 /* field 'status' - general */ #define V4L2_IN_ST_NO_POWER 0x00000001 /* Attached device is off */ #define V4L2_IN_ST_NO_SIGNAL 0x00000002 #define V4L2_IN_ST_NO_COLOR 0x00000004 /* field 'status' - analog */ #define V4L2_IN_ST_NO_H_LOCK 0x00000100 /* No horizontal sync lock */ #define V4L2_IN_ST_COLOR_KILL 0x00000200 /* Color killer is active */ /* field 'status' - digital */ #define V4L2_IN_ST_NO_SYNC 0x00010000 /* No synchronization lock */ #define V4L2_IN_ST_NO_EQU 0x00020000 /* No equalizer lock */ #define V4L2_IN_ST_NO_CARRIER 0x00040000 /* Carrier recovery failed */ /* field 'status' - VCR and set-top box */ #define V4L2_IN_ST_MACROVISION 0x01000000 /* Macrovision detected */ #define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */ #define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */ /* * Video outputs, gives a type and std, and links to a modulator * (counterpart of a tuner) and a set of audio descriptors. */ struct v4l2_output { __u32 index; /* Which output */ __u8 name[32]; /* Label */ __u32 type; /* Type of output */ __u32 audioset; /* Associated audios (bitfield) */ __u32 modulator; /* Associated modulator */ v4l2_std_id std; __u32 reserved[4]; }; /* Values for the 'type' field */ #define V4L2_OUTPUT_TYPE_MODULATOR 1 #define V4L2_OUTPUT_TYPE_ANALOG 2 #define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3 /* * Controls have a unique identifier and a signed 32-bit value. */ struct v4l2_control { __u32 id; __s32 value; }; /* * Extended controls are same as above but bigger structs. */ struct v4l2_ext_control { __u32 id; __u32 reserved2[2]; union { __s32 value; __s64 value64; void *reserved; } ANONYMOUS_UNION; /* XXX anonymous in the original */ } __attribute__ ((packed)); struct v4l2_ext_controls { __u32 ctrl_class; __u32 count; __u32 error_idx; __u32 reserved[2]; struct v4l2_ext_control *controls; }; /* Values for ctrl_class field */ #define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ #define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */ #define V4L2_CTRL_ID_MASK (0x0fffffff) #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) #define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000) /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ struct v4l2_queryctrl { __u32 id; enum v4l2_ctrl_type type; __u8 name[32]; /* Whatever */ __s32 minimum; /* Note signedness */ __s32 maximum; __s32 step; __s32 default_value; __u32 flags; __u32 reserved[2]; }; /* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */ struct v4l2_querymenu { __u32 id; __u32 index; __u8 name[32]; /* Whatever */ __u32 reserved; }; /* Control flags */ #define V4L2_CTRL_FLAG_DISABLED 0x0001 #define V4L2_CTRL_FLAG_GRABBED 0x0002 #define V4L2_CTRL_FLAG_READ_ONLY 0x0004 #define V4L2_CTRL_FLAG_UPDATE 0x0008 #define V4L2_CTRL_FLAG_INACTIVE 0x0010 #define V4L2_CTRL_FLAG_SLIDER 0x0020 /* Query flag, to be ORed with the control ID */ #define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000 /* User-class control IDs defined by V4L2 */ #define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) #define V4L2_CID_USER_BASE V4L2_CID_BASE /* IDs reserved for driver specific controls */ #define V4L2_CID_PRIVATE_BASE 0x08000000 #define V4L2_CID_USER_CLASS (V4L2_CTRL_CLASS_USER | 1) #define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0) #define V4L2_CID_CONTRAST (V4L2_CID_BASE+1) #define V4L2_CID_SATURATION (V4L2_CID_BASE+2) #define V4L2_CID_HUE (V4L2_CID_BASE+3) #define V4L2_CID_AUDIO_VOLUME (V4L2_CID_BASE+5) #define V4L2_CID_AUDIO_BALANCE (V4L2_CID_BASE+6) #define V4L2_CID_AUDIO_BASS (V4L2_CID_BASE+7) #define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8) #define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9) #define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10) #define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) #define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12) #define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13) #define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14) #define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15) #define V4L2_CID_GAMMA (V4L2_CID_BASE+16) #define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* ? Not sure */ #define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17) #define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18) #define V4L2_CID_GAIN (V4L2_CID_BASE+19) #define V4L2_CID_HFLIP (V4L2_CID_BASE+20) #define V4L2_CID_VFLIP (V4L2_CID_BASE+21) #define V4L2_CID_HCENTER (V4L2_CID_BASE+22) #define V4L2_CID_VCENTER (V4L2_CID_BASE+23) #define V4L2_CID_LASTP1 (V4L2_CID_BASE+24) /* last CID + 1 */ /* MPEG-class control IDs defined by V4L2 */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) #define V4L2_CID_MPEG_CLASS (V4L2_CTRL_CLASS_MPEG | 1) /* MPEG streams */ #define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_MPEG_BASE+0) enum v4l2_mpeg_stream_type { V4L2_MPEG_STREAM_TYPE_MPEG2_PS = 0, /* MPEG-2 program stream */ V4L2_MPEG_STREAM_TYPE_MPEG2_TS = 1, /* MPEG-2 transport stream */ V4L2_MPEG_STREAM_TYPE_MPEG1_SS = 2, /* MPEG-1 system stream */ V4L2_MPEG_STREAM_TYPE_MPEG2_DVD = 3, /* MPEG-2 DVD-compatible stream */ V4L2_MPEG_STREAM_TYPE_MPEG1_VCD = 4, /* MPEG-1 VCD-compatible stream */ V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */ }; #define V4L2_CID_MPEG_STREAM_PID_PMT (V4L2_CID_MPEG_BASE+1) #define V4L2_CID_MPEG_STREAM_PID_AUDIO (V4L2_CID_MPEG_BASE+2) #define V4L2_CID_MPEG_STREAM_PID_VIDEO (V4L2_CID_MPEG_BASE+3) #define V4L2_CID_MPEG_STREAM_PID_PCR (V4L2_CID_MPEG_BASE+4) #define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO (V4L2_CID_MPEG_BASE+5) #define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO (V4L2_CID_MPEG_BASE+6) #define V4L2_CID_MPEG_STREAM_VBI_FMT (V4L2_CID_MPEG_BASE+7) enum v4l2_mpeg_stream_vbi_fmt { V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */ V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, IVTV format */ }; /* MPEG audio */ #define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ (V4L2_CID_MPEG_BASE+100) enum v4l2_mpeg_audio_sampling_freq { V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0, V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1, V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2, }; #define V4L2_CID_MPEG_AUDIO_ENCODING (V4L2_CID_MPEG_BASE+101) enum v4l2_mpeg_audio_encoding { V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, }; #define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) enum v4l2_mpeg_audio_l1_bitrate { V4L2_MPEG_AUDIO_L1_BITRATE_32K = 0, V4L2_MPEG_AUDIO_L1_BITRATE_64K = 1, V4L2_MPEG_AUDIO_L1_BITRATE_96K = 2, V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3, V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4, V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5, V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6, V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7, V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8, V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9, V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10, V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11, V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12, V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13, }; #define V4L2_CID_MPEG_AUDIO_L2_BITRATE (V4L2_CID_MPEG_BASE+103) enum v4l2_mpeg_audio_l2_bitrate { V4L2_MPEG_AUDIO_L2_BITRATE_32K = 0, V4L2_MPEG_AUDIO_L2_BITRATE_48K = 1, V4L2_MPEG_AUDIO_L2_BITRATE_56K = 2, V4L2_MPEG_AUDIO_L2_BITRATE_64K = 3, V4L2_MPEG_AUDIO_L2_BITRATE_80K = 4, V4L2_MPEG_AUDIO_L2_BITRATE_96K = 5, V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6, V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7, V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8, V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9, V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10, V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11, V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12, V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13, }; #define V4L2_CID_MPEG_AUDIO_L3_BITRATE (V4L2_CID_MPEG_BASE+104) enum v4l2_mpeg_audio_l3_bitrate { V4L2_MPEG_AUDIO_L3_BITRATE_32K = 0, V4L2_MPEG_AUDIO_L3_BITRATE_40K = 1, V4L2_MPEG_AUDIO_L3_BITRATE_48K = 2, V4L2_MPEG_AUDIO_L3_BITRATE_56K = 3, V4L2_MPEG_AUDIO_L3_BITRATE_64K = 4, V4L2_MPEG_AUDIO_L3_BITRATE_80K = 5, V4L2_MPEG_AUDIO_L3_BITRATE_96K = 6, V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7, V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8, V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9, V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10, V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11, V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12, V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13, }; #define V4L2_CID_MPEG_AUDIO_MODE (V4L2_CID_MPEG_BASE+105) enum v4l2_mpeg_audio_mode { V4L2_MPEG_AUDIO_MODE_STEREO = 0, V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1, V4L2_MPEG_AUDIO_MODE_DUAL = 2, V4L2_MPEG_AUDIO_MODE_MONO = 3, }; #define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION (V4L2_CID_MPEG_BASE+106) enum v4l2_mpeg_audio_mode_extension { V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4 = 0, V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8 = 1, V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2, V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3, }; #define V4L2_CID_MPEG_AUDIO_EMPHASIS (V4L2_CID_MPEG_BASE+107) enum v4l2_mpeg_audio_emphasis { V4L2_MPEG_AUDIO_EMPHASIS_NONE = 0, V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1, V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17 = 2, }; #define V4L2_CID_MPEG_AUDIO_CRC (V4L2_CID_MPEG_BASE+108) enum v4l2_mpeg_audio_crc { V4L2_MPEG_AUDIO_CRC_NONE = 0, V4L2_MPEG_AUDIO_CRC_CRC16 = 1, }; /* MPEG video */ #define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) enum v4l2_mpeg_video_encoding { V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, }; #define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_MPEG_BASE+201) enum v4l2_mpeg_video_aspect { V4L2_MPEG_VIDEO_ASPECT_1x1 = 0, V4L2_MPEG_VIDEO_ASPECT_4x3 = 1, V4L2_MPEG_VIDEO_ASPECT_16x9 = 2, V4L2_MPEG_VIDEO_ASPECT_221x100 = 3, }; #define V4L2_CID_MPEG_VIDEO_B_FRAMES (V4L2_CID_MPEG_BASE+202) #define V4L2_CID_MPEG_VIDEO_GOP_SIZE (V4L2_CID_MPEG_BASE+203) #define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE (V4L2_CID_MPEG_BASE+204) #define V4L2_CID_MPEG_VIDEO_PULLDOWN (V4L2_CID_MPEG_BASE+205) #define V4L2_CID_MPEG_VIDEO_BITRATE_MODE (V4L2_CID_MPEG_BASE+206) enum v4l2_mpeg_video_bitrate_mode { V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1, }; #define V4L2_CID_MPEG_VIDEO_BITRATE (V4L2_CID_MPEG_BASE+207) #define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK (V4L2_CID_MPEG_BASE+208) #define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209) /* XXX check following */ /* MPEG-class control IDs specific to the CX2584x driver as defined by V4L2 */ #define V4L2_CID_MPEG_CX2341X_BASE (V4L2_CTRL_CLASS_MPEG | 0x1000) #define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+0) enum v4l2_mpeg_cx2341x_video_spatial_filter_mode { V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0, V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO = 1, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+1) #define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+2) enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type { V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF = 0, V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT = 2, V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE = 3, V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+3) enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type { V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF = 0, V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+4) enum v4l2_mpeg_cx2341x_video_temporal_filter_mode { V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0, V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO = 1, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+5) #define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+6) enum v4l2_mpeg_cx2341x_video_median_filter_type { V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF = 0, V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR = 1, V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT = 2, V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3, V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG = 4, }; #define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+7) #define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+8) #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+9) #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+10) /* * T U N I N G */ struct v4l2_tuner { __u32 index; __u8 name[32]; enum v4l2_tuner_type type; __u32 capability; __u32 rangelow; __u32 rangehigh; __u32 rxsubchans; __u32 audmode; __s32 signal; __s32 afc; __u32 reserved[4]; }; struct v4l2_modulator { __u32 index; __u8 name[32]; __u32 capability; __u32 rangelow; __u32 rangehigh; __u32 txsubchans; __u32 reserved[4]; }; /* Flags for the 'capability' field */ #define V4L2_TUNER_CAP_LOW 0x0001 #define V4L2_TUNER_CAP_NORM 0x0002 #define V4L2_TUNER_CAP_STEREO 0x0010 #define V4L2_TUNER_CAP_LANG2 0x0020 #define V4L2_TUNER_CAP_SAP 0x0020 #define V4L2_TUNER_CAP_LANG1 0x0040 /* Flags for the 'rxsubchans' field */ #define V4L2_TUNER_SUB_MONO 0x0001 #define V4L2_TUNER_SUB_STEREO 0x0002 #define V4L2_TUNER_SUB_LANG2 0x0004 #define V4L2_TUNER_SUB_SAP 0x0004 #define V4L2_TUNER_SUB_LANG1 0x0008 /* Values for the 'audmode' field */ #define V4L2_TUNER_MODE_MONO 0x0000 #define V4L2_TUNER_MODE_STEREO 0x0001 #define V4L2_TUNER_MODE_LANG2 0x0002 #define V4L2_TUNER_MODE_SAP 0x0002 #define V4L2_TUNER_MODE_LANG1 0x0003 #define V4L2_TUNER_MODE_LANG1_LANG2 0x0004 struct v4l2_frequency { __u32 tuner; enum v4l2_tuner_type type; __u32 frequency; __u32 reserved[8]; }; /* * A U D I O */ struct v4l2_audio { __u32 index; __u8 name[32]; __u32 capability; __u32 mode; __u32 reserved[2]; }; /* Flags for the 'capability' field */ #define V4L2_AUDCAP_STEREO 0x00001 #define V4L2_AUDCAP_AVL 0x00002 /* Flags for the 'mode' field */ #define V4L2_AUDMODE_AVL 0x00001 struct v4l2_audioout { __u32 index; __u8 name[32]; __u32 capability; __u32 mode; __u32 reserved[2]; }; /* * D A T A S E R V I C E S ( V B I ) * * Data services API by Michael Schimek */ /* Raw VBI */ struct v4l2_vbi_format { __u32 sampling_rate; /* in 1 Hz */ __u32 offset; __u32 samples_per_line; __u32 sample_format; /* V4L2_PIX_FMT_* */ __s32 start[2]; __u32 count[2]; __u32 flags; /* V4L2_VBI_* */ __u32 reserved[2]; /* must be zero */ }; /* VBI flags */ #define V4L2_VBI_UNSYNC (1<< 0) #define V4L2_VBI_INTERLACED (1<< 1) #if 1 /* Sliced VBI * * This implements is a proposal V4L2 API to allow SLICED VBI * required for some hardware encoders. It should change without * notice in the definitive implementation. */ struct v4l2_sliced_vbi_format { __u16 service_set; /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field (equals frame lines 313-336 for 625 line video standards, 263-286 for 525 line standards) */ __u16 service_lines[2][24]; __u32 io_size; __u32 reserved[2]; /* must be zero */ }; /* Teletext World System Teletext (WST), defined on ITU-R BT.653-2 */ #define V4L2_SLICED_TELETEXT_B (0x0001) /* Video Program System, defined on ETS 300 231*/ #define V4L2_SLICED_VPS (0x0400) /* Closed Caption, defined on EIA-608 */ #define V4L2_SLICED_CAPTION_525 (0x1000) /* Wide Screen System, defined on ITU-R BT1119.1 */ #define V4L2_SLICED_WSS_625 (0x4000) #define V4L2_SLICED_VBI_525 (V4L2_SLICED_CAPTION_525) #define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625) struct v4l2_sliced_vbi_cap { __u16 service_set; /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field (equals frame lines 313-336 for 625 line video standards, 263-286 for 525 line standards) */ __u16 service_lines[2][24]; enum v4l2_buf_type type; __u32 reserved[3]; /* must be 0 */ }; struct v4l2_sliced_vbi_data { __u32 id; __u32 field; /* 0: first field, 1: second field */ __u32 line; /* 1-23 */ __u32 reserved; /* must be 0 */ __u8 data[48]; }; #endif /* * A G G R E G A T E S T R U C T U R E S */ /* Stream data format */ struct v4l2_format { enum v4l2_buf_type type; union { struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE #if 1 struct v4l2_sliced_vbi_format sliced; // V4L2_BUF_TYPE_SLICED_VBI_CAPTURE #endif __u8 raw_data[200]; // user-defined } fmt; }; /* Stream type-dependent parameters */ struct v4l2_streamparm { enum v4l2_buf_type type; union { struct v4l2_captureparm capture; struct v4l2_outputparm output; __u8 raw_data[200]; /* user-defined */ } parm; }; /* * I O C T L C O D E S F O R V I D E O D E V I C E S * */ #define VIDIOC_QUERYCAP _IOR ('V', 0, struct v4l2_capability) #define VIDIOC_RESERVED _IO ('V', 1) #define VIDIOC_ENUM_FMT _IOWR ('V', 2, struct v4l2_fmtdesc) #define VIDIOC_G_FMT _IOWR ('V', 4, struct v4l2_format) #define VIDIOC_S_FMT _IOWR ('V', 5, struct v4l2_format) #ifdef __KERNEL__ #define VIDIOC_G_MPEGCOMP _IOR ('V', 6, struct v4l2_mpeg_compression) #define VIDIOC_S_MPEGCOMP _IOW ('V', 7, struct v4l2_mpeg_compression) #endif #define VIDIOC_REQBUFS _IOWR ('V', 8, struct v4l2_requestbuffers) #define VIDIOC_QUERYBUF _IOWR ('V', 9, struct v4l2_buffer) #define VIDIOC_G_FBUF _IOR ('V', 10, struct v4l2_framebuffer) #define VIDIOC_S_FBUF _IOW ('V', 11, struct v4l2_framebuffer) #define VIDIOC_OVERLAY _IOW ('V', 14, int) #define VIDIOC_QBUF _IOWR ('V', 15, struct v4l2_buffer) #define VIDIOC_DQBUF _IOWR ('V', 17, struct v4l2_buffer) #define VIDIOC_STREAMON _IOW ('V', 18, int) #define VIDIOC_STREAMOFF _IOW ('V', 19, int) #define VIDIOC_G_PARM _IOWR ('V', 21, struct v4l2_streamparm) #define VIDIOC_S_PARM _IOWR ('V', 22, struct v4l2_streamparm) #define VIDIOC_G_STD _IOR ('V', 23, v4l2_std_id) #define VIDIOC_S_STD _IOW ('V', 24, v4l2_std_id) #define VIDIOC_ENUMSTD _IOWR ('V', 25, struct v4l2_standard) #define VIDIOC_ENUMINPUT _IOWR ('V', 26, struct v4l2_input) #define VIDIOC_G_CTRL _IOWR ('V', 27, struct v4l2_control) #define VIDIOC_S_CTRL _IOWR ('V', 28, struct v4l2_control) #define VIDIOC_G_TUNER _IOWR ('V', 29, struct v4l2_tuner) #define VIDIOC_S_TUNER _IOW ('V', 30, struct v4l2_tuner) #define VIDIOC_G_AUDIO _IOR ('V', 33, struct v4l2_audio) #define VIDIOC_S_AUDIO _IOW ('V', 34, struct v4l2_audio) #define VIDIOC_QUERYCTRL _IOWR ('V', 36, struct v4l2_queryctrl) #define VIDIOC_QUERYMENU _IOWR ('V', 37, struct v4l2_querymenu) #define VIDIOC_G_INPUT _IOR ('V', 38, int) #define VIDIOC_S_INPUT _IOWR ('V', 39, int) #define VIDIOC_G_OUTPUT _IOR ('V', 46, int) #define VIDIOC_S_OUTPUT _IOWR ('V', 47, int) #define VIDIOC_ENUMOUTPUT _IOWR ('V', 48, struct v4l2_output) #define VIDIOC_G_AUDOUT _IOR ('V', 49, struct v4l2_audioout) #define VIDIOC_S_AUDOUT _IOW ('V', 50, struct v4l2_audioout) #define VIDIOC_G_MODULATOR _IOWR ('V', 54, struct v4l2_modulator) #define VIDIOC_S_MODULATOR _IOW ('V', 55, struct v4l2_modulator) #define VIDIOC_G_FREQUENCY _IOWR ('V', 56, struct v4l2_frequency) #define VIDIOC_S_FREQUENCY _IOW ('V', 57, struct v4l2_frequency) #define VIDIOC_CROPCAP _IOWR ('V', 58, struct v4l2_cropcap) #define VIDIOC_G_CROP _IOWR ('V', 59, struct v4l2_crop) #define VIDIOC_S_CROP _IOW ('V', 60, struct v4l2_crop) #define VIDIOC_G_JPEGCOMP _IOR ('V', 61, struct v4l2_jpegcompression) #define VIDIOC_S_JPEGCOMP _IOW ('V', 62, struct v4l2_jpegcompression) #define VIDIOC_QUERYSTD _IOR ('V', 63, v4l2_std_id) #define VIDIOC_TRY_FMT _IOWR ('V', 64, struct v4l2_format) #define VIDIOC_ENUMAUDIO _IOWR ('V', 65, struct v4l2_audio) #define VIDIOC_ENUMAUDOUT _IOWR ('V', 66, struct v4l2_audioout) #define VIDIOC_G_PRIORITY _IOR ('V', 67, enum v4l2_priority) #define VIDIOC_S_PRIORITY _IOW ('V', 68, enum v4l2_priority) #if 1 #define VIDIOC_G_SLICED_VBI_CAP _IOWR ('V', 69, struct v4l2_sliced_vbi_cap) #endif #define VIDIOC_LOG_STATUS _IO ('V', 70) #define VIDIOC_G_EXT_CTRLS _IOWR ('V', 71, struct v4l2_ext_controls) #define VIDIOC_S_EXT_CTRLS _IOWR ('V', 72, struct v4l2_ext_controls) #define VIDIOC_TRY_EXT_CTRLS _IOWR ('V', 73, struct v4l2_ext_controls) #if 1 #define VIDIOC_ENUM_FRAMESIZES _IOWR ('V', 74, struct v4l2_frmsizeenum) #define VIDIOC_ENUM_FRAMEINTERVALS _IOWR ('V', 75, struct v4l2_frmivalenum) #endif #ifdef __OLD_VIDIOC_ /* for compatibility, will go away some day */ #define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int) #define VIDIOC_S_PARM_OLD _IOW ('V', 22, struct v4l2_streamparm) #define VIDIOC_S_CTRL_OLD _IOW ('V', 28, struct v4l2_control) #define VIDIOC_G_AUDIO_OLD _IOWR ('V', 33, struct v4l2_audio) #define VIDIOC_G_AUDOUT_OLD _IOWR ('V', 49, struct v4l2_audioout) #define VIDIOC_CROPCAP_OLD _IOR ('V', 58, struct v4l2_cropcap) #endif #define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ #endif /* __LINUX_VIDEODEV2_H */ linux_compat/linux/vmalloc.h000644 000423 000000 00000000351 10560205144 016757 0ustar00luigiwheel000000 000000 #ifndef _LINUX_VMALLOC_H #define _LINUX_VMALLOC_H #include /* kzalloc, in slab.h on linux */ #define vmalloc(sz) vmalloc_32(sz) void *vmalloc_32(unsigned long size); void vfree(void *); #endif /* _LINUX_VMALLOC_H */ linux_compat/linux/wait.h000644 000423 000000 00000007753 10557430060 016306 0ustar00luigiwheel000000 000000 /* * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id: wait.h,v 1.10 2007/01/29 17:34:40 luigi Exp $ * * simple wait/wake_up emulation. * * We do a very simple emulation, always posting a wakeup, and * mapping a wait() into a tsleep. The body of the wait() routine * is in the main file as msleep() is #defined to something else here. */ #ifndef _LINUX_WAIT_H #define _LINUX_WAIT_H #include /* DBG macro */ #include #include #include #include #include #include struct __wait_queue_head { }; typedef struct __wait_queue_head wait_queue_head_t; static inline void init_waitqueue_head(wait_queue_head_t *q) { } /* * Let this always return true. The worst can happen is * some extra wakeup() */ static inline int waitqueue_active(wait_queue_head_t *q) { //return !list_empty(&q->task_list); // DBG("check %p\n", q); return 1; // XXX fixme } #if 0 void __wake_up(wait_queue_head_t *wq, unsigned int mode, int nr_exclusive, void *key) #endif #define __wake_up(wq, mode, nr_exclusive, key) do { \ if (0) DBG("wakeup %p\n", wq); \ wakeup(wq); \ } while (0) #define wake_up_nr(x, nr) \ __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr, NULL) #define wake_up(x) wake_up_nr(x, 1) #define wake_up_all(x) wake_up_nr(x, 0) #define wake_up_interruptible_nr(x, nr) \ __wake_up(x, TASK_INTERRUPTIBLE, nr, NULL) #define wake_up_interruptible(x) wake_up_interruptible_nr(x, 1) #define wake_up_interruptible_all(x) wake_up_interruptible_nr(x, 0) #if 0 #define wake_up_locked(x) \ __wake_up_locked((x), TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE) #define wake_up_interruptible_sync(x) \ __wake_up_sync((x),TASK_INTERRUPTIBLE, 1) #endif /** * wait_event_interruptible - sleep until a condition gets true * @wq: the waitqueue to wait on * @condition: a C expression for the event to wait for * * The process is put to sleep (TASK_INTERRUPTIBLE) until the * @condition evaluates to true or a signal is received. * The @condition is checked each time the waitqueue @wq is woken up. * * wake_up() has to be called after changing any variable that could * change the result of the wait condition. * * The function will return -ERESTARTSYS if it was interrupted by a * signal and 0 if @condition evaluated to true. */ #define wait_event_interruptible(wq, condition) \ ({ \ int __ret = 0; \ if (0) DBG("wq %p on %s\n", &wq, __stringify(condition)); \ while (!(condition)) { \ __ret = wait_event_body(&wq, 0); \ if (__ret == ERESTART) { \ __ret = -ERESTARTSYS; \ break; \ } \ } \ __ret; \ }) #endif /* _LINUX_WAIT_H */ linux_compat/asm/atomic.h000644 000423 000000 00000001746 10560214246 016233 0ustar00luigiwheel000000 000000 #ifndef _LINUX_ASM_ATOMIC_H_ #define _LINUX_ASM_ATOMIC_H_ /* lr 2007.01.23 seems ok */ /* grab the freebsd version of these instructions */ /* require */ #include typedef struct { volatile u_int counter; } atomic_t; /* atomic_add atomically adds i to variable v and returns * the updated value. */ static __inline__ int atomic_add(int i, atomic_t *v) { return i + atomic_fetchadd_int(&v->counter, i); } static __inline__ void atomic_set(atomic_t *v, int i) { v->counter = i; } static __inline__ int atomic_read(const atomic_t *v) { return v->counter; } #define atomic_inc(v) atomic_fetchadd_int(&(v)->counter, 1) /** * atomic_dec_and_test - decrement and test * @v: pointer of type atomic_t * * Atomically decrements @v by 1 and * returns true if the result is 0, or false for all other * cases. */ static __inline__ int atomic_dec_and_test(atomic_t *v) { int i = atomic_add(1, v); return i == 0 ; } #endif /* _LINUX_ASM_ATOMIC_H_ */ linux_compat/asm/cpufeature.h000644 000423 000000 00000000000 10557773642 017120 0ustar00luigiwheel000000 000000 linux_compat/asm/current.h000644 000423 000000 00000000000 10555075224 016424 0ustar00luigiwheel000000 000000 linux_compat/asm/io.h000644 000423 000000 00000000000 10554510224 015342 0ustar00luigiwheel000000 000000 linux_compat/asm/mutex.h000644 000423 000000 00000000031 10560205352 016101 0ustar00luigiwheel000000 000000 #include linux_compat/asm/page.h000644 000423 000000 00000000000 10554510224 015647 0ustar00luigiwheel000000 000000 linux_compat/asm/pgtable.h000644 000423 000000 00000000000 10560205352 016351 0ustar00luigiwheel000000 000000 linux_compat/asm/processor.h000644 000423 000000 00000000000 10557773642 016774 0ustar00luigiwheel000000 000000 linux_compat/asm/semaphore.h000644 000423 000000 00000003351 10557506476 016753 0ustar00luigiwheel000000 000000 /* * stub for asm/semaphore.h */ #ifndef _LINUX_ASM_SEMAPHORE_H #define _LINUX_ASM_SEMAPHORE_H #include #if 1 /* freebsd semaphores */ #include struct semaphore { struct mtx m; }; static inline void init_MUTEX(struct semaphore *sem) { mtx_init(&sem->m, "ldev", NULL, MTX_DEF); } static inline void down(struct semaphore *sem) { mtx_lock(&sem->m); } static inline int down_interruptible(struct semaphore *sem) { down(sem); return 0; } static inline void up(struct semaphore *sem) { mtx_unlock(&sem->m); } #else /* linux semaphores */ /* from asm/semaphore.h */ struct semaphore { atomic_t count; int sleepers; wait_queue_head_t wait; }; static inline void sema_init (struct semaphore *sem, int val) { /* * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val); * * i'd rather use the more flexible initialization above, but sadly * GCC 2.7.2.3 emits a bogus warning. EGCS doesn't. Oh well. */ atomic_set(&sem->count, val); sem->sleepers = 0; init_waitqueue_head(&sem->wait); } static inline void init_MUTEX (struct semaphore *sem) { sema_init(sem, 1); } static inline void up(struct semaphore *sem) { // XXX to be filled } static inline void down(struct semaphore *sem) { // XXX to be filled } static inline int down_interruptible(struct semaphore *sem) { down(sem); return 0; } /* these are fake implementation to be fixed */ #define spin_lock(sem) do {} while (0) #define spin_lock_irq(sem) do {} while (0) #define spin_lock_irqsave(sem, flags) do {flags = 0;} while (0) #define spin_unlock_irqrestore(sem, flags) do {} while (0) #define spin_unlock(sem) do {} while (0) #define spin_unlock_irq(sem) do {} while (0) #endif #endif /* _LINUX_ASM_SEMAPHORE_H */ linux_compat/asm/system.h000644 000423 000000 00000000000 10555075224 016266 0ustar00luigiwheel000000 000000 linux_compat/asm/types.h000644 000423 000000 00000003525 10560746561 016132 0ustar00luigiwheel000000 000000 #ifndef _I386_TYPES_H #define _I386_TYPES_H #ifndef __ASSEMBLY__ typedef unsigned short umode_t; /* * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the * header files exported to user space */ typedef __signed__ char __s8; typedef unsigned char __u8; typedef __signed__ short __s16; typedef unsigned short __u16; typedef __signed__ int __s32; typedef unsigned int __u32; #if defined(__GNUC__) // && !defined(__STRICT_ANSI__) typedef __signed__ long long __s64; typedef unsigned long long __u64; #endif #endif /* __ASSEMBLY__ */ /* * These aren't exported outside the kernel to avoid name space clashes */ #ifdef __KERNEL__ #define BITS_PER_LONG 32 #ifndef __ASSEMBLY__ typedef signed char s8; typedef unsigned char u8; typedef signed short s16; typedef unsigned short u16; typedef signed int s32; typedef unsigned int u32; typedef signed long long s64; typedef unsigned long long u64; /* DMA addresses come in generic and 64-bit flavours. */ #ifdef __amd64__ typedef u64 dma_addr_t; typedef u64 dma64_addr_t; #endif #ifdef __arm__ typedef u32 dma_addr_t; typedef u32 dma64_addr_t; #endif #ifdef __i386__ #ifdef CONFIG_HIGHMEM64G typedef u64 dma_addr_t; #else typedef u32 dma_addr_t; #endif typedef u64 dma64_addr_t; #endif #ifdef __ia64__ typedef u64 dma_addr_t; #endif #ifdef __mips__ #if (defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || \ defined(CONFIG_64BIT) typedef u64 dma_addr_t; #else typedef u32 dma_addr_t; #endif typedef u64 dma64_addr_t; #endif #ifdef __powerpc__ typedef u32 dma_addr_t; typedef u64 dma64_addr_t; #endif #ifdef __sparc64__ typedef u32 dma_addr_t; typedef u64 dma64_addr_t; #endif #ifdef CONFIG_LBD typedef u64 sector_t; #define HAVE_SECTOR_T #endif #ifdef CONFIG_LSF typedef u64 blkcnt_t; #define HAVE_BLKCNT_T #endif #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif linux_compat/asm/uaccess.h000644 000423 000000 00000000602 10562713271 016377 0ustar00luigiwheel000000 000000 #ifndef _LINUX_UACCESS_H #define _LINUX_UACCESS_H #include #include /* * Transfer between kernel and userspace. * Should really be macros because they need to compute the * size of *ptr to decide what to do. * * XXX must be completed. */ int get_user(int x, void *ptr); int put_user(unsigned char x, void *ptr); #endif /* _LINUX_UACCESS_H */