dect
/
linux-2.6
Archived
13
0
Fork 0

[media] cpia, stradis: remove deprecated V4L1 drivers

Nobody stepped in to convert these drivers to V4L2, so they are now
removed from the kernel.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Hans Verkuil 2010-12-25 07:44:33 -03:00 committed by Mauro Carvalho Chehab
parent 71bb2876a3
commit 39c3d48845
16 changed files with 0 additions and 8466 deletions

View File

@ -1,191 +0,0 @@
This is a driver for the CPiA PPC2 driven parallel connected
Camera. For example the Creative WebcamII is CPiA driven.
) [1]Peter Pregler, Linz 2000, published under the [2]GNU GPL
---------------------------------------------------------------------------
USAGE:
General:
========
1) Make sure you have created the video devices (/dev/video*):
- if you have a recent MAKEDEV do a 'cd /dev;./MAKEDEV video'
- otherwise do a:
cd /dev
mknod video0 c 81 0
ln -s video0 video
2) Compile the kernel (see below for the list of options to use),
configure your parport and reboot.
3) If all worked well you should get messages similar
to the following (your versions may be different) on the console:
V4L-Driver for Vision CPiA based cameras v0.7.4
parport0: read2 timeout.
parport0: Multimedia device, VLSI Vision Ltd PPC2
Parallel port driver for Vision CPiA based camera
CPIA Version: 1.20 (2.0)
CPIA PnP-ID: 0553:0002:0100
VP-Version: 1.0 0100
1 camera(s) found
As modules:
===========
Make sure you have selected the following kernel options (you can
select all stuff as modules):
The cpia-stuff is in the section 'Character devices -> Video For Linux'.
CONFIG_PARPORT=m
CONFIG_PARPORT_PC=m
CONFIG_PARPORT_PC_FIFO=y
CONFIG_PARPORT_1284=y
CONFIG_VIDEO_DEV=m
CONFIG_VIDEO_CPIA=m
CONFIG_VIDEO_CPIA_PP=m
For autoloading of all those modules you need to tell module-init-tools
some stuff. Add the following line to your module-init-tools config-file
(e.g. /etc/modprobe.conf or wherever your distribution does store that
stuff):
options parport_pc io=0x378 irq=7 dma=3
alias char-major-81 cpia_pp
The first line tells the dma/irq channels to use. Those _must_ match
the settings of your BIOS. Do NOT simply use the values above. See
Documentation/parport.txt for more information about this. The second
line associates the video-device file with the driver. Of cause you
can also load the modules once upon boot (usually done in /etc/modules).
Linked into the kernel:
=======================
Make sure you have selected the following kernel options. Note that
you cannot compile the parport-stuff as modules and the cpia-driver
statically (the other way round is okay though).
The cpia-stuff is in the section 'Character devices -> Video For Linux'.
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=y
CONFIG_PARPORT_PC_FIFO=y
CONFIG_PARPORT_1284=y
CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_CPIA=y
CONFIG_VIDEO_CPIA_PP=y
To use DMA/irq you will need to tell the kernel upon boot time the
hardware configuration of the parport. You can give the boot-parameter
at the LILO-prompt or specify it in lilo.conf. I use the following
append-line in lilo.conf:
append="parport=0x378,7,3"
See Documentation/parport.txt for more information about the
configuration of the parport and the values given above. Do not simply
use the values given above.
---------------------------------------------------------------------------
FEATURES:
- mmap/read v4l-interface (but no overlay)
- image formats: CIF/QCIF, SIF/QSIF, various others used by isabel;
note: all sizes except CIF/QCIF are implemented by clipping, i.e.
pixels are not uploaded from the camera
- palettes: VIDEO_PALETTE_GRAY, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB555,
VIDEO_PALETTE_RGB24, VIDEO_PALETTE_RGB32, VIDEO_PALETTE_YUYV,
VIDEO_PALETTE_UYVY, VIDEO_PALETTE_YUV422
- state information (color balance, exposure, ...) is preserved between
device opens
- complete control over camera via proc-interface (_all_ camera settings are
supported), there is also a python-gtk application available for this [3]
- works under SMP (but the driver is completely serialized and synchronous)
so you get no benefit from SMP, but at least it does not crash your box
- might work for non-Intel architecture, let us know about this
---------------------------------------------------------------------------
TESTED APPLICATIONS:
- a simple test application based on Xt is available at [3]
- another test-application based on gqcam-0.4 (uses GTK)
- gqcam-0.6 should work
- xawtv-3.x (also the webcam software)
- xawtv-2.46
- w3cam (cgi-interface and vidcat, e.g. you may try out 'vidcat |xv
-maxpect -root -quit +noresetroot -rmode 5 -')
- vic, the MBONE video conferencing tool (version 2.8ucl4-1)
- isabel 3R4beta (barely working, but AFAICT all the problems are on
their side)
- camserv-0.40
See [3] for pointers to v4l-applications.
---------------------------------------------------------------------------
KNOWN PROBLEMS:
- some applications do not handle the image format correctly, you will
see strange horizontal stripes instead of a nice picture -> make sure
your application does use a supported image size or queries the driver
for the actually used size (reason behind this: the camera cannot
provide any image format, so if size NxM is requested the driver will
use a format to the closest fitting N1xM1, the application should now
query for this granted size, most applications do not).
- all the todo ;)
- if there is not enough light and the picture is too dark try to
adjust the SetSensorFPS setting, automatic frame rate adjustment
has its price
- do not try out isabel 3R4beta (built 135), you will be disappointed
---------------------------------------------------------------------------
TODO:
- multiple camera support (struct camera or something) - This should work,
but hasn't been tested yet.
- architecture independence?
- SMP-safe asynchronous mmap interface
- nibble mode for old parport interfaces
- streaming capture, this should give a performance gain
---------------------------------------------------------------------------
IMPLEMENTATION NOTES:
The camera can act in two modes, streaming or grabbing. Right now a
polling grab-scheme is used. Maybe interrupt driven streaming will be
used for a asynchronous mmap interface in the next major release of the
driver. This might give a better frame rate.
---------------------------------------------------------------------------
THANKS (in no particular order):
- Scott J. Bertin <sbertin@mindspring.com> for cleanups, the proc-filesystem
and much more
- Henry Bruce <whb@vvl.co.uk> for providing developers information about
the CPiA chip, I wish all companies would treat Linux as seriously
- Karoly Erdei <Karoly.Erdei@risc.uni-linz.ac.at> and RISC-Linz for being
my boss ;) resp. my employer and for providing me the hardware and
allow me to devote some working time to this project
- Manuel J. Petit de Gabriel <mpetit@dit.upm.es> for providing help
with Isabel (http://isabel.dit.upm.es/)
- Bas Huisman <bhuism@cs.utwente.nl> for writing the initial parport code
- Jarl Totland <Jarl.Totland@bdc.no> for setting up the mailing list
and maintaining the web-server[3]
- Chris Whiteford <Chris@informinteractive.com> for fixes related to the
1.02 firmware
- special kudos to all the tester whose machines crashed and/or
will crash. :)
---------------------------------------------------------------------------
REFERENCES
1. http://www.risc.uni-linz.ac.at/
mailto:Peter_Pregler@email.com
2. see the file COPYING in the top directory of the kernel tree
3. http://webcam.sourceforge.net/

View File

@ -464,10 +464,6 @@ Siemens
-------
Multimedia eXtension Board (MXB) (SAA7146, SAA7111)
Stradis
-------
SDM275,SDM250,SDM026,SDM025 (SAA7146, IBMMPEG2): MPEG2 decoder only
Powercolor
----------
MTV878

View File

@ -5697,12 +5697,6 @@ M: Ion Badulescu <ionut@badula.org>
S: Odd Fixes
F: drivers/net/starfire*
STRADIS MPEG-2 DECODER DRIVER
M: Nathan Laredo <laredo@gnu.org>
W: http://www.stradis.com/
S: Maintained
F: drivers/media/video/stradis.c
SUN3/3X
M: Sam Creasey <sammy@sammy.net>
W: http://sammy.net/sun3/

View File

@ -51,10 +51,6 @@ source "drivers/staging/cx25821/Kconfig"
source "drivers/staging/tm6000/Kconfig"
source "drivers/staging/cpia/Kconfig"
source "drivers/staging/stradis/Kconfig"
source "drivers/staging/se401/Kconfig"
source "drivers/staging/usbvideo/Kconfig"

View File

@ -8,8 +8,6 @@ obj-$(CONFIG_SLICOSS) += slicoss/
obj-$(CONFIG_VIDEO_GO7007) += go7007/
obj-$(CONFIG_VIDEO_CX25821) += cx25821/
obj-$(CONFIG_VIDEO_TM6000) += tm6000/
obj-$(CONFIG_VIDEO_CPIA) += cpia/
obj-$(CONFIG_VIDEO_STRADIS) += stradis/
obj-$(CONFIG_USB_VICAM) += usbvideo/
obj-$(CONFIG_USB_SE401) += se401/
obj-$(CONFIG_LIRC_STAGING) += lirc/

View File

@ -1,39 +0,0 @@
config VIDEO_CPIA
tristate "CPiA Video For Linux (DEPRECATED)"
depends on VIDEO_V4L1
default n
---help---
This driver is DEPRECATED please use the gspca cpia1 module
instead. Note that you need atleast version 0.6.4 of libv4l for
the cpia1 gspca module.
This is the video4linux driver for cameras based on Vision's CPiA
(Colour Processor Interface ASIC), such as the Creative Labs Video
Blaster Webcam II. If you have one of these cameras, say Y here
and select parallel port and/or USB lowlevel support below,
otherwise say N. This will not work with the Creative Webcam III.
Please read <file:Documentation/video4linux/README.cpia> for more
information.
This driver is also available as a module (cpia).
config VIDEO_CPIA_PP
tristate "CPiA Parallel Port Lowlevel Support"
depends on PARPORT_1284 && VIDEO_CPIA && PARPORT
help
This is the lowlevel parallel port support for cameras based on
Vision's CPiA (Colour Processor Interface ASIC), such as the
Creative Webcam II. If you have the parallel port version of one
of these cameras, say Y here, otherwise say N. It is also available
as a module (cpia_pp).
config VIDEO_CPIA_USB
tristate "CPiA USB Lowlevel Support"
depends on VIDEO_CPIA && USB
help
This is the lowlevel USB support for cameras based on Vision's CPiA
(Colour Processor Interface ASIC), such as the Creative Webcam II.
If you have the USB version of one of these cameras, say Y here,
otherwise say N. This will not work with the Creative Webcam III.
It is also available as a module (cpia_usb).

View File

@ -1,5 +0,0 @@
obj-$(CONFIG_VIDEO_CPIA) += cpia.o
obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o
obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o
EXTRA_CFLAGS += -Idrivers/media/video

View File

@ -1,8 +0,0 @@
This is an obsolete driver for some cpia-based webcams that use the parallel port.
We couldn't find anyone with this hardware in order to port it to use V4L2.
Also, parallel-port webcams are obsolete nowadays.
If nobody take care on it, the driver will be removed for 2.6.38.
Please send patches to linux-media@vger.kernel.org

File diff suppressed because it is too large Load Diff

View File

@ -1,432 +0,0 @@
#ifndef cpia_h
#define cpia_h
/*
* CPiA Parallel Port Video4Linux driver
*
* Supports CPiA based parallel port Video Camera's.
*
* (C) Copyright 1999 Bas Huisman,
* Peter Pregler,
* Scott J. Bertin,
* VLSI Vision Ltd.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define CPIA_MAJ_VER 1
#define CPIA_MIN_VER 2
#define CPIA_PATCH_VER 3
#define CPIA_PP_MAJ_VER CPIA_MAJ_VER
#define CPIA_PP_MIN_VER CPIA_MIN_VER
#define CPIA_PP_PATCH_VER CPIA_PATCH_VER
#define CPIA_USB_MAJ_VER CPIA_MAJ_VER
#define CPIA_USB_MIN_VER CPIA_MIN_VER
#define CPIA_USB_PATCH_VER CPIA_PATCH_VER
#define CPIA_MAX_FRAME_SIZE_UNALIGNED (352 * 288 * 4) /* CIF at RGB32 */
#define CPIA_MAX_FRAME_SIZE ((CPIA_MAX_FRAME_SIZE_UNALIGNED + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) /* align above to PAGE_SIZE */
#ifdef __KERNEL__
#include <asm/uaccess.h>
#include <linux/videodev.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <linux/list.h>
#include <linux/mutex.h>
struct cpia_camera_ops
{
/* open sets privdata to point to structure for this camera.
* Returns negative value on error, otherwise 0.
*/
int (*open)(void *privdata);
/* Registers callback function cb to be called with cbdata
* when an image is ready. If cb is NULL, only single image grabs
* should be used. cb should immediately call streamRead to read
* the data or data may be lost. Returns negative value on error,
* otherwise 0.
*/
int (*registerCallback)(void *privdata, void (*cb)(void *cbdata),
void *cbdata);
/* transferCmd sends commands to the camera. command MUST point to
* an 8 byte buffer in kernel space. data can be NULL if no extra
* data is needed. The size of the data is given by the last 2
* bytes of command. data must also point to memory in kernel space.
* Returns negative value on error, otherwise 0.
*/
int (*transferCmd)(void *privdata, u8 *command, u8 *data);
/* streamStart initiates stream capture mode.
* Returns negative value on error, otherwise 0.
*/
int (*streamStart)(void *privdata);
/* streamStop terminates stream capture mode.
* Returns negative value on error, otherwise 0.
*/
int (*streamStop)(void *privdata);
/* streamRead reads a frame from the camera. buffer points to a
* buffer large enough to hold a complete frame in kernel space.
* noblock indicates if this should be a non blocking read.
* Returns the number of bytes read, or negative value on error.
*/
int (*streamRead)(void *privdata, u8 *buffer, int noblock);
/* close disables the device until open() is called again.
* Returns negative value on error, otherwise 0.
*/
int (*close)(void *privdata);
/* If wait_for_stream_ready is non-zero, wait until the streamState
* is STREAM_READY before calling streamRead.
*/
int wait_for_stream_ready;
/*
* Used to maintain lowlevel module usage counts
*/
struct module *owner;
};
struct cpia_frame {
u8 *data;
int count;
int width;
int height;
volatile int state;
};
struct cam_params {
struct {
u8 firmwareVersion;
u8 firmwareRevision;
u8 vcVersion;
u8 vcRevision;
} version;
struct {
u16 vendor;
u16 product;
u16 deviceRevision;
} pnpID;
struct {
u8 vpVersion;
u8 vpRevision;
u16 cameraHeadID;
} vpVersion;
struct {
u8 systemState;
u8 grabState;
u8 streamState;
u8 fatalError;
u8 cmdError;
u8 debugFlags;
u8 vpStatus;
u8 errorCode;
} status;
struct {
u8 brightness;
u8 contrast;
u8 saturation;
} colourParams;
struct {
u8 gainMode;
u8 expMode;
u8 compMode;
u8 centreWeight;
u8 gain;
u8 fineExp;
u8 coarseExpLo;
u8 coarseExpHi;
u8 redComp;
u8 green1Comp;
u8 green2Comp;
u8 blueComp;
} exposure;
struct {
u8 balanceMode;
u8 redGain;
u8 greenGain;
u8 blueGain;
} colourBalance;
struct {
u8 divisor;
u8 baserate;
} sensorFps;
struct {
u8 gain1;
u8 gain2;
u8 gain4;
u8 gain8;
} apcor;
struct {
u8 disabled;
u8 flickerMode;
u8 coarseJump;
int allowableOverExposure;
} flickerControl;
struct {
u8 gain1;
u8 gain2;
u8 gain4;
u8 gain8;
} vlOffset;
struct {
u8 mode;
u8 decimation;
} compression;
struct {
u8 frTargeting;
u8 targetFR;
u8 targetQ;
} compressionTarget;
struct {
u8 yThreshold;
u8 uvThreshold;
} yuvThreshold;
struct {
u8 hysteresis;
u8 threshMax;
u8 smallStep;
u8 largeStep;
u8 decimationHysteresis;
u8 frDiffStepThresh;
u8 qDiffStepThresh;
u8 decimationThreshMod;
} compressionParams;
struct {
u8 videoSize; /* CIF/QCIF */
u8 subSample;
u8 yuvOrder;
} format;
struct { /* Intel QX3 specific data */
u8 qx3_detected; /* a QX3 is present */
u8 toplight; /* top light lit , R/W */
u8 bottomlight; /* bottom light lit, R/W */
u8 button; /* snapshot button pressed (R/O) */
u8 cradled; /* microscope is in cradle (R/O) */
} qx3;
struct {
u8 colStart; /* skip first 8*colStart pixels */
u8 colEnd; /* finish at 8*colEnd pixels */
u8 rowStart; /* skip first 4*rowStart lines */
u8 rowEnd; /* finish at 4*rowEnd lines */
} roi;
u8 ecpTiming;
u8 streamStartLine;
};
enum v4l_camstates {
CPIA_V4L_IDLE = 0,
CPIA_V4L_ERROR,
CPIA_V4L_COMMAND,
CPIA_V4L_GRABBING,
CPIA_V4L_STREAMING,
CPIA_V4L_STREAMING_PAUSED,
};
#define FRAME_NUM 2 /* double buffering for now */
struct cam_data {
struct list_head cam_data_list;
struct mutex busy_lock; /* guard against SMP multithreading */
struct cpia_camera_ops *ops; /* lowlevel driver operations */
void *lowlevel_data; /* private data for lowlevel driver */
u8 *raw_image; /* buffer for raw image data */
struct cpia_frame decompressed_frame;
/* buffer to hold decompressed frame */
int image_size; /* sizeof last decompressed image */
int open_count; /* # of process that have camera open */
/* camera status */
int fps; /* actual fps reported by the camera */
int transfer_rate; /* transfer rate from camera in kB/s */
u8 mainsFreq; /* for flicker control */
/* proc interface */
struct mutex param_lock; /* params lock for this camera */
struct cam_params params; /* camera settings */
struct proc_dir_entry *proc_entry; /* /proc/cpia/videoX */
/* v4l */
int video_size; /* VIDEO_SIZE_ */
volatile enum v4l_camstates camstate; /* v4l layer status */
struct video_device vdev; /* v4l videodev */
struct video_picture vp; /* v4l camera settings */
struct video_window vw; /* v4l capture area */
struct video_capture vc; /* v4l subcapture area */
/* mmap interface */
int curframe; /* the current frame to grab into */
u8 *frame_buf; /* frame buffer data */
struct cpia_frame frame[FRAME_NUM];
/* FRAME_NUM-buffering, so we need a array */
int first_frame;
int mmap_kludge; /* 'wrong' byte order for mmap */
volatile u32 cmd_queue; /* queued commands */
int exposure_status; /* EXPOSURE_* */
int exposure_count; /* number of frames at this status */
};
/* cpia_register_camera is called by low level driver for each camera.
* A unique camera number is returned, or a negative value on error */
struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel);
/* cpia_unregister_camera is called by low level driver when a camera
* is removed. This must not fail. */
void cpia_unregister_camera(struct cam_data *cam);
/* raw CIF + 64 byte header + (2 bytes line_length + EOL) per line + 4*EOI +
* one byte 16bit DMA alignment
*/
#define CPIA_MAX_IMAGE_SIZE ((352*288*2)+64+(288*3)+5)
/* constant value's */
#define MAGIC_0 0x19
#define MAGIC_1 0x68
#define DATA_IN 0xC0
#define DATA_OUT 0x40
#define VIDEOSIZE_QCIF 0 /* 176x144 */
#define VIDEOSIZE_CIF 1 /* 352x288 */
#define VIDEOSIZE_SIF 2 /* 320x240 */
#define VIDEOSIZE_QSIF 3 /* 160x120 */
#define VIDEOSIZE_48_48 4 /* where no one has gone before, iconsize! */
#define VIDEOSIZE_64_48 5
#define VIDEOSIZE_128_96 6
#define VIDEOSIZE_160_120 VIDEOSIZE_QSIF
#define VIDEOSIZE_176_144 VIDEOSIZE_QCIF
#define VIDEOSIZE_192_144 7
#define VIDEOSIZE_224_168 8
#define VIDEOSIZE_256_192 9
#define VIDEOSIZE_288_216 10
#define VIDEOSIZE_320_240 VIDEOSIZE_SIF
#define VIDEOSIZE_352_288 VIDEOSIZE_CIF
#define VIDEOSIZE_88_72 11 /* quarter CIF */
#define SUBSAMPLE_420 0
#define SUBSAMPLE_422 1
#define YUVORDER_YUYV 0
#define YUVORDER_UYVY 1
#define NOT_COMPRESSED 0
#define COMPRESSED 1
#define NO_DECIMATION 0
#define DECIMATION_ENAB 1
#define EOI 0xff /* End Of Image */
#define EOL 0xfd /* End Of Line */
#define FRAME_HEADER_SIZE 64
/* Image grab modes */
#define CPIA_GRAB_SINGLE 0
#define CPIA_GRAB_CONTINUOUS 1
/* Compression parameters */
#define CPIA_COMPRESSION_NONE 0
#define CPIA_COMPRESSION_AUTO 1
#define CPIA_COMPRESSION_MANUAL 2
#define CPIA_COMPRESSION_TARGET_QUALITY 0
#define CPIA_COMPRESSION_TARGET_FRAMERATE 1
/* Return offsets for GetCameraState */
#define SYSTEMSTATE 0
#define GRABSTATE 1
#define STREAMSTATE 2
#define FATALERROR 3
#define CMDERROR 4
#define DEBUGFLAGS 5
#define VPSTATUS 6
#define ERRORCODE 7
/* SystemState */
#define UNINITIALISED_STATE 0
#define PASS_THROUGH_STATE 1
#define LO_POWER_STATE 2
#define HI_POWER_STATE 3
#define WARM_BOOT_STATE 4
/* GrabState */
#define GRAB_IDLE 0
#define GRAB_ACTIVE 1
#define GRAB_DONE 2
/* StreamState */
#define STREAM_NOT_READY 0
#define STREAM_READY 1
#define STREAM_OPEN 2
#define STREAM_PAUSED 3
#define STREAM_FINISHED 4
/* Fatal Error, CmdError, and DebugFlags */
#define CPIA_FLAG 1
#define SYSTEM_FLAG 2
#define INT_CTRL_FLAG 4
#define PROCESS_FLAG 8
#define COM_FLAG 16
#define VP_CTRL_FLAG 32
#define CAPTURE_FLAG 64
#define DEBUG_FLAG 128
/* VPStatus */
#define VP_STATE_OK 0x00
#define VP_STATE_FAILED_VIDEOINIT 0x01
#define VP_STATE_FAILED_AECACBINIT 0x02
#define VP_STATE_AEC_MAX 0x04
#define VP_STATE_ACB_BMAX 0x08
#define VP_STATE_ACB_RMIN 0x10
#define VP_STATE_ACB_GMIN 0x20
#define VP_STATE_ACB_RMAX 0x40
#define VP_STATE_ACB_GMAX 0x80
/* default (minimum) compensation values */
#define COMP_RED 220
#define COMP_GREEN1 214
#define COMP_GREEN2 COMP_GREEN1
#define COMP_BLUE 230
/* exposure status */
#define EXPOSURE_VERY_LIGHT 0
#define EXPOSURE_LIGHT 1
#define EXPOSURE_NORMAL 2
#define EXPOSURE_DARK 3
#define EXPOSURE_VERY_DARK 4
/* ErrorCode */
#define ERROR_FLICKER_BELOW_MIN_EXP 0x01 /*flicker exposure got below minimum exposure */
#define ALOG(fmt,args...) printk(fmt, ##args)
#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __func__ , __LINE__ , ##args)
#ifdef _CPIA_DEBUG_
#define ADBG(fmt,args...) printk(fmt, jiffies, ##args)
#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args)
#else
#define DBG(fmn,args...) do {} while(0)
#endif
#define DEB_BYTE(p)\
DBG("%1d %1d %1d %1d %1d %1d %1d %1d \n",\
(p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\
(p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0);
#endif /* __KERNEL__ */
#endif /* cpia_h */

View File

@ -1,869 +0,0 @@
/*
* cpia_pp CPiA Parallel Port driver
*
* Supports CPiA based parallel port Video Camera's.
*
* (C) Copyright 1999 Bas Huisman <bhuism@cs.utwente.nl>
* (C) Copyright 1999-2000 Scott J. Bertin <sbertin@securenym.net>,
* (C) Copyright 1999-2000 Peter Pregler <Peter_Pregler@email.com>
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
/* #define _CPIA_DEBUG_ 1 */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/parport.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/kmod.h>
/* #define _CPIA_DEBUG_ define for verbose debug output */
#include "cpia.h"
static int cpia_pp_open(void *privdata);
static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata),
void *cbdata);
static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data);
static int cpia_pp_streamStart(void *privdata);
static int cpia_pp_streamStop(void *privdata);
static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock);
static int cpia_pp_close(void *privdata);
#define ABOUT "Parallel port driver for Vision CPiA based cameras"
#define PACKET_LENGTH 8
/* Magic numbers for defining port-device mappings */
#define PPCPIA_PARPORT_UNSPEC -4
#define PPCPIA_PARPORT_AUTO -3
#define PPCPIA_PARPORT_OFF -2
#define PPCPIA_PARPORT_NONE -1
static int parport_nr[PARPORT_MAX] = {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC};
static char *parport[PARPORT_MAX] = {NULL,};
MODULE_AUTHOR("B. Huisman <bhuism@cs.utwente.nl> & Peter Pregler <Peter_Pregler@email.com>");
MODULE_DESCRIPTION("Parallel port driver for Vision CPiA based cameras");
MODULE_LICENSE("GPL");
module_param_array(parport, charp, NULL, 0);
MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp.");
struct pp_cam_entry {
struct pardevice *pdev;
struct parport *port;
struct work_struct cb_task;
void (*cb_func)(void *cbdata);
void *cb_data;
int open_count;
wait_queue_head_t wq_stream;
/* image state flags */
int image_ready; /* we got an interrupt */
int image_complete; /* we have seen 4 EOI */
int streaming; /* we are in streaming mode */
int stream_irq;
};
static struct cpia_camera_ops cpia_pp_ops =
{
cpia_pp_open,
cpia_pp_registerCallback,
cpia_pp_transferCmd,
cpia_pp_streamStart,
cpia_pp_streamStop,
cpia_pp_streamRead,
cpia_pp_close,
1,
THIS_MODULE
};
static LIST_HEAD(cam_list);
static spinlock_t cam_list_lock_pp;
/* FIXME */
static void cpia_parport_enable_irq( struct parport *port ) {
parport_enable_irq(port);
mdelay(10);
return;
}
static void cpia_parport_disable_irq( struct parport *port ) {
parport_disable_irq(port);
mdelay(10);
return;
}
/* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility
* Link Flag during negotiation */
#define UPLOAD_FLAG 0x08
#define NIBBLE_TRANSFER 0x01
#define ECP_TRANSFER 0x03
#define PARPORT_CHUNK_SIZE PAGE_SIZE
static void cpia_pp_run_callback(struct work_struct *work)
{
void (*cb_func)(void *cbdata);
void *cb_data;
struct pp_cam_entry *cam;
cam = container_of(work, struct pp_cam_entry, cb_task);
cb_func = cam->cb_func;
cb_data = cam->cb_data;
cb_func(cb_data);
}
/****************************************************************************
*
* CPiA-specific low-level parport functions for nibble uploads
*
***************************************************************************/
/* CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */
/* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */
static size_t cpia_read_nibble (struct parport *port,
void *buffer, size_t len,
int flags)
{
/* adapted verbatim, with one change, from
parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */
unsigned char *buf = buffer;
int i;
unsigned char byte = 0;
len *= 2; /* in nibbles */
for (i=0; i < len; i++) {
unsigned char nibble;
/* The CPiA firmware suppresses the use of nDataAvail (nFault LO)
* after every second nibble to signal that more
* data is available. (the total number of Bytes that
* should be sent is known; if too few are received, an error
* will be recorded after a timeout).
* This is incompatible with parport_ieee1284_read_nibble(),
* which expects to find nFault LO after every second nibble.
*/
/* Solution: modify cpia_read_nibble to only check for
* nDataAvail before the first nibble is sent.
*/
/* Does the error line indicate end of data? */
if (((i /*& 1*/) == 0) &&
(parport_read_status(port) & PARPORT_STATUS_ERROR)) {
DBG("%s: No more nibble data (%d bytes)\n",
port->name, i/2);
goto end_of_data;
}
/* Event 7: Set nAutoFd low. */
parport_frob_control (port,
PARPORT_CONTROL_AUTOFD,
PARPORT_CONTROL_AUTOFD);
/* Event 9: nAck goes low. */
port->ieee1284.phase = IEEE1284_PH_REV_DATA;
if (parport_wait_peripheral (port,
PARPORT_STATUS_ACK, 0)) {
/* Timeout -- no more data? */
DBG("%s: Nibble timeout at event 9 (%d bytes)\n",
port->name, i/2);
parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
break;
}
/* Read a nibble. */
nibble = parport_read_status (port) >> 3;
nibble &= ~8;
if ((nibble & 0x10) == 0)
nibble |= 8;
nibble &= 0xf;
/* Event 10: Set nAutoFd high. */
parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
/* Event 11: nAck goes high. */
if (parport_wait_peripheral (port,
PARPORT_STATUS_ACK,
PARPORT_STATUS_ACK)) {
/* Timeout -- no more data? */
DBG("%s: Nibble timeout at event 11\n",
port->name);
break;
}
if (i & 1) {
/* Second nibble */
byte |= nibble << 4;
*buf++ = byte;
} else
byte = nibble;
}
if (i == len) {
/* Read the last nibble without checking data avail. */
if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
end_of_data:
/* Go to reverse idle phase. */
parport_frob_control (port,
PARPORT_CONTROL_AUTOFD,
PARPORT_CONTROL_AUTOFD);
port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
}
else
port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
}
return i/2;
}
/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1)
* (See CPiA Data sheet p. 31)
*
* "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a
* nonstandard variant of nibble mode which allows the same (mediocre)
* data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable
* parallel ports, but works also for non-TRISTATE-capable ports.
* (Standard nibble mode only send 4 bits per cycle)
*
*/
static size_t cpia_read_nibble_stream(struct parport *port,
void *buffer, size_t len,
int flags)
{
int i;
unsigned char *buf = buffer;
int endseen = 0;
for (i=0; i < len; i++) {
unsigned char nibble[2], byte = 0;
int j;
/* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */
if (endseen > 3 )
break;
/* Event 7: Set nAutoFd low. */
parport_frob_control (port,
PARPORT_CONTROL_AUTOFD,
PARPORT_CONTROL_AUTOFD);
/* Event 9: nAck goes low. */
port->ieee1284.phase = IEEE1284_PH_REV_DATA;
if (parport_wait_peripheral (port,
PARPORT_STATUS_ACK, 0)) {
/* Timeout -- no more data? */
DBG("%s: Nibble timeout at event 9 (%d bytes)\n",
port->name, i/2);
parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
break;
}
/* Read lower nibble */
nibble[0] = parport_read_status (port) >>3;
/* Event 10: Set nAutoFd high. */
parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
/* Event 11: nAck goes high. */
if (parport_wait_peripheral (port,
PARPORT_STATUS_ACK,
PARPORT_STATUS_ACK)) {
/* Timeout -- no more data? */
DBG("%s: Nibble timeout at event 11\n",
port->name);
break;
}
/* Read upper nibble */
nibble[1] = parport_read_status (port) >>3;
/* reassemble the byte */
for (j = 0; j < 2 ; j++ ) {
nibble[j] &= ~8;
if ((nibble[j] & 0x10) == 0)
nibble[j] |= 8;
nibble[j] &= 0xf;
}
byte = (nibble[0] |(nibble[1] << 4));
*buf++ = byte;
if(byte == EOI)
endseen++;
else
endseen = 0;
}
return i;
}
/****************************************************************************
*
* EndTransferMode
*
***************************************************************************/
static void EndTransferMode(struct pp_cam_entry *cam)
{
parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);
}
/****************************************************************************
*
* ForwardSetup
*
***************************************************************************/
static int ForwardSetup(struct pp_cam_entry *cam)
{
int retry;
/* The CPiA uses ECP protocol for Downloads from the Host to the camera.
* This will be software-emulated if ECP hardware is not present
*/
/* the usual camera maximum response time is 10ms, but after receiving
* some commands, it needs up to 40ms. (Data Sheet p. 32)*/
for(retry = 0; retry < 4; ++retry) {
if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) {
break;
}
mdelay(10);
}
if(retry == 4) {
DBG("Unable to negotiate IEEE1284 ECP Download mode\n");
return -1;
}
return 0;
}
/****************************************************************************
*
* ReverseSetup
*
***************************************************************************/
static int ReverseSetup(struct pp_cam_entry *cam, int extensibility)
{
int retry;
int upload_mode, mode = IEEE1284_MODE_ECP;
int transfer_mode = ECP_TRANSFER;
if (!(cam->port->modes & PARPORT_MODE_ECP) &&
!(cam->port->modes & PARPORT_MODE_TRISTATE)) {
mode = IEEE1284_MODE_NIBBLE;
transfer_mode = NIBBLE_TRANSFER;
}
upload_mode = mode;
if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK;
/* the usual camera maximum response time is 10ms, but after
* receiving some commands, it needs up to 40ms. */
for(retry = 0; retry < 4; ++retry) {
if(!parport_negotiate(cam->port, mode)) {
break;
}
mdelay(10);
}
if(retry == 4) {
if(extensibility)
DBG("Unable to negotiate upload extensibility mode\n");
else
DBG("Unable to negotiate upload mode\n");
return -1;
}
if(extensibility) cam->port->ieee1284.mode = upload_mode;
return 0;
}
/****************************************************************************
*
* WritePacket
*
***************************************************************************/
static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size)
{
int retval=0;
int size_written;
if (packet == NULL) {
return -EINVAL;
}
if (ForwardSetup(cam)) {
DBG("Write failed in setup\n");
return -EIO;
}
size_written = parport_write(cam->port, packet, size);
if(size_written != size) {
DBG("Write failed, wrote %d/%d\n", size_written, size);
retval = -EIO;
}
EndTransferMode(cam);
return retval;
}
/****************************************************************************
*
* ReadPacket
*
***************************************************************************/
static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size)
{
int retval=0;
if (packet == NULL) {
return -EINVAL;
}
if (ReverseSetup(cam, 0)) {
return -EIO;
}
/* support for CPiA variant nibble reads */
if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) {
if(cpia_read_nibble(cam->port, packet, size, 0) != size)
retval = -EIO;
} else {
if(parport_read(cam->port, packet, size) != size)
retval = -EIO;
}
EndTransferMode(cam);
return retval;
}
/****************************************************************************
*
* cpia_pp_streamStart
*
***************************************************************************/
static int cpia_pp_streamStart(void *privdata)
{
struct pp_cam_entry *cam = privdata;
DBG("\n");
cam->streaming=1;
cam->image_ready=0;
//if (ReverseSetup(cam,1)) return -EIO;
if(cam->stream_irq) cpia_parport_enable_irq(cam->port);
return 0;
}
/****************************************************************************
*
* cpia_pp_streamStop
*
***************************************************************************/
static int cpia_pp_streamStop(void *privdata)
{
struct pp_cam_entry *cam = privdata;
DBG("\n");
cam->streaming=0;
cpia_parport_disable_irq(cam->port);
//EndTransferMode(cam);
return 0;
}
/****************************************************************************
*
* cpia_pp_streamRead
*
***************************************************************************/
static int cpia_pp_read(struct parport *port, u8 *buffer, int len)
{
int bytes_read;
/* support for CPiA variant "nibble stream" reads */
if(port->ieee1284.mode == IEEE1284_MODE_NIBBLE)
bytes_read = cpia_read_nibble_stream(port,buffer,len,0);
else {
int new_bytes;
for(bytes_read=0; bytes_read<len; bytes_read += new_bytes) {
new_bytes = parport_read(port, buffer+bytes_read,
len-bytes_read);
if(new_bytes < 0) break;
}
}
return bytes_read;
}
static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
{
struct pp_cam_entry *cam = privdata;
int read_bytes = 0;
int i, endseen, block_size, new_bytes;
if(cam == NULL) {
DBG("Internal driver error: cam is NULL\n");
return -EINVAL;
}
if(buffer == NULL) {
DBG("Internal driver error: buffer is NULL\n");
return -EINVAL;
}
//if(cam->streaming) DBG("%d / %d\n", cam->image_ready, noblock);
if( cam->stream_irq ) {
DBG("%d\n", cam->image_ready);
cam->image_ready--;
}
cam->image_complete=0;
if (0/*cam->streaming*/) {
if(!cam->image_ready) {
if(noblock) return -EWOULDBLOCK;
interruptible_sleep_on(&cam->wq_stream);
if( signal_pending(current) ) return -EINTR;
DBG("%d\n", cam->image_ready);
}
} else {
if (ReverseSetup(cam, 1)) {
DBG("unable to ReverseSetup\n");
return -EIO;
}
}
endseen = 0;
block_size = PARPORT_CHUNK_SIZE;
while( !cam->image_complete ) {
cond_resched();
new_bytes = cpia_pp_read(cam->port, buffer, block_size );
if( new_bytes <= 0 ) {
break;
}
i=-1;
while(++i<new_bytes && endseen<4) {
if(*buffer==EOI) {
endseen++;
} else {
endseen=0;
}
buffer++;
}
read_bytes += i;
if( endseen==4 ) {
cam->image_complete=1;
break;
}
if( CPIA_MAX_IMAGE_SIZE-read_bytes <= PARPORT_CHUNK_SIZE ) {
block_size=CPIA_MAX_IMAGE_SIZE-read_bytes;
}
}
EndTransferMode(cam);
return cam->image_complete ? read_bytes : -EIO;
}
/****************************************************************************
*
* cpia_pp_transferCmd
*
***************************************************************************/
static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data)
{
int err;
int retval=0;
int databytes;
struct pp_cam_entry *cam = privdata;
if(cam == NULL) {
DBG("Internal driver error: cam is NULL\n");
return -EINVAL;
}
if(command == NULL) {
DBG("Internal driver error: command is NULL\n");
return -EINVAL;
}
databytes = (((int)command[7])<<8) | command[6];
if ((err = WritePacket(cam, command, PACKET_LENGTH)) < 0) {
DBG("Error writing command\n");
return err;
}
if(command[0] == DATA_IN) {
u8 buffer[8];
if(data == NULL) {
DBG("Internal driver error: data is NULL\n");
return -EINVAL;
}
if((err = ReadPacket(cam, buffer, 8)) < 0) {
DBG("Error reading command result\n");
return err;
}
memcpy(data, buffer, databytes);
} else if(command[0] == DATA_OUT) {
if(databytes > 0) {
if(data == NULL) {
DBG("Internal driver error: data is NULL\n");
retval = -EINVAL;
} else {
if((err=WritePacket(cam, data, databytes)) < 0){
DBG("Error writing command data\n");
return err;
}
}
}
} else {
DBG("Unexpected first byte of command: %x\n", command[0]);
retval = -EINVAL;
}
return retval;
}
/****************************************************************************
*
* cpia_pp_open
*
***************************************************************************/
static int cpia_pp_open(void *privdata)
{
struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata;
if (cam == NULL)
return -EINVAL;
if(cam->open_count == 0) {
if (parport_claim(cam->pdev)) {
DBG("failed to claim the port\n");
return -EBUSY;
}
parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);
parport_data_forward(cam->port);
parport_write_control(cam->port, PARPORT_CONTROL_SELECT);
udelay(50);
parport_write_control(cam->port,
PARPORT_CONTROL_SELECT
| PARPORT_CONTROL_INIT);
}
++cam->open_count;
return 0;
}
/****************************************************************************
*
* cpia_pp_registerCallback
*
***************************************************************************/
static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), void *cbdata)
{
struct pp_cam_entry *cam = privdata;
int retval = 0;
if(cam->port->irq != PARPORT_IRQ_NONE) {
cam->cb_func = cb;
cam->cb_data = cbdata;
INIT_WORK(&cam->cb_task, cpia_pp_run_callback);
} else {
retval = -1;
}
return retval;
}
/****************************************************************************
*
* cpia_pp_close
*
***************************************************************************/
static int cpia_pp_close(void *privdata)
{
struct pp_cam_entry *cam = privdata;
if (--cam->open_count == 0) {
parport_release(cam->pdev);
}
return 0;
}
/****************************************************************************
*
* cpia_pp_register
*
***************************************************************************/
static int cpia_pp_register(struct parport *port)
{
struct pardevice *pdev = NULL;
struct pp_cam_entry *cam;
struct cam_data *cpia;
if (!(port->modes & PARPORT_MODE_PCSPP)) {
LOG("port is not supported by CPiA driver\n");
return -ENXIO;
}
cam = kzalloc(sizeof(struct pp_cam_entry), GFP_KERNEL);
if (cam == NULL) {
LOG("failed to allocate camera structure\n");
return -ENOMEM;
}
pdev = parport_register_device(port, "cpia_pp", NULL, NULL,
NULL, 0, cam);
if (!pdev) {
LOG("failed to parport_register_device\n");
kfree(cam);
return -ENXIO;
}
cam->pdev = pdev;
cam->port = port;
init_waitqueue_head(&cam->wq_stream);
cam->streaming = 0;
cam->stream_irq = 0;
if((cpia = cpia_register_camera(&cpia_pp_ops, cam)) == NULL) {
LOG("failed to cpia_register_camera\n");
parport_unregister_device(pdev);
kfree(cam);
return -ENXIO;
}
spin_lock( &cam_list_lock_pp );
list_add( &cpia->cam_data_list, &cam_list );
spin_unlock( &cam_list_lock_pp );
return 0;
}
static void cpia_pp_detach (struct parport *port)
{
struct list_head *tmp;
struct cam_data *cpia = NULL;
struct pp_cam_entry *cam;
spin_lock( &cam_list_lock_pp );
list_for_each (tmp, &cam_list) {
cpia = list_entry(tmp, struct cam_data, cam_data_list);
cam = (struct pp_cam_entry *) cpia->lowlevel_data;
if (cam && cam->port->number == port->number) {
list_del(&cpia->cam_data_list);
break;
}
cpia = NULL;
}
spin_unlock( &cam_list_lock_pp );
if (!cpia) {
DBG("cpia_pp_detach failed to find cam_data in cam_list\n");
return;
}
cam = (struct pp_cam_entry *) cpia->lowlevel_data;
cpia_unregister_camera(cpia);
if(cam->open_count > 0)
cpia_pp_close(cam);
parport_unregister_device(cam->pdev);
cpia->lowlevel_data = NULL;
kfree(cam);
}
static void cpia_pp_attach (struct parport *port)
{
unsigned int i;
switch (parport_nr[0])
{
case PPCPIA_PARPORT_UNSPEC:
case PPCPIA_PARPORT_AUTO:
if (port->probe_info[0].class != PARPORT_CLASS_MEDIA ||
port->probe_info[0].cmdset == NULL ||
strncmp(port->probe_info[0].cmdset, "CPIA_1", 6) != 0)
return;
cpia_pp_register(port);
break;
default:
for (i = 0; i < PARPORT_MAX; ++i) {
if (port->number == parport_nr[i]) {
cpia_pp_register(port);
break;
}
}
break;
}
}
static struct parport_driver cpia_pp_driver = {
.name = "cpia_pp",
.attach = cpia_pp_attach,
.detach = cpia_pp_detach,
};
static int __init cpia_pp_init(void)
{
printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);
if(parport_nr[0] == PPCPIA_PARPORT_OFF) {
printk(" disabled\n");
return 0;
}
spin_lock_init( &cam_list_lock_pp );
if (parport_register_driver (&cpia_pp_driver)) {
LOG ("unable to register with parport\n");
return -EIO;
}
return 0;
}
static int __init cpia_init(void)
{
if (parport[0]) {
/* The user gave some parameters. Let's see what they were. */
if (!strncmp(parport[0], "auto", 4)) {
parport_nr[0] = PPCPIA_PARPORT_AUTO;
} else {
int n;
for (n = 0; n < PARPORT_MAX && parport[n]; n++) {
if (!strncmp(parport[n], "none", 4)) {
parport_nr[n] = PPCPIA_PARPORT_NONE;
} else {
char *ep;
unsigned long r = simple_strtoul(parport[n], &ep, 0);
if (ep != parport[n]) {
parport_nr[n] = r;
} else {
LOG("bad port specifier `%s'\n", parport[n]);
return -ENODEV;
}
}
}
}
}
return cpia_pp_init();
}
static void __exit cpia_cleanup(void)
{
parport_unregister_driver(&cpia_pp_driver);
return;
}
module_init(cpia_init);
module_exit(cpia_cleanup);

View File

@ -1,640 +0,0 @@
/*
* cpia_usb CPiA USB driver
*
* Supports CPiA based parallel port Video Camera's.
*
* Copyright (C) 1999 Jochen Scharrlach <Jochen.Scharrlach@schwaben.de>
* Copyright (C) 1999, 2000 Johannes Erdfelt <johannes@erdfelt.com>
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
/* #define _CPIA_DEBUG_ 1 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/usb.h>
#include "cpia.h"
#define USB_REQ_CPIA_GRAB_FRAME 0xC1
#define USB_REQ_CPIA_UPLOAD_FRAME 0xC2
#define WAIT_FOR_NEXT_FRAME 0
#define FORCE_FRAME_UPLOAD 1
#define FRAMES_PER_DESC 10
#define FRAME_SIZE_PER_DESC 960 /* Shouldn't be hardcoded */
#define CPIA_NUMSBUF 2
#define STREAM_BUF_SIZE (PAGE_SIZE * 4)
#define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2)
struct cpia_sbuf {
char *data;
struct urb *urb;
};
#define FRAMEBUF_LEN (CPIA_MAX_FRAME_SIZE+100)
enum framebuf_status {
FRAME_EMPTY,
FRAME_READING,
FRAME_READY,
FRAME_ERROR,
};
struct framebuf {
int length;
enum framebuf_status status;
u8 data[FRAMEBUF_LEN];
struct framebuf *next;
};
struct usb_cpia {
/* Device structure */
struct usb_device *dev;
unsigned char iface;
wait_queue_head_t wq_stream;
int cursbuf; /* Current receiving sbuf */
struct cpia_sbuf sbuf[CPIA_NUMSBUF]; /* Double buffering */
int streaming;
int open;
int present;
struct framebuf *buffers[3];
struct framebuf *curbuff, *workbuff;
};
static int cpia_usb_open(void *privdata);
static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata),
void *cbdata);
static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data);
static int cpia_usb_streamStart(void *privdata);
static int cpia_usb_streamStop(void *privdata);
static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock);
static int cpia_usb_close(void *privdata);
#define ABOUT "USB driver for Vision CPiA based cameras"
static struct cpia_camera_ops cpia_usb_ops = {
cpia_usb_open,
cpia_usb_registerCallback,
cpia_usb_transferCmd,
cpia_usb_streamStart,
cpia_usb_streamStop,
cpia_usb_streamRead,
cpia_usb_close,
0,
THIS_MODULE
};
static LIST_HEAD(cam_list);
static spinlock_t cam_list_lock_usb;
static void cpia_usb_complete(struct urb *urb)
{
int i;
char *cdata;
struct usb_cpia *ucpia;
if (!urb || !urb->context)
return;
ucpia = (struct usb_cpia *) urb->context;
if (!ucpia->dev || !ucpia->streaming || !ucpia->present || !ucpia->open)
return;
if (ucpia->workbuff->status == FRAME_EMPTY) {
ucpia->workbuff->status = FRAME_READING;
ucpia->workbuff->length = 0;
}
for (i = 0; i < urb->number_of_packets; i++) {
int n = urb->iso_frame_desc[i].actual_length;
int st = urb->iso_frame_desc[i].status;
cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
if (st)
printk(KERN_DEBUG "cpia data error: [%d] len=%d, status=%X\n", i, n, st);
if (FRAMEBUF_LEN < ucpia->workbuff->length + n) {
printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n", ucpia->workbuff->length, n);
return;
}
if (n) {
if ((ucpia->workbuff->length > 0) ||
(0x19 == cdata[0] && 0x68 == cdata[1])) {
memcpy(ucpia->workbuff->data + ucpia->workbuff->length, cdata, n);
ucpia->workbuff->length += n;
} else
DBG("Ignoring packet!\n");
} else {
if (ucpia->workbuff->length > 4 &&
0xff == ucpia->workbuff->data[ucpia->workbuff->length-1] &&
0xff == ucpia->workbuff->data[ucpia->workbuff->length-2] &&
0xff == ucpia->workbuff->data[ucpia->workbuff->length-3] &&
0xff == ucpia->workbuff->data[ucpia->workbuff->length-4]) {
ucpia->workbuff->status = FRAME_READY;
ucpia->curbuff = ucpia->workbuff;
ucpia->workbuff = ucpia->workbuff->next;
ucpia->workbuff->status = FRAME_EMPTY;
ucpia->workbuff->length = 0;
if (waitqueue_active(&ucpia->wq_stream))
wake_up_interruptible(&ucpia->wq_stream);
}
}
}
/* resubmit */
urb->dev = ucpia->dev;
if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __func__, i);
}
static int cpia_usb_open(void *privdata)
{
struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
struct urb *urb;
int ret, retval = 0, fx, err;
if (!ucpia)
return -EINVAL;
ucpia->sbuf[0].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
if (!ucpia->sbuf[0].data)
return -EINVAL;
ucpia->sbuf[1].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
if (!ucpia->sbuf[1].data) {
retval = -EINVAL;
goto error_0;
}
ret = usb_set_interface(ucpia->dev, ucpia->iface, 3);
if (ret < 0) {
printk(KERN_ERR "cpia_usb_open: usb_set_interface error (ret = %d)\n", ret);
retval = -EBUSY;
goto error_1;
}
ucpia->buffers[0]->status = FRAME_EMPTY;
ucpia->buffers[0]->length = 0;
ucpia->buffers[1]->status = FRAME_EMPTY;
ucpia->buffers[1]->length = 0;
ucpia->buffers[2]->status = FRAME_EMPTY;
ucpia->buffers[2]->length = 0;
ucpia->curbuff = ucpia->buffers[0];
ucpia->workbuff = ucpia->buffers[1];
/* We double buffer the Iso lists, and also know the polling
* interval is every frame (1 == (1 << (bInterval -1))).
*/
urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
if (!urb) {
printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 0\n");
retval = -ENOMEM;
goto error_1;
}
ucpia->sbuf[0].urb = urb;
urb->dev = ucpia->dev;
urb->context = ucpia;
urb->pipe = usb_rcvisocpipe(ucpia->dev, 1);
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = ucpia->sbuf[0].data;
urb->complete = cpia_usb_complete;
urb->number_of_packets = FRAMES_PER_DESC;
urb->interval = 1;
urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;
for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx;
urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC;
}
urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
if (!urb) {
printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 1\n");
retval = -ENOMEM;
goto error_urb0;
}
ucpia->sbuf[1].urb = urb;
urb->dev = ucpia->dev;
urb->context = ucpia;
urb->pipe = usb_rcvisocpipe(ucpia->dev, 1);
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = ucpia->sbuf[1].data;
urb->complete = cpia_usb_complete;
urb->number_of_packets = FRAMES_PER_DESC;
urb->interval = 1;
urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;
for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx;
urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC;
}
/* queue the ISO urbs, and resubmit in the completion handler */
err = usb_submit_urb(ucpia->sbuf[0].urb, GFP_KERNEL);
if (err) {
printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 0 ret %d\n",
err);
goto error_urb1;
}
err = usb_submit_urb(ucpia->sbuf[1].urb, GFP_KERNEL);
if (err) {
printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 1 ret %d\n",
err);
goto error_urb1;
}
ucpia->streaming = 1;
ucpia->open = 1;
return 0;
error_urb1: /* free urb 1 */
usb_free_urb(ucpia->sbuf[1].urb);
ucpia->sbuf[1].urb = NULL;
error_urb0: /* free urb 0 */
usb_free_urb(ucpia->sbuf[0].urb);
ucpia->sbuf[0].urb = NULL;
error_1:
kfree (ucpia->sbuf[1].data);
ucpia->sbuf[1].data = NULL;
error_0:
kfree (ucpia->sbuf[0].data);
ucpia->sbuf[0].data = NULL;
return retval;
}
//
// convenience functions
//
/****************************************************************************
*
* WritePacket
*
***************************************************************************/
static int WritePacket(struct usb_device *udev, const u8 *packet, u8 *buf, size_t size)
{
if (!packet)
return -EINVAL;
return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
packet[1] + (packet[0] << 8),
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
packet[2] + (packet[3] << 8),
packet[4] + (packet[5] << 8), buf, size, 1000);
}
/****************************************************************************
*
* ReadPacket
*
***************************************************************************/
static int ReadPacket(struct usb_device *udev, u8 *packet, u8 *buf, size_t size)
{
if (!packet || size <= 0)
return -EINVAL;
return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
packet[1] + (packet[0] << 8),
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
packet[2] + (packet[3] << 8),
packet[4] + (packet[5] << 8), buf, size, 1000);
}
static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data)
{
int err = 0;
int databytes;
struct usb_cpia *ucpia = (struct usb_cpia *)privdata;
struct usb_device *udev = ucpia->dev;
if (!udev) {
DBG("Internal driver error: udev is NULL\n");
return -EINVAL;
}
if (!command) {
DBG("Internal driver error: command is NULL\n");
return -EINVAL;
}
databytes = (((int)command[7])<<8) | command[6];
if (command[0] == DATA_IN) {
u8 buffer[8];
if (!data) {
DBG("Internal driver error: data is NULL\n");
return -EINVAL;
}
err = ReadPacket(udev, command, buffer, 8);
if (err < 0)
return err;
memcpy(data, buffer, databytes);
} else if(command[0] == DATA_OUT)
WritePacket(udev, command, data, databytes);
else {
DBG("Unexpected first byte of command: %x\n", command[0]);
err = -EINVAL;
}
return 0;
}
static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata),
void *cbdata)
{
return -ENODEV;
}
static int cpia_usb_streamStart(void *privdata)
{
return -ENODEV;
}
static int cpia_usb_streamStop(void *privdata)
{
return -ENODEV;
}
static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock)
{
struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
struct framebuf *mybuff;
if (!ucpia || !ucpia->present)
return -1;
if (ucpia->curbuff->status != FRAME_READY)
interruptible_sleep_on(&ucpia->wq_stream);
else
DBG("Frame already waiting!\n");
mybuff = ucpia->curbuff;
if (!mybuff)
return -1;
if (mybuff->status != FRAME_READY || mybuff->length < 4) {
DBG("Something went wrong!\n");
return -1;
}
memcpy(frame, mybuff->data, mybuff->length);
mybuff->status = FRAME_EMPTY;
/* DBG("read done, %d bytes, Header: %x/%x, Footer: %x%x%x%x\n", */
/* mybuff->length, frame[0], frame[1], */
/* frame[mybuff->length-4], frame[mybuff->length-3], */
/* frame[mybuff->length-2], frame[mybuff->length-1]); */
return mybuff->length;
}
static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
{
if (!ucpia->streaming)
return;
ucpia->streaming = 0;
/* Set packet size to 0 */
if (try) {
int ret;
ret = usb_set_interface(ucpia->dev, ucpia->iface, 0);
if (ret < 0) {
printk(KERN_ERR "usb_set_interface error (ret = %d)\n", ret);
return;
}
}
/* Unschedule all of the iso td's */
if (ucpia->sbuf[1].urb) {
usb_kill_urb(ucpia->sbuf[1].urb);
usb_free_urb(ucpia->sbuf[1].urb);
ucpia->sbuf[1].urb = NULL;
}
kfree(ucpia->sbuf[1].data);
ucpia->sbuf[1].data = NULL;
if (ucpia->sbuf[0].urb) {
usb_kill_urb(ucpia->sbuf[0].urb);
usb_free_urb(ucpia->sbuf[0].urb);
ucpia->sbuf[0].urb = NULL;
}
kfree(ucpia->sbuf[0].data);
ucpia->sbuf[0].data = NULL;
}
static int cpia_usb_close(void *privdata)
{
struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
if(!ucpia)
return -ENODEV;
ucpia->open = 0;
/* ucpia->present = 0 protects against trying to reset the
* alt setting if camera is physically disconnected while open */
cpia_usb_free_resources(ucpia, ucpia->present);
return 0;
}
/* Probing and initializing */
static int cpia_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_cpia *ucpia;
struct cam_data *cam;
int ret;
/* A multi-config CPiA camera? */
if (udev->descriptor.bNumConfigurations != 1)
return -ENODEV;
interface = intf->cur_altsetting;
printk(KERN_INFO "USB CPiA camera found\n");
ucpia = kzalloc(sizeof(*ucpia), GFP_KERNEL);
if (!ucpia) {
printk(KERN_ERR "couldn't kmalloc cpia struct\n");
return -ENOMEM;
}
ucpia->dev = udev;
ucpia->iface = interface->desc.bInterfaceNumber;
init_waitqueue_head(&ucpia->wq_stream);
ucpia->buffers[0] = vmalloc(sizeof(*ucpia->buffers[0]));
if (!ucpia->buffers[0]) {
printk(KERN_ERR "couldn't vmalloc frame buffer 0\n");
goto fail_alloc_0;
}
ucpia->buffers[1] = vmalloc(sizeof(*ucpia->buffers[1]));
if (!ucpia->buffers[1]) {
printk(KERN_ERR "couldn't vmalloc frame buffer 1\n");
goto fail_alloc_1;
}
ucpia->buffers[2] = vmalloc(sizeof(*ucpia->buffers[2]));
if (!ucpia->buffers[2]) {
printk(KERN_ERR "couldn't vmalloc frame buffer 2\n");
goto fail_alloc_2;
}
ucpia->buffers[0]->next = ucpia->buffers[1];
ucpia->buffers[1]->next = ucpia->buffers[2];
ucpia->buffers[2]->next = ucpia->buffers[0];
ret = usb_set_interface(udev, ucpia->iface, 0);
if (ret < 0) {
printk(KERN_ERR "cpia_probe: usb_set_interface error (ret = %d)\n", ret);
/* goto fail_all; */
}
/* Before register_camera, important */
ucpia->present = 1;
cam = cpia_register_camera(&cpia_usb_ops, ucpia);
if (!cam) {
LOG("failed to cpia_register_camera\n");
goto fail_all;
}
spin_lock( &cam_list_lock_usb );
list_add( &cam->cam_data_list, &cam_list );
spin_unlock( &cam_list_lock_usb );
usb_set_intfdata(intf, cam);
return 0;
fail_all:
vfree(ucpia->buffers[2]);
ucpia->buffers[2] = NULL;
fail_alloc_2:
vfree(ucpia->buffers[1]);
ucpia->buffers[1] = NULL;
fail_alloc_1:
vfree(ucpia->buffers[0]);
ucpia->buffers[0] = NULL;
fail_alloc_0:
kfree(ucpia);
return -EIO;
}
static void cpia_disconnect(struct usb_interface *intf);
static struct usb_device_id cpia_id_table [] = {
{ USB_DEVICE(0x0553, 0x0002) },
{ USB_DEVICE(0x0813, 0x0001) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cpia_id_table);
MODULE_LICENSE("GPL");
static struct usb_driver cpia_driver = {
.name = "cpia",
.probe = cpia_probe,
.disconnect = cpia_disconnect,
.id_table = cpia_id_table,
};
static void cpia_disconnect(struct usb_interface *intf)
{
struct cam_data *cam = usb_get_intfdata(intf);
struct usb_cpia *ucpia;
usb_set_intfdata(intf, NULL);
if (!cam)
return;
ucpia = (struct usb_cpia *) cam->lowlevel_data;
spin_lock( &cam_list_lock_usb );
list_del(&cam->cam_data_list);
spin_unlock( &cam_list_lock_usb );
ucpia->present = 0;
cpia_unregister_camera(cam);
if(ucpia->open)
cpia_usb_close(cam->lowlevel_data);
ucpia->curbuff->status = FRAME_ERROR;
if (waitqueue_active(&ucpia->wq_stream))
wake_up_interruptible(&ucpia->wq_stream);
ucpia->curbuff = ucpia->workbuff = NULL;
vfree(ucpia->buffers[2]);
ucpia->buffers[2] = NULL;
vfree(ucpia->buffers[1]);
ucpia->buffers[1] = NULL;
vfree(ucpia->buffers[0]);
ucpia->buffers[0] = NULL;
cam->lowlevel_data = NULL;
kfree(ucpia);
}
static int __init usb_cpia_init(void)
{
printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
CPIA_USB_MAJ_VER,CPIA_USB_MIN_VER,CPIA_USB_PATCH_VER);
spin_lock_init(&cam_list_lock_usb);
return usb_register(&cpia_driver);
}
static void __exit usb_cpia_cleanup(void)
{
usb_deregister(&cpia_driver);
}
module_init (usb_cpia_init);
module_exit (usb_cpia_cleanup);

View File

@ -1,7 +0,0 @@
config VIDEO_STRADIS
tristate "Stradis 4:2:2 MPEG-2 video driver (DEPRECATED)"
depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && VIRT_TO_BUS && BKL
help
Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video
driver for PCI. There is a product page at
<http://www.stradis.com/>.

View File

@ -1,3 +0,0 @@
obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
EXTRA_CFLAGS += -Idrivers/media/video

View File

@ -1,6 +0,0 @@
This is an obsolete driver for ancient stradis hardware.
We couldn't find anyone with this hardware in order to port it to use V4L2.
If nobody take care on it, the driver will be removed for 2.6.38.
Please send patches to linux-media@vger.kernel.org

File diff suppressed because it is too large Load Diff