lkml.org 
[lkml]   [2003]   [Mar]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectPATCH: cpia -maintainers update
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.5.65/drivers/media/video/cpia.c linux-2.5.65-ac2/drivers/media/video/cpia.c
--- linux-2.5.65/drivers/media/video/cpia.c 2003-02-10 18:38:46.000000000 +0000
+++ linux-2.5.65-ac2/drivers/media/video/cpia.c 2003-03-06 23:46:22.000000000 +0000
@@ -23,7 +23,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

-/* #define _CPIA_DEBUG_ define for verbose debug output */
+/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
+/* #define _CPIA_DEBUG_ 1 */
+
#include <linux/config.h>

#include <linux/module.h>
@@ -1796,7 +1798,7 @@

retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
if (retval)
- LOG("%x - failed\n", command);
+ DBG("%x - failed\n", command);

return retval;
}
@@ -2174,7 +2176,7 @@
}
if (ll == 1) {
if (*ibuf != EOL) {
- LOG("EOL not found giving up after %d/%d"
+ DBG("EOL not found giving up after %d/%d"
" bytes\n", origsize-size, origsize);
return -1;
}
@@ -3158,7 +3160,8 @@

static void put_cam(struct cpia_camera_ops* ops)
{
- module_put(ops->owner);
+ if (ops->owner)
+ module_put(ops->owner);
}

/* ------------------------- V4L interface --------------------- */
@@ -3173,16 +3176,15 @@
return -ENODEV;
}

+ if (cam->open_count > 0) {
+ DBG("Camera already open\n");
+ return -EBUSY;
+ }
+
if (!try_module_get(cam->ops->owner))
return -ENODEV;

down(&cam->busy_lock);
- err = -EBUSY;
- if (cam->open_count > 0) {
- DBG("Camera already open\n");
- goto oops;
- }
-
err = -ENOMEM;
if (!cam->raw_image) {
cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE);
@@ -3206,10 +3208,11 @@
cam->ops->close(cam->lowlevel_data);
goto oops;
}
-
- if(signal_pending(current))
- return -EINTR;

+ err = -EINTR;
+ if(signal_pending(current))
+ goto oops;
+
/* Set ownership of /proc/cpia/videoX to current user */
if(cam->proc_entry)
cam->proc_entry->uid = current->uid;
@@ -3451,6 +3454,14 @@
cam->params.colourParams.contrast = 80;
}

+ /* Adjust flicker control if necessary */
+ if(cam->params.flickerControl.allowableOverExposure < 0)
+ cam->params.flickerControl.allowableOverExposure =
+ -find_over_exposure(cam->params.colourParams.brightness);
+ if(cam->params.flickerControl.flickerMode != 0)
+ cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
+
+
/* queue command to update camera */
cam->cmd_queue |= COMMAND_SETCOLOURPARAMS;
up(&cam->param_lock);
@@ -3600,7 +3611,7 @@
{
int *frame = arg;

- //DBG("VIDIOCSYNC: %d\n", frame);
+ //DBG("VIDIOCSYNC: %d\n", *frame);

if (*frame<0 || *frame >= FRAME_NUM) {
retval = -EINVAL;
@@ -3628,52 +3639,53 @@
}

case VIDIOCGCAPTURE:
+ {
+ struct video_capture *vc = arg;
+
DBG("VIDIOCGCAPTURE\n");
- if (copy_to_user(arg, &cam->vc, sizeof(struct video_capture)))
- retval = -EFAULT;
+
+ *vc = cam->vc;
+
break;
+ }

case VIDIOCSCAPTURE:
{
- struct video_capture vc;
+ struct video_capture *vc = arg;

DBG("VIDIOCSCAPTURE\n");
- if (copy_from_user(&vc, arg, sizeof(vc))) {
- retval = -EFAULT;
- break;
- }

- if (vc.decimation != 0) { /* How should this be used? */
+ if (vc->decimation != 0) { /* How should this be used? */
retval = -EINVAL;
break;
}
- if (vc.flags != 0) { /* Even/odd grab not supported */
+ if (vc->flags != 0) { /* Even/odd grab not supported */
retval = -EINVAL;
break;
}

/* Clip to the resolution we can set for the ROI
(every 8 columns and 4 rows) */
- vc.x = vc.x & ~(__u32)7;
- vc.y = vc.y & ~(__u32)3;
- vc.width = vc.width & ~(__u32)7;
- vc.height = vc.height & ~(__u32)3;
-
- if(vc.width == 0 || vc.height == 0 ||
- vc.x + vc.width > cam->vw.width ||
- vc.y + vc.height > cam->vw.height) {
+ vc->x = vc->x & ~(__u32)7;
+ vc->y = vc->y & ~(__u32)3;
+ vc->width = vc->width & ~(__u32)7;
+ vc->height = vc->height & ~(__u32)3;
+
+ if(vc->width == 0 || vc->height == 0 ||
+ vc->x + vc->width > cam->vw.width ||
+ vc->y + vc->height > cam->vw.height) {
retval = -EINVAL;
break;
}

- DBG("%d,%d/%dx%d\n", vc.x,vc.y,vc.width, vc.height);
+ DBG("%d,%d/%dx%d\n", vc->x,vc->y,vc->width, vc->height);

down(&cam->param_lock);

- cam->vc.x = vc.x;
- cam->vc.y = vc.y;
- cam->vc.width = vc.width;
- cam->vc.height = vc.height;
+ cam->vc.x = vc->x;
+ cam->vc.y = vc->y;
+ cam->vc.width = vc->width;
+ cam->vc.height = vc->height;

set_vw_size(cam);
cam->cmd_queue |= COMMAND_SETFORMAT;
@@ -3688,16 +3700,20 @@

case VIDIOCGUNIT:
{
- struct video_unit vu;
- vu.video = cam->vdev.minor;
- vu.vbi = VIDEO_NO_UNIT;
- vu.radio = VIDEO_NO_UNIT;
- vu.audio = VIDEO_NO_UNIT;
- vu.teletext = VIDEO_NO_UNIT;
+ struct video_unit *vu = arg;
+
+ DBG("VIDIOCGUNIT\n");
+
+ vu->video = cam->vdev.minor;
+ vu->vbi = VIDEO_NO_UNIT;
+ vu->radio = VIDEO_NO_UNIT;
+ vu->audio = VIDEO_NO_UNIT;
+ vu->teletext = VIDEO_NO_UNIT;
+
break;
}
-

+
/* pointless to implement overlay with this camera */
case VIDIOCCAPTURE:
case VIDIOCGFBUF:
@@ -3728,12 +3744,13 @@
return video_usercopy(inode, file, cmd, arg, cpia_do_ioctl);
}

+
/* FIXME */
static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
{
struct video_device *dev = file->private_data;
unsigned long start = vma->vm_start;
- unsigned long size = vma->vm_end-vma->vm_start;
+ unsigned long size = vma->vm_end - vma->vm_start;
unsigned long page, pos;
struct cam_data *cam = dev->priv;
int retval;
@@ -3956,9 +3973,6 @@
printk(KERN_DEBUG "video_register_device failed\n");
return NULL;
}
-#ifdef CONFIG_PROC_FS
- create_proc_cpia_cam(camera);
-#endif

/* get version information from camera: open/reset/close */

@@ -3975,6 +3989,10 @@
/* close cpia */
camera->ops->close(camera->lowlevel_data);

+#ifdef CONFIG_PROC_FS
+ create_proc_cpia_cam(camera);
+#endif
+
printk(KERN_INFO " CPiA Version: %d.%02d (%d.%d)\n",
camera->params.version.firmwareVersion,
camera->params.version.firmwareRevision,
@@ -3997,6 +4015,7 @@
DBG("unregistering video\n");
video_unregister_device(&cam->vdev);
if (cam->open_count) {
+ put_cam(cam->ops);
DBG("camera open -- setting ops to NULL\n");
cam->ops = NULL;
}
@@ -4019,9 +4038,6 @@
proc_cpia_create();
#endif

-#ifdef CONFIG_VIDEO_CPIA_PP
- cpia_pp_init();
-#endif
#ifdef CONFIG_KMOD
#ifdef CONFIG_VIDEO_CPIA_PP_MODULE
request_module("cpia_pp");
@@ -4031,6 +4047,10 @@
request_module("cpia_usb");
#endif
#endif /* CONFIG_KMOD */
+
+#ifdef CONFIG_VIDEO_CPIA_PP
+ cpia_pp_init();
+#endif
#ifdef CONFIG_VIDEO_CPIA_USB
cpia_usb_init();
#endif
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.5.65/drivers/media/video/cpia.h linux-2.5.65-ac2/drivers/media/video/cpia.h
--- linux-2.5.65/drivers/media/video/cpia.h 2003-02-10 18:38:53.000000000 +0000
+++ linux-2.5.65-ac2/drivers/media/video/cpia.h 2003-03-06 23:46:22.000000000 +0000
@@ -27,12 +27,16 @@
*/

#define CPIA_MAJ_VER 1
-#define CPIA_MIN_VER 2
-#define CPIA_PATCH_VER 2
+#define CPIA_MIN_VER 2
+#define CPIA_PATCH_VER 3

-#define CPIA_PP_MAJ_VER 1
-#define CPIA_PP_MIN_VER 2
-#define CPIA_PP_PATCH_VER 2
+#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 */
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.5.65/drivers/media/video/cpia_pp.c linux-2.5.65-ac2/drivers/media/video/cpia_pp.c
--- linux-2.5.65/drivers/media/video/cpia_pp.c 2003-02-10 18:37:56.000000000 +0000
+++ linux-2.5.65-ac2/drivers/media/video/cpia_pp.c 2003-03-06 23:46:22.000000000 +0000
@@ -22,6 +22,9 @@
* 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/config.h>
#include <linux/version.h>

@@ -34,6 +37,7 @@
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/smp_lock.h>
+#include <linux/sched.h>

#include <linux/kmod.h>

@@ -49,68 +53,10 @@
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"

-/* IEEE 1284 Compatiblity Mode signal names */
-#define nStrobe PARPORT_CONTROL_STROBE /* inverted */
-#define nAutoFd PARPORT_CONTROL_AUTOFD /* inverted */
-#define nInit PARPORT_CONTROL_INIT
-#define nSelectIn PARPORT_CONTROL_SELECT
-#define IntrEnable PARPORT_CONTROL_INTEN /* normally zero for no IRQ */
-#define DirBit PARPORT_CONTROL_DIRECTION /* 0 = Forward, 1 = Reverse */
-
-#define nFault PARPORT_STATUS_ERROR
-#define Select PARPORT_STATUS_SELECT
-#define PError PARPORT_STATUS_PAPEROUT
-#define nAck PARPORT_STATUS_ACK
-#define Busy PARPORT_STATUS_BUSY /* inverted */
-
-/* some more */
-#define HostClk nStrobe
-#define HostAck nAutoFd
-#define nReverseRequest nInit
-#define Active_1284 nSelectIn
-#define nPeriphRequest nFault
-#define XFlag Select
-#define nAckReverse PError
-#define PeriphClk nAck
-#define PeriphAck Busy
-
-/* these can be used to correct for the inversion on some bits */
-#define STATUS_INVERSION_MASK (Busy)
-#define CONTROL_INVERSION_MASK (nStrobe|nAutoFd|nSelectIn)
-
-#define ECR_empty 0x01
-#define ECR_full 0x02
-#define ECR_serviceIntr 0x04
-#define ECR_dmaEn 0x08
-#define ECR_nErrIntrEn 0x10
-
-#define ECR_mode_mask 0xE0
-#define ECR_SPP_mode 0x00
-#define ECR_PS2_mode 0x20
-#define ECR_FIFO_mode 0x40
-#define ECR_ECP_mode 0x60
-
-#define ECP_FIFO_SIZE 16
-#define DMA_BUFFER_SIZE PAGE_SIZE
- /* for 16bit DMA make sure DMA_BUFFER_SIZE is 16 bit aligned */
-#define PARPORT_CHUNK_SIZE PAGE_SIZE/* >=2.3.x */
- /* we read this many bytes at once */
-
-#define GetECRMasked(port,mask) (parport_read_econtrol(port) & (mask))
-#define GetStatus(port) ((parport_read_status(port)^STATUS_INVERSION_MASK)&(0xf8))
-#define SetStatus(port,val) parport_write_status(port,(val)^STATUS_INVERSION_MASK)
-#define GetControl(port) ((parport_read_control(port)^CONTROL_INVERSION_MASK)&(0x3f))
-#define SetControl(port,val) parport_write_control(port,(val)^CONTROL_INVERSION_MASK)
-
-#define GetStatusMasked(port,mask) (GetStatus(port) & (mask))
-#define GetControlMasked(port,mask) (GetControl(port) & (mask))
-#define SetControlMasked(port,mask) SetControl(port,GetControl(port) | (mask));
-#define ClearControlMasked(port,mask) SetControl(port,GetControl(port)&~(mask));
-#define FrobControlBit(port,mask,value) SetControl(port,(GetControl(port)&~(mask))|((value)&(mask)));
+#define ABOUT "Parallel port driver for Vision CPiA based cameras"

-#define PACKET_LENGTH 8
+#define PACKET_LENGTH 8

/* Magic numbers for defining port-device mappings */
#define PPCPIA_PARPORT_UNSPEC -4
@@ -162,30 +108,7 @@
};

static LIST_HEAD(cam_list);
-static spinlock_t cam_list_lock_pp = SPIN_LOCK_UNLOCKED;
-
-#ifdef _CPIA_DEBUG_
-#define DEB_PORT(port) { \
-u8 controll = GetControl(port); \
-u8 statusss = GetStatus(port); \
-DBG("nsel %c per %c naut %c nstrob %c nak %c busy %c nfaul %c sel %c init %c dir %c\n",\
-((controll & nSelectIn) ? 'U' : 'D'), \
-((statusss & PError) ? 'U' : 'D'), \
-((controll & nAutoFd) ? 'U' : 'D'), \
-((controll & nStrobe) ? 'U' : 'D'), \
-((statusss & nAck) ? 'U' : 'D'), \
-((statusss & Busy) ? 'U' : 'D'), \
-((statusss & nFault) ? 'U' : 'D'), \
-((statusss & Select) ? 'U' : 'D'), \
-((controll & nInit) ? 'U' : 'D'), \
-((controll & DirBit) ? 'R' : 'F') \
-); }
-#else
-#define DEB_PORT(port) {}
-#endif
-
-#define WHILE_OUT_TIMEOUT (HZ/10)
-#define DMA_TIMEOUT 10*HZ
+static spinlock_t cam_list_lock_pp;

/* FIXME */
static void cpia_parport_enable_irq( struct parport *port ) {
@@ -200,6 +123,205 @@
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
+
+
+/****************************************************************************
+ *
+ * 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)) {
+ port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+ DBG("%s: No more nibble data (%d bytes)\n",
+ port->name, i/2);
+
+ /* Go to reverse idle phase. */
+ parport_frob_control (port,
+ PARPORT_CONTROL_AUTOFD,
+ PARPORT_CONTROL_AUTOFD);
+ port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+ 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 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;
+ }
+
+ i /= 2; /* i is now in bytes */
+
+ if (i == len) {
+ /* Read the last nibble without checking data avail. */
+ port = port->physport;
+ if (parport_read_status (port) & PARPORT_STATUS_ERROR)
+ port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+ else
+ port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+ }
+
+ return i;
+}
+
+/* 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
@@ -219,20 +341,25 @@
{
int retry;

- /* After some commands the camera needs extra time before
- * it will respond again, so we try up to 3 times */
- for(retry=0; retry<3; ++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 == 3) {
- DBG("Unable to negotiate ECP mode\n");
+ if(retry == 4) {
+ DBG("Unable to negotiate IEEE1284 ECP Download mode\n");
return -1;
}
return 0;
}
-
/****************************************************************************
*
* ReverseSetup
@@ -241,24 +368,35 @@
static int ReverseSetup(struct pp_cam_entry *cam, int extensibility)
{
int retry;
- int mode = IEEE1284_MODE_ECP;
- if(extensibility) mode = 8|3|IEEE1284_EXT_LINK;
+ 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;
+ }

- /* After some commands the camera needs extra time before
- * it will respond again, so we try up to 3 times */
- for(retry=0; retry<3; ++retry) {
+ 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 == 3) {
+ if(retry == 4) {
if(extensibility)
- DBG("Unable to negotiate extensibility mode\n");
+ DBG("Unable to negotiate upload extensibility mode\n");
else
- DBG("Unable to negotiate ECP mode\n");
+ DBG("Unable to negotiate upload mode\n");
return -1;
}
- if(extensibility) cam->port->ieee1284.mode = IEEE1284_MODE_ECP;
+ if(extensibility) cam->port->ieee1284.mode = upload_mode;
return 0;
}

@@ -296,14 +434,21 @@
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;
}
- if(parport_read(cam->port, packet, size) != size) {
- retval = -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;
@@ -347,11 +492,29 @@
* 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;
+ int i, endseen, block_size, new_bytes;

if(cam == NULL) {
DBG("Internal driver error: cam is NULL\n");
@@ -380,27 +543,36 @@
return -EIO;
}
}
- read_bytes = parport_read(cam->port, buffer, CPIA_MAX_IMAGE_SIZE );
-
- EndTransferMode(cam);
- DBG("read %d bytes\n", read_bytes);
- if( read_bytes<0) return -EIO;
endseen = 0;
- for( i=0; i<read_bytes && endseen<4; i++ ) {
- if( *buffer==EOI ) {
- endseen++;
- } else {
- endseen=0;
- }
- buffer++;
- }
- if( endseen>3 ) {
- cam->image_complete=1;
- DBG("endseen at %d bytes\n", i);
- }
+ 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
@@ -530,9 +702,8 @@
struct pp_cam_entry *cam;
struct cam_data *cpia;

- if (!(port->modes & PARPORT_MODE_ECP) &&
- !(port->modes & PARPORT_MODE_TRISTATE)) {
- LOG("port is not ECP capable\n");
+ if (!(port->modes & PARPORT_MODE_PCSPP)) {
+ LOG("port is not supported by CPiA driver\n");
return -ENXIO;
}

@@ -575,29 +746,33 @@
static void cpia_pp_detach (struct parport *port)
{
struct list_head *tmp;
- struct cam_data *cpia;
+ 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 = cpia->lowlevel_data;
+ cam = (struct pp_cam_entry *) cpia->lowlevel_data;
if (cam && cam->port->number == port->number) {
list_del(&cpia->cam_data_list);
- cpia_unregister_camera(cpia);
-
- if(cam->open_count > 0) {
- cpia_pp_close(cam);
- }
-
- parport_unregister_device(cam->pdev);
-
- kfree(cam);
- cpia->lowlevel_data = NULL;
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)
@@ -645,11 +820,12 @@
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;
}

diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.5.65/drivers/media/video/cpia_usb.c linux-2.5.65-ac2/drivers/media/video/cpia_usb.c
--- linux-2.5.65/drivers/media/video/cpia_usb.c 2003-02-10 18:37:56.000000000 +0000
+++ linux-2.5.65-ac2/drivers/media/video/cpia_usb.c 2003-03-06 23:46:22.000000000 +0000
@@ -21,11 +21,13 @@
* 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/sched.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
@@ -105,7 +107,7 @@
};

static LIST_HEAD(cam_list);
-static spinlock_t cam_list_lock_usb = SPIN_LOCK_UNLOCKED;
+static spinlock_t cam_list_lock_usb;

static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
{
@@ -464,12 +466,14 @@
{
struct usb_cpia *ucpia = (struct usb_cpia *) privdata;

- ucpia->open = 0;
+ if(!ucpia)
+ return -ENODEV;

- cpia_usb_free_resources(ucpia, 1);
+ ucpia->open = 0;

- if (!ucpia->present)
- kfree(ucpia);
+ /* 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;
}
@@ -565,7 +569,7 @@
vfree(ucpia->buffers[0]);
ucpia->buffers[0] = NULL;
fail_alloc_0:
-
+ kfree(ucpia);
return -EIO;
}

@@ -588,9 +592,6 @@
.id_table = cpia_id_table,
};

-/* don't use dev, it may be NULL! (see usb_cpia_cleanup) */
-/* _disconnect from usb_cpia_cleanup is not necessary since usb_deregister */
-/* will do it for us as well as passing a udev structure - jerdfelt */
static void cpia_disconnect(struct usb_interface *intf)
{
struct cam_data *cam = usb_get_intfdata(intf);
@@ -606,12 +607,11 @@
list_del(&cam->cam_data_list);
spin_unlock( &cam_list_lock_usb );

- /* Don't even try to reset the altsetting if we're disconnected */
- cpia_usb_free_resources(ucpia, 0);
-
ucpia->present = 0;

cpia_unregister_camera(cam);
+ if(ucpia->open)
+ cpia_usb_close(cam->lowlevel_data);

ucpia->curbuff->status = FRAME_ERROR;

@@ -639,29 +639,25 @@
ucpia->buffers[0] = NULL;
}

- if (!ucpia->open) {
- kfree(ucpia);
- cam->lowlevel_data = 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)
{
-/*
- struct cam_data *cam;
-
- while ((cam = cam_list) != NULL)
- cpia_disconnect(NULL, cam);
-*/
-
usb_deregister(&cpia_driver);
}


module_init (usb_cpia_init);
module_exit (usb_cpia_cleanup);
+
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 13:34    [W:0.054 / U:0.476 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site