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>tirimbino
parent
71bb2876a3
commit
39c3d48845
@ -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/ |
@ -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). |
@ -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
|
@ -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
@ -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 */ |
@ -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); |
@ -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); |
||||
|
@ -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/>. |
@ -1,3 +0,0 @@ |
||||
obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/video
|
@ -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
Loading…
Reference in new issue