Commit 4afc05e5 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] cpia -maintainers update

parent 765af494
...@@ -23,7 +23,9 @@ ...@@ -23,7 +23,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -1796,7 +1798,7 @@ static int do_command_extended(struct cam_data *cam, u16 command, ...@@ -1796,7 +1798,7 @@ static int do_command_extended(struct cam_data *cam, u16 command,
retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data); retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
if (retval) if (retval)
LOG("%x - failed\n", command); DBG("%x - failed\n", command);
return retval; return retval;
} }
...@@ -2174,7 +2176,7 @@ static int parse_picture(struct cam_data *cam, int size) ...@@ -2174,7 +2176,7 @@ static int parse_picture(struct cam_data *cam, int size)
} }
if (ll == 1) { if (ll == 1) {
if (*ibuf != EOL) { 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); " bytes\n", origsize-size, origsize);
return -1; return -1;
} }
...@@ -3158,7 +3160,8 @@ static int reset_camera(struct cam_data *cam) ...@@ -3158,7 +3160,8 @@ static int reset_camera(struct cam_data *cam)
static void put_cam(struct cpia_camera_ops* ops) static void put_cam(struct cpia_camera_ops* ops)
{ {
module_put(ops->owner); if (ops->owner)
module_put(ops->owner);
} }
/* ------------------------- V4L interface --------------------- */ /* ------------------------- V4L interface --------------------- */
...@@ -3173,16 +3176,15 @@ static int cpia_open(struct inode *inode, struct file *file) ...@@ -3173,16 +3176,15 @@ static int cpia_open(struct inode *inode, struct file *file)
return -ENODEV; return -ENODEV;
} }
if (cam->open_count > 0) {
DBG("Camera already open\n");
return -EBUSY;
}
if (!try_module_get(cam->ops->owner)) if (!try_module_get(cam->ops->owner))
return -ENODEV; return -ENODEV;
down(&cam->busy_lock); down(&cam->busy_lock);
err = -EBUSY;
if (cam->open_count > 0) {
DBG("Camera already open\n");
goto oops;
}
err = -ENOMEM; err = -ENOMEM;
if (!cam->raw_image) { if (!cam->raw_image) {
cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE); cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE);
...@@ -3206,10 +3208,11 @@ static int cpia_open(struct inode *inode, struct file *file) ...@@ -3206,10 +3208,11 @@ static int cpia_open(struct inode *inode, struct file *file)
cam->ops->close(cam->lowlevel_data); cam->ops->close(cam->lowlevel_data);
goto oops; 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 */ /* Set ownership of /proc/cpia/videoX to current user */
if(cam->proc_entry) if(cam->proc_entry)
cam->proc_entry->uid = current->uid; cam->proc_entry->uid = current->uid;
...@@ -3451,6 +3454,14 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, ...@@ -3451,6 +3454,14 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
cam->params.colourParams.contrast = 80; 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 */ /* queue command to update camera */
cam->cmd_queue |= COMMAND_SETCOLOURPARAMS; cam->cmd_queue |= COMMAND_SETCOLOURPARAMS;
up(&cam->param_lock); up(&cam->param_lock);
...@@ -3600,7 +3611,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, ...@@ -3600,7 +3611,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
{ {
int *frame = arg; int *frame = arg;
//DBG("VIDIOCSYNC: %d\n", frame); //DBG("VIDIOCSYNC: %d\n", *frame);
if (*frame<0 || *frame >= FRAME_NUM) { if (*frame<0 || *frame >= FRAME_NUM) {
retval = -EINVAL; retval = -EINVAL;
...@@ -3628,52 +3639,53 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, ...@@ -3628,52 +3639,53 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
} }
case VIDIOCGCAPTURE: case VIDIOCGCAPTURE:
{
struct video_capture *vc = arg;
DBG("VIDIOCGCAPTURE\n"); DBG("VIDIOCGCAPTURE\n");
if (copy_to_user(arg, &cam->vc, sizeof(struct video_capture)))
retval = -EFAULT; *vc = cam->vc;
break; break;
}
case VIDIOCSCAPTURE: case VIDIOCSCAPTURE:
{ {
struct video_capture vc; struct video_capture *vc = arg;
DBG("VIDIOCSCAPTURE\n"); 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; retval = -EINVAL;
break; break;
} }
if (vc.flags != 0) { /* Even/odd grab not supported */ if (vc->flags != 0) { /* Even/odd grab not supported */
retval = -EINVAL; retval = -EINVAL;
break; break;
} }
/* Clip to the resolution we can set for the ROI /* Clip to the resolution we can set for the ROI
(every 8 columns and 4 rows) */ (every 8 columns and 4 rows) */
vc.x = vc.x & ~(__u32)7; vc->x = vc->x & ~(__u32)7;
vc.y = vc.y & ~(__u32)3; vc->y = vc->y & ~(__u32)3;
vc.width = vc.width & ~(__u32)7; vc->width = vc->width & ~(__u32)7;
vc.height = vc.height & ~(__u32)3; vc->height = vc->height & ~(__u32)3;
if(vc.width == 0 || vc.height == 0 || if(vc->width == 0 || vc->height == 0 ||
vc.x + vc.width > cam->vw.width || vc->x + vc->width > cam->vw.width ||
vc.y + vc.height > cam->vw.height) { vc->y + vc->height > cam->vw.height) {
retval = -EINVAL; retval = -EINVAL;
break; 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); down(&cam->param_lock);
cam->vc.x = vc.x; cam->vc.x = vc->x;
cam->vc.y = vc.y; cam->vc.y = vc->y;
cam->vc.width = vc.width; cam->vc.width = vc->width;
cam->vc.height = vc.height; cam->vc.height = vc->height;
set_vw_size(cam); set_vw_size(cam);
cam->cmd_queue |= COMMAND_SETFORMAT; cam->cmd_queue |= COMMAND_SETFORMAT;
...@@ -3688,16 +3700,20 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, ...@@ -3688,16 +3700,20 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
case VIDIOCGUNIT: case VIDIOCGUNIT:
{ {
struct video_unit vu; struct video_unit *vu = arg;
vu.video = cam->vdev.minor;
vu.vbi = VIDEO_NO_UNIT; DBG("VIDIOCGUNIT\n");
vu.radio = VIDEO_NO_UNIT;
vu.audio = VIDEO_NO_UNIT; vu->video = cam->vdev.minor;
vu.teletext = VIDEO_NO_UNIT; vu->vbi = VIDEO_NO_UNIT;
vu->radio = VIDEO_NO_UNIT;
vu->audio = VIDEO_NO_UNIT;
vu->teletext = VIDEO_NO_UNIT;
break; break;
} }
/* pointless to implement overlay with this camera */ /* pointless to implement overlay with this camera */
case VIDIOCCAPTURE: case VIDIOCCAPTURE:
case VIDIOCGFBUF: case VIDIOCGFBUF:
...@@ -3728,12 +3744,13 @@ static int cpia_ioctl(struct inode *inode, struct file *file, ...@@ -3728,12 +3744,13 @@ static int cpia_ioctl(struct inode *inode, struct file *file,
return video_usercopy(inode, file, cmd, arg, cpia_do_ioctl); return video_usercopy(inode, file, cmd, arg, cpia_do_ioctl);
} }
/* FIXME */ /* FIXME */
static int cpia_mmap(struct file *file, struct vm_area_struct *vma) static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct video_device *dev = file->private_data; struct video_device *dev = file->private_data;
unsigned long start = vma->vm_start; 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; unsigned long page, pos;
struct cam_data *cam = dev->priv; struct cam_data *cam = dev->priv;
int retval; int retval;
...@@ -3956,9 +3973,6 @@ struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowleve ...@@ -3956,9 +3973,6 @@ struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowleve
printk(KERN_DEBUG "video_register_device failed\n"); printk(KERN_DEBUG "video_register_device failed\n");
return NULL; return NULL;
} }
#ifdef CONFIG_PROC_FS
create_proc_cpia_cam(camera);
#endif
/* get version information from camera: open/reset/close */ /* get version information from camera: open/reset/close */
...@@ -3975,6 +3989,10 @@ struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowleve ...@@ -3975,6 +3989,10 @@ struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowleve
/* close cpia */ /* close cpia */
camera->ops->close(camera->lowlevel_data); 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", printk(KERN_INFO " CPiA Version: %d.%02d (%d.%d)\n",
camera->params.version.firmwareVersion, camera->params.version.firmwareVersion,
camera->params.version.firmwareRevision, camera->params.version.firmwareRevision,
...@@ -3997,6 +4015,7 @@ void cpia_unregister_camera(struct cam_data *cam) ...@@ -3997,6 +4015,7 @@ void cpia_unregister_camera(struct cam_data *cam)
DBG("unregistering video\n"); DBG("unregistering video\n");
video_unregister_device(&cam->vdev); video_unregister_device(&cam->vdev);
if (cam->open_count) { if (cam->open_count) {
put_cam(cam->ops);
DBG("camera open -- setting ops to NULL\n"); DBG("camera open -- setting ops to NULL\n");
cam->ops = NULL; cam->ops = NULL;
} }
...@@ -4019,9 +4038,6 @@ static int __init cpia_init(void) ...@@ -4019,9 +4038,6 @@ static int __init cpia_init(void)
proc_cpia_create(); proc_cpia_create();
#endif #endif
#ifdef CONFIG_VIDEO_CPIA_PP
cpia_pp_init();
#endif
#ifdef CONFIG_KMOD #ifdef CONFIG_KMOD
#ifdef CONFIG_VIDEO_CPIA_PP_MODULE #ifdef CONFIG_VIDEO_CPIA_PP_MODULE
request_module("cpia_pp"); request_module("cpia_pp");
...@@ -4031,6 +4047,10 @@ static int __init cpia_init(void) ...@@ -4031,6 +4047,10 @@ static int __init cpia_init(void)
request_module("cpia_usb"); request_module("cpia_usb");
#endif #endif
#endif /* CONFIG_KMOD */ #endif /* CONFIG_KMOD */
#ifdef CONFIG_VIDEO_CPIA_PP
cpia_pp_init();
#endif
#ifdef CONFIG_VIDEO_CPIA_USB #ifdef CONFIG_VIDEO_CPIA_USB
cpia_usb_init(); cpia_usb_init();
#endif #endif
......
...@@ -27,12 +27,16 @@ ...@@ -27,12 +27,16 @@
*/ */
#define CPIA_MAJ_VER 1 #define CPIA_MAJ_VER 1
#define CPIA_MIN_VER 2 #define CPIA_MIN_VER 2
#define CPIA_PATCH_VER 2 #define CPIA_PATCH_VER 3
#define CPIA_PP_MAJ_VER 1 #define CPIA_PP_MAJ_VER CPIA_MAJ_VER
#define CPIA_PP_MIN_VER 2 #define CPIA_PP_MIN_VER CPIA_MIN_VER
#define CPIA_PP_PATCH_VER 2 #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_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 */ #define CPIA_MAX_FRAME_SIZE ((CPIA_MAX_FRAME_SIZE_UNALIGNED + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) /* align above to PAGE_SIZE */
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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/config.h>
#include <linux/version.h> #include <linux/version.h>
...@@ -34,6 +37,7 @@ ...@@ -34,6 +37,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/sched.h>
#include <linux/kmod.h> #include <linux/kmod.h>
...@@ -49,68 +53,10 @@ static int cpia_pp_streamStop(void *privdata); ...@@ -49,68 +53,10 @@ static int cpia_pp_streamStop(void *privdata);
static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock); static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock);
static int cpia_pp_close(void *privdata); static int cpia_pp_close(void *privdata);
#define ABOUT "Parallel port driver for Vision CPiA based cameras" #define ABOUT "Parallel port driver for Vision CPiA based cameras"
/* IEEE 1284 Compatiblity Mode signal names */ #define PACKET_LENGTH 8
#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 PACKET_LENGTH 8
/* Magic numbers for defining port-device mappings */ /* Magic numbers for defining port-device mappings */
#define PPCPIA_PARPORT_UNSPEC -4 #define PPCPIA_PARPORT_UNSPEC -4
...@@ -162,30 +108,7 @@ static struct cpia_camera_ops cpia_pp_ops = ...@@ -162,30 +108,7 @@ static struct cpia_camera_ops cpia_pp_ops =
}; };
static LIST_HEAD(cam_list); static LIST_HEAD(cam_list);
static spinlock_t cam_list_lock_pp = SPIN_LOCK_UNLOCKED; static spinlock_t cam_list_lock_pp;
#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
/* FIXME */ /* FIXME */
static void cpia_parport_enable_irq( struct parport *port ) { static void cpia_parport_enable_irq( struct parport *port ) {
...@@ -200,6 +123,205 @@ static void cpia_parport_disable_irq( struct parport *port ) { ...@@ -200,6 +123,205 @@ static void cpia_parport_disable_irq( struct parport *port ) {
return; 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 * EndTransferMode
...@@ -219,20 +341,25 @@ static int ForwardSetup(struct pp_cam_entry *cam) ...@@ -219,20 +341,25 @@ static int ForwardSetup(struct pp_cam_entry *cam)
{ {
int retry; int retry;
/* After some commands the camera needs extra time before /* The CPiA uses ECP protocol for Downloads from the Host to the camera.
* it will respond again, so we try up to 3 times */ * This will be software-emulated if ECP hardware is not present
for(retry=0; retry<3; ++retry) { */
/* 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)) { if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) {
break; break;
} }
mdelay(10);
} }
if(retry == 3) { if(retry == 4) {
DBG("Unable to negotiate ECP mode\n"); DBG("Unable to negotiate IEEE1284 ECP Download mode\n");
return -1; return -1;
} }
return 0; return 0;
} }
/**************************************************************************** /****************************************************************************
* *
* ReverseSetup * ReverseSetup
...@@ -241,24 +368,35 @@ static int ForwardSetup(struct pp_cam_entry *cam) ...@@ -241,24 +368,35 @@ static int ForwardSetup(struct pp_cam_entry *cam)
static int ReverseSetup(struct pp_cam_entry *cam, int extensibility) static int ReverseSetup(struct pp_cam_entry *cam, int extensibility)
{ {
int retry; int retry;
int mode = IEEE1284_MODE_ECP; int upload_mode, mode = IEEE1284_MODE_ECP;
if(extensibility) mode = 8|3|IEEE1284_EXT_LINK; 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;
/* After some commands the camera needs extra time before /* the usual camera maximum response time is 10ms, but after
* it will respond again, so we try up to 3 times */ * receiving some commands, it needs up to 40ms. */
for(retry=0; retry<3; ++retry) {
for(retry = 0; retry < 4; ++retry) {
if(!parport_negotiate(cam->port, mode)) { if(!parport_negotiate(cam->port, mode)) {
break; break;
} }
mdelay(10);
} }
if(retry == 3) { if(retry == 4) {
if(extensibility) if(extensibility)
DBG("Unable to negotiate extensibility mode\n"); DBG("Unable to negotiate upload extensibility mode\n");
else else
DBG("Unable to negotiate ECP mode\n"); DBG("Unable to negotiate upload mode\n");
return -1; return -1;
} }
if(extensibility) cam->port->ieee1284.mode = IEEE1284_MODE_ECP; if(extensibility) cam->port->ieee1284.mode = upload_mode;
return 0; return 0;
} }
...@@ -296,14 +434,21 @@ static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size) ...@@ -296,14 +434,21 @@ static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size)
static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size) static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size)
{ {
int retval=0; int retval=0;
if (packet == NULL) { if (packet == NULL) {
return -EINVAL; return -EINVAL;
} }
if (ReverseSetup(cam, 0)) { if (ReverseSetup(cam, 0)) {
return -EIO; 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); EndTransferMode(cam);
return retval; return retval;
...@@ -347,11 +492,29 @@ static int cpia_pp_streamStop(void *privdata) ...@@ -347,11 +492,29 @@ static int cpia_pp_streamStop(void *privdata)
* cpia_pp_streamRead * 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) static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
{ {
struct pp_cam_entry *cam = privdata; struct pp_cam_entry *cam = privdata;
int read_bytes = 0; int read_bytes = 0;
int i, endseen; int i, endseen, block_size, new_bytes;
if(cam == NULL) { if(cam == NULL) {
DBG("Internal driver error: cam is NULL\n"); DBG("Internal driver error: cam is NULL\n");
...@@ -380,27 +543,36 @@ static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock) ...@@ -380,27 +543,36 @@ static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
return -EIO; 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; endseen = 0;
for( i=0; i<read_bytes && endseen<4; i++ ) { block_size = PARPORT_CHUNK_SIZE;
if( *buffer==EOI ) { while( !cam->image_complete ) {
endseen++; cond_resched();
} else {
endseen=0; new_bytes = cpia_pp_read(cam->port, buffer, block_size );
} if( new_bytes <= 0 ) {
buffer++; break;
} }
if( endseen>3 ) { i=-1;
cam->image_complete=1; while(++i<new_bytes && endseen<4) {
DBG("endseen at %d bytes\n", i); 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; return cam->image_complete ? read_bytes : -EIO;
} }
/**************************************************************************** /****************************************************************************
* *
* cpia_pp_transferCmd * cpia_pp_transferCmd
...@@ -530,9 +702,8 @@ static int cpia_pp_register(struct parport *port) ...@@ -530,9 +702,8 @@ static int cpia_pp_register(struct parport *port)
struct pp_cam_entry *cam; struct pp_cam_entry *cam;
struct cam_data *cpia; struct cam_data *cpia;
if (!(port->modes & PARPORT_MODE_ECP) && if (!(port->modes & PARPORT_MODE_PCSPP)) {
!(port->modes & PARPORT_MODE_TRISTATE)) { LOG("port is not supported by CPiA driver\n");
LOG("port is not ECP capable\n");
return -ENXIO; return -ENXIO;
} }
...@@ -575,29 +746,33 @@ static int cpia_pp_register(struct parport *port) ...@@ -575,29 +746,33 @@ static int cpia_pp_register(struct parport *port)
static void cpia_pp_detach (struct parport *port) static void cpia_pp_detach (struct parport *port)
{ {
struct list_head *tmp; struct list_head *tmp;
struct cam_data *cpia; struct cam_data *cpia = NULL;
struct pp_cam_entry *cam; struct pp_cam_entry *cam;
spin_lock( &cam_list_lock_pp ); spin_lock( &cam_list_lock_pp );
list_for_each (tmp, &cam_list) { list_for_each (tmp, &cam_list) {
cpia = list_entry(tmp, struct cam_data, cam_data_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) { if (cam && cam->port->number == port->number) {
list_del(&cpia->cam_data_list); 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; break;
} }
cpia = NULL;
} }
spin_unlock( &cam_list_lock_pp ); 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) static void cpia_pp_attach (struct parport *port)
...@@ -645,11 +820,12 @@ int cpia_pp_init(void) ...@@ -645,11 +820,12 @@ int cpia_pp_init(void)
return 0; return 0;
} }
spin_lock_init( &cam_list_lock_pp );
if (parport_register_driver (&cpia_pp_driver)) { if (parport_register_driver (&cpia_pp_driver)) {
LOG ("unable to register with parport\n"); LOG ("unable to register with parport\n");
return -EIO; return -EIO;
} }
return 0; return 0;
} }
......
...@@ -21,11 +21,13 @@ ...@@ -21,11 +21,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/sched.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
...@@ -105,7 +107,7 @@ static struct cpia_camera_ops cpia_usb_ops = { ...@@ -105,7 +107,7 @@ static struct cpia_camera_ops cpia_usb_ops = {
}; };
static LIST_HEAD(cam_list); 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) static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
{ {
...@@ -464,12 +466,14 @@ static int cpia_usb_close(void *privdata) ...@@ -464,12 +466,14 @@ static int cpia_usb_close(void *privdata)
{ {
struct usb_cpia *ucpia = (struct usb_cpia *) privdata; 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) /* ucpia->present = 0 protects against trying to reset the
kfree(ucpia); * alt setting if camera is physically disconnected while open */
cpia_usb_free_resources(ucpia, ucpia->present);
return 0; return 0;
} }
...@@ -565,7 +569,7 @@ static int cpia_probe(struct usb_interface *intf, ...@@ -565,7 +569,7 @@ static int cpia_probe(struct usb_interface *intf,
vfree(ucpia->buffers[0]); vfree(ucpia->buffers[0]);
ucpia->buffers[0] = NULL; ucpia->buffers[0] = NULL;
fail_alloc_0: fail_alloc_0:
kfree(ucpia);
return -EIO; return -EIO;
} }
...@@ -588,9 +592,6 @@ static struct usb_driver cpia_driver = { ...@@ -588,9 +592,6 @@ static struct usb_driver cpia_driver = {
.id_table = cpia_id_table, .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) static void cpia_disconnect(struct usb_interface *intf)
{ {
struct cam_data *cam = usb_get_intfdata(intf); struct cam_data *cam = usb_get_intfdata(intf);
...@@ -606,12 +607,11 @@ static void cpia_disconnect(struct usb_interface *intf) ...@@ -606,12 +607,11 @@ static void cpia_disconnect(struct usb_interface *intf)
list_del(&cam->cam_data_list); list_del(&cam->cam_data_list);
spin_unlock( &cam_list_lock_usb ); 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; ucpia->present = 0;
cpia_unregister_camera(cam); cpia_unregister_camera(cam);
if(ucpia->open)
cpia_usb_close(cam->lowlevel_data);
ucpia->curbuff->status = FRAME_ERROR; ucpia->curbuff->status = FRAME_ERROR;
...@@ -639,29 +639,25 @@ static void cpia_disconnect(struct usb_interface *intf) ...@@ -639,29 +639,25 @@ static void cpia_disconnect(struct usb_interface *intf)
ucpia->buffers[0] = NULL; ucpia->buffers[0] = NULL;
} }
if (!ucpia->open) { cam->lowlevel_data = NULL;
kfree(ucpia); kfree(ucpia);
cam->lowlevel_data = NULL;
}
} }
static int __init usb_cpia_init(void) 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); return usb_register(&cpia_driver);
} }
static void __exit usb_cpia_cleanup(void) static void __exit usb_cpia_cleanup(void)
{ {
/*
struct cam_data *cam;
while ((cam = cam_list) != NULL)
cpia_disconnect(NULL, cam);
*/
usb_deregister(&cpia_driver); usb_deregister(&cpia_driver);
} }
module_init (usb_cpia_init); module_init (usb_cpia_init);
module_exit (usb_cpia_cleanup); module_exit (usb_cpia_cleanup);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment